How can I recursively Include ALL navigable properties to emulate Lazy Loading

谁说我不能喝 提交于 2019-12-01 11:25:33

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

You would use this like so:

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

If you use model-first or database-first, you could write some T4 template to generate what you need using edmx model. It is not easy, but possible.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!