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

时间:2017-06-21 17:26:04

标签: c# entity-framework-core system.reflection

我正在为EF Core项目创建通用存储库,以避免为所有模型编写CRUD。我遇到的主要障碍是没有加载导航属性,因为Core还没有支持延迟加载,而泛型类显然无法为类特定属性定义.Include语句。

我试图为我的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);
        }

但是当包含不是导航属性的属性时会抛出错误。

我发现这个答案与EF 5相同,但涉及EF核心中没有的方法:

EF5 How to get list of navigation properties for a domain object

是否有可能在EF Core中完成同样的事情?

2 个答案:

答案 0 :(得分:15)

使用EF Core中的元数据比以前的EF版本更容易。 DbContext类提供了Model属性,可以访问

  

有关实体形状,它们之间的关系以及它们如何映射到数据库的元数据。

执行所要求的代码可能是这样的:

public virtual IQueryable<T> Query(bool eager = false)
{
    var query = _context.Set<T>().AsQueryable();
    if (eager)
    {
        foreach (var property in _context.Model.FindEntityType(typeof(T)).GetNavigations())
            query = query.Include(property.Name);
    }
    return query;
}

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

请注意,尽管这符合您的要求,但它的通用方法非常有限,因为它只加载实体的直接导航属性,即不处理使用ThenInclude加载嵌套导航属性。

答案 1 :(得分:-1)

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