【问题标题】:Include all navigation properties using Reflection in generic repository using EF Core使用 EF Core 在通用存储库中包含使用反射的所有导航属性
【发布时间】:2017-06-21 17:26:04
【问题描述】:

我正在为 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 中完成同样的事情?

【问题讨论】:

  • 只是一个建议,但不是有一个用于急切加载的参数,而是一个您想要急切加载的属性的 lambda 表达式?参数之类的。表达式> 包括。
  • 我想这是一个选项,我想避免开发人员在调用 repo 时必须指定一堆东西。

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


【解决方案1】:

在 EF Core 中处理元数据比在以前的 EF 版本中要容易得多。 DbContext 类提供 Model 属性,该属性提供对

的访问

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

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

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

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

【讨论】:

  • 根据您的回答,在这部分return Query(eager).SingleOrDefault(i =&gt; i.EntityId == itemId);EntityId 指的是什么?
  • @warheat1990 这来自 OP 代码。我假设T 存在一些通用约束,例如具有Guid EntityId { get; } 属性的基类或接口。
  • 这个解决方案在早期就可以工作。迁移到 EF Core 2.1.3 后。我收到以下异常“发生了一个或多个错误。(在类型'Microsoft.EntityFrameworkCore.Query.Internal.AnonymousObject'和'YourEntity'之间没有定义强制运算符。)”有什么想法吗?
  • @Rakesh 它在 2.1.3 中仍然适用于我。您可以使用 repro 发布问题。
【解决方案2】:
    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;
    }

【讨论】:

  • 虽然此代码可以准确回答问题,但最好附上解释,以便其他用户熟悉。
猜你喜欢
  • 2020-11-10
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2015-06-05
  • 2020-01-01
  • 2023-02-10
相关资源
最近更新 更多