如何递归地包括所有可导航属性以模拟延迟加载

为了模拟延迟加载,我希望有一个方法递归地通过Eager Loading包含完整的对象图,这样在加载实体时,它的所有相关数据也会被加载。

从MSDN文档:

  • 要包含单个引用:query.Include(e => e.Level1Reference)。
  • 要包含单个集合:query.Include(e => e.Level1Collection)。
  • 要包含引用,然后引用一个级别:query.Include(e => e.Level1Reference.Level2Reference)。
  • 要包含一个引用,然后是一个级别的集合:query.Include(e => e.Level1Reference.Level2Collection)。
  • 要包含一个集合,然后向下一级引用:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference))。
  • 要包含一个集合,然后是一个级别的集合:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection))。
  • 要包含一个集合,然后向下一级引用:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference))。
  • 要包含一个集合,然后是一个级别的集合:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection))。
  • 要包含一个集合,一个引用和一个引用两个级别:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference.Level3Reference))。
  • 要包括集合,集合和引用两个级别:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection.Select(l2 => l2.Level3Reference)))。

题:

我如何递归地包含所有可导航属性并将其构建到通用存储库方法中,这样我可以在需要时获得实体的深层对象图,无论是否添加了新属性?

好的,这是一个经过编辑的版本,可以更好地满足您的要求:

private static void EnumerateAllIncludesList(DbContext context, IEnumerable entities, List entitiesLoaded = null) { if (entitiesLoaded == null) entitiesLoaded = new List(); foreach (var entity in entities) EnumerateAllIncludesEntity(context, entity, entitiesLoaded); } private static void EnumerateAllIncludesEntity(DbContext context, object entity, List entitiesLoaded) { if (entitiesLoaded.Contains(entity)) return; entitiesLoaded.Add(entity); Type type = entity.GetType(); var properties = type.GetProperties(); foreach (var propertyInfo in properties) { var propertyType = propertyInfo.PropertyType; bool isCollection = propertyType.GetInterfaces().Any(x => x == typeof(IEnumerable)) && !propertyType.Equals(typeof(string)); if (isCollection) { var entry = context.Entry(entity); if(entry.Member(propertyInfo.Name) as DbCollectionEntry == null) continue; entry.Collection(propertyInfo.Name).Load(); var propertyValue = propertyInfo.GetValue(entity); if (propertyValue == null) continue; EnumerateAllIncludesList(context, (IEnumerable)propertyValue, entitiesLoaded); } else if ((!propertyType.IsValueType && !propertyType.Equals(typeof(string)))) { var entry = context.Entry(entity); if (entry.Member(propertyInfo.Name) as DbReferenceEntry == null) continue; entry.Reference(propertyInfo.Name).Load(); var propertyValue = propertyInfo.GetValue(entity); if (propertyValue == null) continue; EnumerateAllIncludesEntity(context, propertyValue, entitiesLoaded); } else continue; } } 

你会像这样使用它:

 using (var context = new MyContext()) { var result = context.People.Where(x => x.Id == 1).ToList(); EnumerateAllIncludesList(context,result); } 

如果您使用模型优先或数据库优先,您可以编写一些T4模板以使用edmx模型生成所需内容。 这不容易,但可能。