简体   繁体   English

使用 EF Core 在通用存储库中包含使用反射的所有导航属性

[英]Include all navigation properties using Reflection in generic repository using EF Core

I'm working on creating a generic repository for an EF Core project to avoid having to write CRUD for all models.我正在为 EF Core 项目创建一个通用存储库,以避免必须为所有模型编写 CRUD。 A major roadblock I've hit is navigation properties not being loaded since Core doesn't yet support lazy loading and the generic class obviously can't define .Include statements for class specific properties.我遇到的一个主要障碍是未加载导航属性,因为 Core 尚不支持延迟加载,并且泛型类显然无法定义 .Include 类特定属性的语句。

I'm trying to do something like this for my Get method to include all the properties dynamically:我正在尝试为我的 Get 方法做这样的事情来动态包含所有属性:

public virtual T Get(Guid itemId, bool eager = false)
        {
            IQueryable<T> querySet = _context.Set<T>();

            if (eager)
            {
                foreach (PropertyInfo p in typeof(T).GetProperties())
                {
                    querySet = querySet.Include(p.Name);
                } 
            }

            return querySet.SingleOrDefault(i => i.EntityId == itemId);
        }

But it throws an error when including properties that are not navigation properties.但是当包含不是导航属性的属性时会引发错误。

I found this answer which is about the same thing but its for EF 5 and involves methods that are not present in EF core:我发现这个答案大致相同,但它适用于 EF 5,并且涉及 EF 核心中不存在的方法:

EF5 How to get list of navigation properties for a domain object EF5 如何获取域对象的导航属性列表

Is it possible to accomplish the same thing in EF Core?是否有可能在 EF Core 中完成同样的事情?

Working with metadata in EF Core is much easier than in previous EF versions.在 EF Core 中使用元数据比在以前的 EF 版本中容易得多。 The DbContext class provides Model property which provides access to DbContext类提供Model属性,该属性提供对

The metadata about the shape of entities, the relationships between them, and how they map to the database.关于实体形状、它们之间的关系以及它们如何映射到数据库的元数据。

The code which does what you ask could be like this:执行您要求的代码可能是这样的:

public virtual IQueryable<T> Query(bool eager = false)
{
    var query = _context.Set<T>().AsQueryable();
    if (eager)
    {
        var navigations = _context.Model.FindEntityType(typeof(T))
            .GetDerivedTypesInclusive()
            .SelectMany(type => type.GetNavigations())
            .Distinct();

        foreach (var property in navigations)
            query = query.Include(property.Name);
    }
    return query;
}

public virtual T Get(Guid itemId, bool eager = false)
{
    return Query(eager).SingleOrDefault(i => i.EntityId == itemId);
}

Please note that although this does what you asked for, it's quite limited generic approach since it eager loads only the direct navigation properties of the entity, ie does not handle loading nested navigation properties with ThenInclude .请注意,虽然这符合您的要求,但它是非常有限的通用方法,因为它仅急切加载实体的直接导航属性,即不使用ThenInclude处理加载嵌套导航属性。

    private List<PropertyInfo> GetNavigationProperties<T>(GesFormaContext _gesFormaContext)
    {
        List<PropertyInfo> propertyInfos = new List<PropertyInfo>();
        _gesFormaContext.Model.GetEntityTypes().Select(x => x.GetNavigations()).ToList().ForEach(entityTypes =>
        {
            entityTypes.ToList().ForEach(property =>
            {
                propertyInfos.AddRange(typeof(T).GetProperties().Where(x => x.PropertyType == property.PropertyInfo.PropertyType).ToList());
            });

        });


        return propertyInfos;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM