Entity Framework 6中是否有简便方式预加载所有依赖对象?
在Entity Framework 6中预加载多层关联对象的简便方法
嘿,针对你用EF6存储A→B→C层级结构、还要通过WCF传输的场景,预加载所有依赖对象其实有挺直接的办法,我给你梳理下:
首先,你的类结构是ClassA包含多个ClassB,每个ClassB又关联多个ClassC对吧?EF6里最常用的预加载方式就是嵌套的Include调用,分两种写法:
1. 强类型嵌套Include(推荐)
这种写法类型安全,重构代码时不容易出错,针对集合属性用Select深入加载下一层:
// 假设ClassB中对应ClassC的集合属性叫ChildClassesC var classAWithAllDependencies = dbContext.ClassAs .Include(a => a.ChildClasses.Select(b => b.ChildClassesC)) .FirstOrDefault(a => a.ClassAId == targetId);
如果层级更深(比如ClassC还有子对象),只需要继续嵌套Select就行:
.Include(a => a.ChildClasses.Select(b => b.ChildClassesC.Select(c => c.ChildClassesD)))
2. 字符串路径重载Include
如果觉得强类型写法太繁琐,也可以用字符串指定关联路径,不过这种写法在属性名变更时容易出错:
var classAWithAllDependencies = dbContext.ClassAs .Include("ChildClasses.ChildClassesC") .FirstOrDefault(a => a.ClassAId == targetId);
额外注意:适配WCF传输的细节
因为EF默认会生成延迟加载代理对象,直接传给WCF容易出问题——要么触发意外的延迟加载查询,要么因为循环引用(比如ClassB的ParentClass指向ClassA)导致序列化失败,所以要做这几点:
- 查询时关闭跟踪或禁用延迟加载:
// 方式1:查询时临时禁用跟踪,避免代理对象 var classAWithAllDependencies = dbContext.ClassAs.AsNoTracking() .Include(a => a.ChildClasses.Select(b => b.ChildClassesC)) .FirstOrDefault(a => a.ClassAId == targetId); // 方式2:全局关闭延迟加载(如果不需要延迟加载的话) dbContext.Configuration.LazyLoadingEnabled = false; - 给实体类添加序列化标记,处理循环引用:
[DataContract(IsReference = true)] public class ClassA { [DataMember] public int ClassAId { get; set; } [DataMember] public virtual ICollection<ClassB> ChildClasses { get; set; } } [DataContract(IsReference = true)] public class ClassB { [DataMember] public int ClassBId { get; set; } [DataMember] public virtual ClassA ParentClass { get; set; } [DataMember] public virtual ICollection<ClassC> ChildClassesC { get; set; } } [DataContract(IsReference = true)] public class ClassC { [DataMember] public int ClassCId { get; set; } [DataMember] public virtual ClassB ParentClass { get; set; } }
IsReference=true会让WCF识别对象引用,避免循环序列化的问题。
内容的提问来源于stack exchange,提问作者Turbofant
相关产品推荐
相关产品推荐

