我有2个实体框架查询,除了2个属性的lambda之外几乎相同; Select()
方法中的位置和日期时间。
var departQuery = _dataContext
.Job
.Where(j => j.Departure.DateTime >= startDate && j.Departure.DateTime <= endDate)
.Select(j => new DispatchDashboardItem()
{
JobId = j.Id,
Direction = "PickUp",
CustomerName = j.Driver.Name,
Vehicle = j.Vehicle,
Location = j.Departure.MeetingLocation.Name,
DateTime = j.Departure.DateTime,
});
var returnQuery = _dataContext
.Job
.Where(j => j.Return.DateTime >= startDate && j.Return.DateTime <= endDate)
.Select(j => new DispatchDashboardItem()
{
JobId = j.Id,
Direction = "DropOff",
CustomerName = j.Driver.Name,
Vehicle = j.Vehicle,
Location = j.Return.MeetingLocation.Name,
DateTime = j.Return.DateTime,
});
我尝试创建一个扩展方法来共享没有func参数的select,但是抛出异常然后我使用location param:
public static IQueryable<DashboardItem> SelectDashboardItem(this IQueryable<Job> query,
string direction,
Func<Job, MeetingDetail> location)
{
return query
.Select(j => new DashboardItem()
{
JobId = j.Id,
Direction = direction,
CustomerName = j.Driver.Name,
Vehicle = j.Vehicle,
// This works without using the func
Location = location(j).MeetingLocation.Name,
DateTime = location(j).DateTime,
});
}
我看到了他的错误信息:
LINQ表达式节点类型&#39;调用&#39; LINQ to Entities不支持。
答案 0 :(得分:1)
将此语法与let语句一起使用,以便一举实现合成。您需要一个基类或更好的接口,以实现您的出发和返回实体之间的通用性。
var query = from job in _dataContext.Job
let departureOrReturn = (direction == "PickUp" ? job.Departure : job.Return) as BaseReturnOrDeparture
where (departureOrReturn.DateTime >= startDate && departureOrReturn.DateTime <= endDate)
select new DispatchDashboardItem
{
JobId = job.Id,
Direction = direction,
CustomerName = job.Driver.Name,
Vehicle = job.Vehicle,
Location = deptartureOrReturn.MeetingLocation.Name,
DateTime = deptartureOrReturn.DateTime,
};
答案 1 :(得分:0)
而不是使用Func
作为参数使用Expression
。传递您用作参数的相同lambda表达式,它将被隐式转换。现在要实现您的需求,您需要使用LinqKit库:
public static IQueryable<DashboardItem> SelectDashboardItem(this IQueryable<Job> query,
string direction,
Expression<Func<Job, MeetingDetail>> location)
{
return query.AsExpandable()
.Select(j => new DashboardItem()
{
JobId = j.Id,
Direction = direction,
CustomerName = j.Driver.Name,
Vehicle = j.Vehicle,
// This works without using the func
Location = location.Invoke(j).MeetingLocation.Name,
DateTime = location.Invoke(j).DateTime,
});
}
ToExpandable
在DLINQ Table对象周围创建一个瘦包装器。感谢这个包装器,您可以使用名为Invoke
的第二个方法扩展Expression
类以调用lambda表达式,同时仍然可以将查询转换为T-SQL。这是有效的,因为在转换为表达式树时,包装器会将所有出现的Invoke
方法替换为调用的lambda表达式的表达式树,并将这些表达式传递给能够将扩展查询转换为T-SQL的DLINQ。 / p>