.ThenInclude 用于 Entity Framework Core 2 中的子实体

Mat*_*ynn 2 c# entity-framework-core

以前(使用 .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);
    }
Run Code Online (Sandbox Code Playgroud)

例如,我会打电话;

context.Get<Job>(id, 
    x => x.Equipment,
    x => x.Equipment.Select(y => y.Type));
Run Code Online (Sandbox Code Playgroud)

包括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<T>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);
    }
Run Code Online (Sandbox Code Playgroud)

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

Iva*_*oev 5

EF Core Include/ThenInclude模式不能用Expression<Func<T, object>>[]EF6 中的like表示。

查看 EF Core 扩展之一的源代码 - Microsoft.EntityFrameworkCore.UnitOfWork,它声称是

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

看起来包含的预期模式应该基于Func<IQueryable<T>, IIncludableQueryable<T, object>>

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);
}
Run Code Online (Sandbox Code Playgroud)

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

您的示例的用法是:

context.Get<Job>(id, q => q
    .Include(x => x.Equipment)
        .ThenInclude(y => y.Type));
Run Code Online (Sandbox Code Playgroud)