使用Reflection在EF Core的通用存储库中包含所有导航属性 [英] Include all navigation properties using Reflection in generic repository using EF Core

查看:149
本文介绍了使用Reflection在EF Core的通用存储库中包含所有导航属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为EF Core项目创建通用存储库,以避免必须为所有模型编写CRUD。我遇到的主要障碍是导航属性未加载,因为Core尚不支持延迟加载,并且泛型类显然无法定义.include声明,用于类的特定属性。



我正在尝试为我的Get方法做​​这样的事情以动态地包含所有属性:

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

如果(急切)
{
foreach(typeof(T).GetProperties()中的PropertyInfo p)
{
querySet = querySet.Include( p.Name);
}
}

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

但是,当包含非导航属性时,会引发错误。 p>

我发现这个答案大致相同,但它适用于EF 5,并且涉及EF核心中不存在的方法:



EF5如何获取域对象的导航属性列表



是否可以在EF Core中完成相同的操作?

解决方案

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


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


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

 公共虚拟IQueryable< T>查询(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属性)
query = query.Include(property.Name);
}
返回查询;
}

公共虚拟T Get(Guid itemId,bool eager = false)
{
return Query(eager).SingleOrDefault(i => i.EntityId == itemId);
}

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


I'm working on creating a generic repository for an EF Core project to avoid having to write CRUD for all models. 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.

I'm trying to do something like this for my Get method to include all the properties dynamically:

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:

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

Is it possible to accomplish the same thing in EF Core?

解决方案

Working with metadata in EF Core is much easier than in previous EF versions. The DbContext class provides Model property which provides access to

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, i.e. does not handle loading nested navigation properties with ThenInclude.

这篇关于使用Reflection在EF Core的通用存储库中包含所有导航属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆