所以我目前正在将我们的代码库从EF 6迁移到EF core 2.0,我只是遇到了一些Expressions的问题。
所以我们有一些常见的过滤器,我们已经将它抽象出一个表达式。
public static Expression<Func<AutotaskContractServiceUnit, bool>> ThisMonth()
{
var startDate = Clock.Now.Start();
var endDate = Clock.Now.End();
return csu => csu.StartDate.Date >= startDate.Date && csu.EndDate.Date <= endDate.Date;
}
这将消耗如下
return from vc in ContractRepository.GetAll()
let isAssigned = vc.AssetId != null
join v in _veeamRepository.GetAll() on vc.AssetId equals v.Id into veeams
from v in veeams.DefaultIfEmpty()
join ac in AutotaskContractRepository.GetAll() on vc.ContractId equals ac.Id
join ats in AutotaskServiceRepository.GetAll() on vc.ServiceId equals ats.Id
let billed = ac.ContractServiceUnits // navigation property
.AsQueryable()
.Where(AutotaskContractServiceUnitFilters.ThisMonth())
.Where(csu => csu.ServiceID == vc.ServiceId)
.OrderByDescending(csu => csu.Id)
.FirstOrDefault()
select new VeeamBillingModel
{
// property selection
};
实际问题在于查询的这一部分
let billed = ac.ContractServiceUnits
.AsQueryable()
.Where(AutotaskContractServiceUnitFilters.ThisMonth())
.Where(csu => csu.ServiceID == vc.ServiceId)
.OrderByDescending(csu => csu.Id)
.FirstOrDefault()
因为我得到了这个例外
无法解析表达式'&lt;&gt; h__TransparentIdentifier4。&lt;&gt; h__TransparentIdentifier3.ac.ContractServiceUnits.AsQueryable()':目前不支持方法'System.Linq.Queryable.AsQueryable'的重载。
所以我的问题是,如何在EF Core中实现相同的结果?
我尝试过的事情
删除AsQueryable()。这个问题是编译器然后抱怨它无法转换表达式&lt;&gt;到Func&lt;&gt;
Argument 2: cannot convert from 'System.Linq.Expressions.Expression<System.Func<Portal.Autotask.ContractServiceUnit.Entities.AutotaskContractServiceUnit, bool>>' to 'System.Func<Portal.Autotask.ContractServiceUnit.Entities.AutotaskContractServiceUnit, bool>'
更改表达式&lt;&gt;到一个Func&lt;&gt;编译得很好,但是一旦它尝试执行查询就会引发异常,因为它不是表达式&lt;&gt;。
我也试过LinqKit(简单地说)但是无法让它运转起来。我认为因为来自连接表的.AsExpandable()无法正常工作。
我设法使其工作的唯一方法是手动将表达式放在.Where子句中。
let billed = ac.ContractServiceUnits
.Where(x => x.StartDate.Date >= start.Date && x.EndDate <= end.Date)
.Where(csu => csu.ServiceID == vc.ServiceId)
.OrderByDescending(csu => csu.Id)
.FirstOrDefault()
但这不是一个好的解决方案,因为我们有其他表达式,查询逻辑可以更改并手动更新所有查询太耗时。
如果有人能对此有所了解,那将是王牌, 干杯!