gpt4 book ai didi

c# - 在 LINQ to Entities 中重用选择表达式

转载 作者:太空宇宙 更新时间:2023-11-03 16:59:35 24 4
gpt4 key购买 nike

我有一些复杂的业务定义,我想定义一次并在 Linq to Entities 中重用它们,并在基于它构建的其他表达式中使用它们。

下面是我的尝试,当我最初通过 ConvertOrderDetailsToViewModel 时,它起作用了一个List ,但我想在 IQueryable 上执行此操作,这会导致错误:

LINQ to Entities does not recognize the method 'System.Decimal Invoke(OrderDetail)' method, and this method cannot be translated into a store expression.

有没有办法在本地实现这一点(没有第 3 方库)?看起来像来自 this answer ,您可以在数据库本身中定义这些函数,然后从 C# 中调用它们,但同样,如果可能,希望仅在 C# 代码中执行此操作。

也遇到了this answer看起来它适用于 Where表达式,但是当我尝试为我的 select 实现它时表达式,我得到了这个错误,我得到了,因为我试图将表达式分配给小数。

Cannot implicitly convert type Expression<Func<OrderDetail, decimal>> to 'decimal'

这是表达式函数:

public static Expression<Func<OrderDetail, decimal>> calcQtyNeedOD = (od) => (od.OrderedQuantity - od.PickedQuantity); 

调用该函数的 View 模型创建方法:

public List<AllocationNeedViewModel> ConvertOrderDetailsToViewModel(IQueryable<OrderDetail> qryShipOrderDtls, List<int> itemIdsToExclude, bool boolGroupViewModelByItemAndRemnant)
{
var qryAllocNeedVMTEST =
from od in qryShipOrderDtls
select new AllocationNeedViewModel()
{
WorkReleaseHeaderId = od.OrderHeader.WorkReleaseHeaderId.Value,
OrderHeaderId = od.OrderHeaderId,
OrderDetailId = od.Id,
ItemId = od.ItemId.Value,
ItemDescription = od.Item.Description,
IsInventoryTracked = od.Item.TrackInventory,
QtyNeed = calcQtyNeedOD(od),
QtyRemain = 0,
QtyAllocated = 0,
IsAllocated = false
}
;
return qryAllocNeedVMTEST.ToList();
}

为了使这个更复杂,还有其他属性我也希望有一个可重用的表达式,它们也将使用第一个表达式......即

public static readonly Expression<Func<OrderDetail, decimal>> calcQtyRemainOD =
(od) => calcQtyNeedOD.Compile().Invoke(od) - calcQtyAllocatedOD.Compile().Invoke(od);

更新 #1

查看更新 #2...此解决方案无效!

虽然到目前为止还没有人能够提供一种本地方法来 查询重用选择表达式,但我确实找到了一种部分解决方案,可以在 重用它们em> 相同的查询。一旦您将表达式转换/分配给实体的属性,您就可以(与 T-SQL 不同)然后将该属性指定为另一个后续属性表达式的一部分。

示例 - 这显示了每个属性投影的完整表达式。在这个例子中,QtyRemain本质上只是 QtyNeed - QtyAllocated .我在 QtyRemain 中再次指定了那些作业:

public List<AllocationNeedViewModel> ConvertOrderDetailsToViewModel(IQueryable<OrderDetail> qryShipOrderDtls, List<int> itemIdsToExclude, bool boolGroupViewModelByItemAndRemnant)
{
var qryAllocNeedVM = qryShipOrderDtls
.Select(od => new AllocationNeedViewModel() //Get all Work Order Detail Needs for Work Release
{
QtyNeed = (od.OrderedQuantity - od.PickedQuantity),
QtyAllocated = (od.AllocatedInventories.Count == 0 ? 0 : od.AllocatedInventories.Where(ai => ai.StatusId < _AllocatedInventoryProcessedStatus).Sum(ai => ai.AllocatedQty)),
QtyRemain = (od.OrderedQuantity - od.PickedQuantity) - (od.AllocatedInventories.Count == 0 ? 0 : od.AllocatedInventories.Where(ai => ai.StatusId < _AllocatedInventoryProcessedStatus).Sum(ai => ai.AllocatedQty))
}
);
return qryAllocNeedVM.ToList();
}

相反,您可以简单地使用 QtyRemain 中已经定义的属性属性分配,像这样:

public List<AllocationNeedViewModel> ConvertOrderDetailsToViewModel(IQueryable<OrderDetail> qryShipOrderDtls, List<int> itemIdsToExclude, bool boolGroupViewModelByItemAndRemnant)
{
var qryAllocNeedVM = qryShipOrderDtls
.Select(od => new AllocationNeedViewModel() //Get all Work Order Detail Needs for Work Release
{
QtyNeed = (od.OrderedQuantity - od.PickedQuantity),
QtyAllocated = (od.AllocatedInventories.Count == 0 ? 0 : od.AllocatedInventories.Where(ai => ai.StatusId < _AllocatedInventoryProcessedStatus).Sum(ai => ai.AllocatedQty)),
QtyRemain = this.QtyNeed - this.QtyAllocated
}
);
return qryAllocNeedVM.ToList();
}

虽然这不是我最初问题的完整解决方案,但它是一个部分解决方案,可以为您带来一些所需的好处。

更新#2

我在更新 #1 上错了。尽管这可以编译并生成 SQL,但它是不正确的。 this.QtyNeed的返回值在后续表达式中使用时,结果始终为 0 . :(

最佳答案

您是否考虑过以下问题?

public static Func<OrderDetail, decimal> calcQtyNeedOD = (od) => (od.OrderedQuantity - od.PickedQuantity);

public List<AllocationNeedViewModel> ConvertOrderDetailsToViewModel(IQueryable<OrderDetail> qryShipOrderDtls, List<int> itemIdsToExclude, bool boolGroupViewModelByItemAndRemnant)
{
return qryShipOrderDtls
.ToArray()
.Select(new AllocationNeedViewModel
{
WorkReleaseHeaderId = od.OrderHeader.WorkReleaseHeaderId.Value,
OrderHeaderId = od.OrderHeaderId,
OrderDetailId = od.Id,
ItemId = od.ItemId.Value,
ItemDescription = od.Item.Description,
IsInventoryTracked = od.Item.TrackInventory,
QtyNeed = calcQtyNeedOD(od),
QtyRemain = 0,
QtyAllocated = 0,
IsAllocated = false
}).ToList();
}

原始查询试图对实际数据库执行 Func(它不会理解您的表达式)。由于您没有过滤查询(没有 where 子句),因此返回整个集合,以便您可以使用本地 Func 进行投影。

关于c# - 在 LINQ to Entities 中重用选择表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46162210/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com