.net core EF Core 3在使用.AsExpandable()时存在.Include()问题

.net core EF Core 3在使用.AsExpandable()时存在.Include()问题,.net-core,entity-framework-core,c#-3.0,.net Core,Entity Framework Core,C# 3.0,我已经从我见过的几个CQRS框架中迁移了概念,并且刚刚开始面临一些问题 我有一个通用的EntityDbContext子类,我在任何消费项目中都使用它,不需要进一步扩展以适应应用程序的域,而是提供接口、IReadEntities和IWriteEntities,它们具有类似Query()和Get()的方法,这些方法在后台调用Set(),返回DbSet()然后允许将标准LINQ表达式链接到任何EF查询上。我在iQueryTables上使用Include()时遇到了一些问题,因为我在所有调用结束时将Li

我已经从我见过的几个CQRS框架中迁移了概念,并且刚刚开始面临一些问题

我有一个通用的EntityDbContext子类,我在任何消费项目中都使用它,不需要进一步扩展以适应应用程序的域,而是提供接口、IReadEntities和IWriteEntities,它们具有类似Query()和Get()的方法,这些方法在后台调用Set(),返回DbSet()然后允许将标准LINQ表达式链接到任何EF查询上。我在iQueryTables上使用Include()时遇到了一些问题,因为我在所有调用结束时将LinqKit与AsExpandable()一起使用。这就是我的上下文查询方法的样子

public new IQueryable<TEntity> Query<TEntity>() where TEntity : class, IEntity
{
    // AsNoTracking returns entities that are not attached to the DbContext
    return QueryUnfiltered<TEntity>().Where(_recordAuthority.Clause<TEntity>());
}

public IQueryable<TEntity> QueryUnfiltered<TEntity>() where TEntity : class, IEntity
{
    // AsNoTracking returns entities that are not attached to the DbContext
    return Set<TEntity>().AsNoTracking().AsExpandable();
}
public new IQueryable Query(),其中tenty:class,ienty
{
//AsNoTracking返回未附加到DbContext的实体
返回QueryUnfiltered().Where(_recordAuthority.子句());
}
public IQueryable QueryUnfiltered(),其中tenty:class,ienty
{
//AsNoTracking返回未附加到DbContext的实体
返回集().AsNoTracking().AsExpandable();
}
典型的查询处理程序如下所示:

public async Task<IEnumerable<GetCustomerView>> Handle(CustomersBy query, CancellationToken cancellationToken)
{
    var customers = _db.Query<Customer>();

    // Apply filters
    if (!string.IsNullOrEmpty(query.FirstName))
        customers = customers.Where(x => x.FirstName.Contains(query.FirstName));

    if (!string.IsNullOrEmpty(query.LastName))
        customers = customers.Where(x => x.LastName.Contains(query.LastName));

    // Execute the query and return the results
    var view = await customers.Select(x => new GetCustomerView
    {
        Id = x.Id,
        FirstName = x.FirstName,
        LastName = x.LastName,
        EmailAddress = x.EmailAddress
    }).ToListAsync(cancellationToken).ConfigureAwait(false) as IEnumerable<GetCustomerView>;

    return view;
}
公共异步任务句柄(CustomersBy查询、CancellationToken CancellationToken)
{
var customers=_db.Query();
//应用过滤器
如果(!string.IsNullOrEmpty(query.FirstName))
customers=customers.Where(x=>x.FirstName.Contains(query.FirstName));
如果(!string.IsNullOrEmpty(query.LastName))
customers=customers.Where(x=>x.LastName.Contains(query.LastName));
//执行查询并返回结果
var view=等待客户。选择(x=>newgetcustomerview
{
Id=x.Id,
FirstName=x.FirstName,
LastName=x.LastName,
EmailAddress=x.EmailAddress
}).ToListSync(cancellationToken)。将等待(false)配置为IEnumerable;
返回视图;
}
如果我想在使用数据库服务上的投影时从相关表中提取地址详细信息,并且在执行之前使用Select,那么这个场景可以很好地工作。尽管在某些情况下,将对象图拉回来并指定Include(…)语句是有意义的,但目前指定
\u db.Query().Include(c=>c.Address)
并不会影响地址导航属性。我尝试过关闭AsExpandable(),然后返回结果

问题是,是否有人看到了一种方法,可以将Include语句作为参数提供给该方法,然后在调用AsExpandable()之前,我循环使用它们并将其固定?如果可能的话,我不知道该怎么做

也许还有别的办法


有趣的是,这显然适用于同事使用EF6的模式版本。他说,他们在AsExpandable之后指定Include是没有问题的。

这是EF Core和LinqKit
AsExpandable的已知问题(一般来说,任何使用自定义
IQueryProvider
执行查询表达式树预处理的扩展库,如LinqKit),由于EF Core忽略所有EF Core特定的
IQueryable
扩展(
Include
/
thenclude
AsNoTracking
等),因此查询提供程序与EF Core提供程序不同(或不继承)(EF6没有此类要求)


话虽如此,目前除了在调用
AsExpandable

Ok之前应用所有EF核心特定扩展之外,没有其他解决方案。我创建了一个重载:

public IQueryable<TEntity> Query<TEntity, TProperty>(IEnumerable<Expression<Func<TEntity, TProperty>>> includes) where TEntity : class, IEntity
{
    var query = Set<TEntity>().AsNoTracking();

    foreach (var expression in includes)
    {
        query = query.Include(expression);
    }

    return query.AsExpandable();
}
publicIQueryable查询(IEnumerable包含),其中tenty:class,ienty
{
var query=Set().AsNoTracking();
foreach(includes中的var表达式)
{
query=query.Include(表达式);
}
返回query.AsExpandable();
}
从我的处理程序中,我创建一个包含表达式的列表,并传递到查询:

var includes = new List<Expression<Func<Customer, object>>>
{
    c => c.Address
};

var customers = _db.Query(includes);
var result = await customers.ToListAsync(cancellationToken).ConfigureAwait(false);
var includes=新列表
{
c=>c.地址
};
var客户=_db.Query(包括);
var结果=等待客户。ToListSync(取消令牌)。ConfigureWait(错误);
执行查询时已填充导航属性:

这意味着我没有从客户机代码的角度“流畅地”链接它们,但我认为这并不可怕


想法?

很酷,谢谢你提供的细节。不过,我感兴趣的是,在给定查询方法的情况下,如何在AsExpandable之前注入Include。我在想,我可以使用一个参数,它是一个包含列表,或者是它们分解成的任何东西,可能是
IQueryable查询(表达式包含),其中tenty:class,ienty
,然后循环并附加Include语句。我开始做这件事,但不确定兰姆达要做什么<代码>表达式blah=(c,a)=>c.地址似乎没有编译哦,我很傻这是正确的
表达式blah=c=>c.Address
如果您不需要
然后include
参数表达式[]include
将像EF6一样工作。否则,您需要类似于
Func includes=null的内容。你可以在其他答案中找到这一点,包括我的答案。