我怎么可以递归包括所有通航特性来模拟延迟加载(How can I recursively Inclu

2019-07-22 11:23发布

要模拟延迟加载,我想有一个递归包含的,这样在加载实体,与其相关的全部数据的加载以及通过预先加载完整的对象图的方法。

从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)))。

题:

我怎么可以递归包括所有通航特性构筑成一个通用存储库法这一点,以便在需要时,无论是否加入新的属性,我可以得到一个实体的深对象图?

Answer 1:

好吧,这是一个应该满足您的要求好一点的编辑版本:

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);
}


Answer 2:

如果你使用模型的第一或数据库第一,你可以写一些T4模板来生成你需要使用EDMX模型是什么。 这是不容易的,但可能的。



文章来源: How can I recursively Include ALL navigable properties to emulate Lazy Loading