【问题标题】:.ThenInclude for sub entity in Entity Framework Core 2.ThenInclude 用于 Entity Framework Core 2 中的子实体
【发布时间】:2018-10-12 18:03:07
【问题描述】:

以前(使用 .net 4.5.2 和 EF 6 时)。我有一个通用的Get 方法,它接受了如下的一些包含;

public abstract class DataContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDataContext
{
    public DataContext(DbContextOptions options)
    : base(options)
    {
    }

    // reduced for brevity

    public T Get<T>(int id, params Expression<Func<T, object>>[] includes) where T : class, IEntity
    {
        return this.Set<T>().Include(includes).FirstOrDefault(x => x.Id == id);
    }

然后我会打电话给例如;

context.Get<Job>(id, 
    x => x.Equipment,
    x => x.Equipment.Select(y => y.Type));

包括Job.EquipmentJob.Equipment.Type

但是,当我将其移植到 asp.net core 2 时。我尝试了相同的通用方法,但如果我尝试包含子实体,则会收到以下错误;

属性表达式“x => {from Equipment y in x.Equipment select [y].Type}”无效。该表达式应表示属性访问:'t => t.MyProperty'。有关包含相关数据的更多信息,请参阅http://go.microsoft.com/fwlink/?LinkID=746393

谁能建议我如何解决这个问题,以便在我的通用 Get&lt;T&gt; 方法中包含子实体和 Entity Framework Core 2?

更新

通过查看文档,还有一个额外的包含方法

include(string navigationPropertyPath)

我添加了以下方法;

    public T Get<T>(int id, string[] includes) where T : class, IEntity
    {
        var result = this.Set<T>().AsQueryable();

        foreach(var include in includes)
        {
            result = result.Include(include);
        }

        return result.FirstOrDefault(x => x.Id == id);
    }

虽然我不相信这里的效率,但哪个有效?

【问题讨论】:

  • 在 Entity Framework Core 中没有接受 Expression&lt;Func&lt;T, object&gt;&gt;[]Include 重载,还是您在 EF6 中使用它的方式?
  • .Include 工作正常,但似乎选择子实体在核心 2 中发生了变化? (以前运行良好的代码不起作用)。我还找到了链接docs.microsoft.com/en-us/ef/core/querying/related-data,这似乎暗示了.ThenInclude
  • 是的,您需要使用ThenInclude,但您的代码甚至无法在 EF Core 2 上为我编译
  • 奇怪的是它对我来说编译没问题。我编辑以包含我的DbContext 扩展名。我注意到有一个Include(string navigationPropertyPath) 可以完成这项工作。我会对此进行测试并更新我的结果。
  • 另一种解决方案是将 lambda 表达式转换为字符串形式的路径:stackoverflow.com/a/47063432/861716

标签: c# entity-framework-core


【解决方案1】:

EF Core Include / ThenInclude 模式不能像 EF6 中那样由 Expression&lt;Func&lt;T, object&gt;&gt;[] 表示。

查看EF Core扩展之一的源代码——Microsoft.EntityFrameworkCore.UnitOfWork,号称是

Microsoft.EntityFrameworkCore 的插件,用于支持存储库、工作单元模式和支持分布式事务的多个数据库。

看起来包含的预期模式应该基于Func&lt;IQueryable&lt;T&gt;, IIncludableQueryable&lt;T, object&gt;&gt;

public T Get<T>(int id, Func<IQueryable<T>, IIncludableQueryable<T, object>> include = null) where T : class, IEntity
{
    var result = this.Set<T>().AsQueryable();

    if (include != null)
        result = include(result);

    return result.FirstOrDefault(x => x.Id == id);
}

缺点是它增加了对调用者的 EF Core 依赖,并且需要using Microsoft.EntityFrameworkCore;。在您的情况下这不是必需的,因为您正在扩展 DbContext

你的例子的用法是:

context.Get<Job>(id, q => q
    .Include(x => x.Equipment)
        .ThenInclude(y => y.Type));

【讨论】:

  • 这是否允许多个包含?例如,如果我需要在退货中包含多个复杂实体?与 EF6 一样,我可以简单地链接包含以撤回我需要的内容?
  • 是的,确实如此。在 EF Core 中,您将链接多个 Include / ThenInclude。每个Include 都从根目录重新启动。示例here 和文档中。
  • 你认为如何使这个动态化?我想在 BaseRepository 中有这个,它是一些存储库的基类,我不会为每个 repo 编写所有实现,但我找不到使 thenInclude 动态的方法,有什么建议吗?
  • @RSadocchi 不确定您所说的“制作动态”是什么意思,也许您可​​以举个例子。在上面的示例(和链接)中,Include / ThenInclude 由 repo 方法的 caller 外部提供。
  • @IvanStoev 感谢您的回答,请查看stackoverflow.com/questions/55898559/… 获取代码示例
【解决方案2】:

你可以这样做:

   public abstract class DataContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>, IDataContext
    {
        public DataContext(DbContextOptions options)
        : base(options)
        {
        }

        // reduced for brevity

        public T Get<T>(int id, Func<IQueryable<T>, IIncludableQueryable<T, object>> includes = null) where T : class, IEntity
        {
            IQueryable<T> queryable = this.Set<T>();

            if (includes != null)
            {
                queryable = includes(queryable);
            }

            return queryable.FirstOrDefault(x => x.Id == id);
        }
    }

   context.Get<Job>(id, includes: source => source.Include(x => x.Equipment).ThenInclude(x => x.Type));

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 2020-02-06
    • 2022-01-17
    • 2019-07-31
    • 2018-08-09
    • 2017-05-05
    • 2017-06-13
    • 2022-01-19
    相关资源
    最近更新 更多