3

UsergroupUsers我曾经自己在 POCO 中为多对多关系或关系 ID生成所有辅助表,但现在我希望 EF 处理它们。现在我认为这毕竟不是一个好主意。

问题

当我尝试UsergroupDynamicField为特定用户获取所有信息时,它会N+1为每个用户组用户生成查询。

在这里,我通过简单地说明UsergroupsIQUeriable代替IEnumerable. 现在我不能这样做,因为 EF 不会映射它,它必须是ICollection.

代码

public class User
{
    ...
    public virtual ICollection<Usergroup> Usergroups { get; set; }
    public IEnumerable<UserField> Fields
    {
        get
        {
            var fields = this.Usergroups.SelectMany(x => x.UsergroupDynamicFields); // N + 1 for every Usergroup

            foreach (var field in fields)
            {
                yield return new UserField
                {
                    Name = field.Name
                };
            }
        }
    }
}

数据库

D B DB2

4

2 回答 2

1

在这里,我通过简单地说明用户组将是 IQUeriable 而不是 IEnumerable 来克服这个问题。现在我不能这样做,因为 EF 不会映射它,它必须是 ICollection。

但最终实现的类ICollectionEntityCollection<T>. 此集合具有您可以使用的CreateSourceQuery()功能

var usergroupsQuery = ((EntityCollection<UserGroup>)this.Usergroups).CreateSourceQuery();
var fields = usergroupsQuery.SelectMany(x => x.UsergroupDynamicFields);

更新:正如评论中所指出的,只有在更改跟踪可能并启用(非密封类和所有相关属性)时ICollection<T>才会使用。您可以通过另一种方式创建查询:EntityCollection<T>virtual

var usergroupsQuery = db.Entry(this).Collection(u => u.Usergroups).Query();
var fields = usergroupsQuery.SelectMany(x => x.UsergroupDynamicFields);

请注意,这需要您以db某种方式访问​​。

于 2013-07-25T14:24:27.880 回答
0

我尝试使用类似的东西

var res = c.Users.Include("Groups.DynFields").First().Groups.SelectMany(x => x.DynFields).ToList();

它似乎没问题。我使用EF5。

当然......这不是 User 类中的方法。它需要能够在 DbSet 对象上调用 Include 方法。

我希望这可能会有所帮助。

完整的解决方案

 public class User {
        public Int32 Id { get; set; }
        public String Name { get; set; }

        public virtual ICollection<UserGroup> Groups { get; set; }
    }

    public class UserGroup {
        public Int32 Id { get; set; }
        public String Name { get; set; }

        public virtual ICollection<User> Users { get; set; }

        public virtual ICollection<UserGroupDynamicField> DynFields { get; set; }
    }

    public class UserGroupDynamicField {
        public Int32 Id { get; set; }
        public String Name { get; set; }
        public virtual UserGroup Group { get; set; }
    }


    public class UserGroupDynFEFCFConfiguration : EntityTypeConfiguration<UserGroupDynamicField > {
        public UserGroupDynFEFCFConfiguration()
            : base() {
                HasRequired(x => x.Group);
        }
    }

    public class UserGroupEFCFConfiguration : EntityTypeConfiguration<UserGroup> {
        public UserGroupEFCFConfiguration()
            : base() {
                HasMany(x => x.Users).WithMany(y => y.Groups);
        }
    }       

    public class TestEFContext : DbContext {
        public IDbSet<User> Users { get; set; }
        public IDbSet<UserGroup> Groups { get; set; }

        public TestEFContext(String cs)
            : base(cs) {
            Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder) {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Configurations.Add(new UserGroupDynFEFCFConfiguration());
            modelBuilder.Configurations.Add(new UserGroupEFCFConfiguration());
        }
    }

    class Program {
        static void Main(String[] args) {
            String cs = @"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";

            using (TestEFContext c = new TestEFContext(cs)) {
                UserGroup g1 = new UserGroup {
                    Name = "G1",
                    DynFields = new List<UserGroupDynamicField> { 
                        new UserGroupDynamicField { Name = "DF11"},
                        new UserGroupDynamicField { Name = "DF12"}
                    }
                };
                c.Groups.Add(g1);

                UserGroup g2 = new UserGroup {
                    Name = "G2",
                    DynFields = new List<UserGroupDynamicField> { 
                        new UserGroupDynamicField { Name = "DF21"},
                        new UserGroupDynamicField { Name = "DF22"}
                    }
                };
                c.Groups.Add(g2);

                c.Users.Add(new User {
                    Name = "U1",
                    Groups = new List<UserGroup> { g1, g2 }
                });

                c.SaveChanges();
            }      

            using (TestEFContext c = new TestEFContext(cs)) {
                var res = c.Users.Include("Groups.DynFields").First().Groups.SelectMany(x => x.DynFields).ToList();
                foreach (var v in res) {
                    Console.WriteLine(v.Name);
                } 
            }
        }
    }
于 2013-07-25T13:51:48.580 回答