本文介绍了如何递归包含所有可导航属性以模拟延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要模拟延迟加载,我想有一种方法,可以通过Eager Loading递归地包含完整的对象图,以便在加载实体时也加载其所有相关数据。

To emulate Lazy Loading, I would like to have a method that recursively Include's the complete object graph via Eager Loading so that upon loading the entity, all of its related data is loaded as well.

来自MSDN文档:


  • 包括单个引用:query.Include(e => e.Level1Reference)

  • 要包含一个集合:query.Include(e => e.Level1Collection)。

  • 要包含一个引用,然后再包含一个引用

  • 要包括一个引用,然后是一个集合,则下一级:query.Include(e => e.Level1Reference)。 .level2Collection)。

  • 要包含一个集合,然后向下一级引用:query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference))。 / li>
  • 先包含一个集合,然后再向下一层收集: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))))。

  • To include a single reference: query.Include(e => e.Level1Reference).
  • To include a single collection: query.Include(e => e.Level1Collection).
  • To include a reference and then a reference one level down: query.Include(e => e.Level1Reference.Level2Reference).
  • To include a reference and then a collection one level down: query.Include(e => e.Level1Reference.Level2Collection).
  • To include a collection and then a reference one level down: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference)).
  • To include a collection and then a collection one level down: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection)).
  • To include a collection and then a reference one level down: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference)).
  • To include a collection and then a collection one level down: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection)).
  • To include a collection, a reference, and a reference two levels down: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Reference.Level3Reference)).
  • To include a collection, a collection, and a reference two levels down: query.Include(e => e.Level1Collection.Select(l1 => l1.Level2Collection.Select(l2 => l2.Level3Reference))).

问题:

我如何递归包括所有可导航属性并将其构建为通用存储库方法,以便我可以

How can I recursively Include ALL navigable properties and build this into a generic repository method so that I can get a deep object graph of an entity whenever required, regardless if new properties were added?

推荐答案

好,这是一个经修改的版本n应该可以更好地满足您的要求:

Ok, this is an edited version that should meet your requirements a little better:

private static void EnumerateAllIncludesList(DbContext context, IEnumerable entities, List<object> entitiesLoaded = null)
{
    if (entitiesLoaded == null)
        entitiesLoaded = new List<object>();

    foreach (var entity in entities)
        EnumerateAllIncludesEntity(context, entity, entitiesLoaded);

}

private static void EnumerateAllIncludesEntity(DbContext context, object entity, List<object> 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);
}

这篇关于如何递归包含所有可导航属性以模拟延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 16:02