所以我在Linq-To-Entities与asp.net mvc项目
我总是被这类问题难住了。
我的schema是:
ProductTag
+TagName
+<<ProductNames>>//Many-to-many relationship
ProductName
+FullName
+<<Tag>>//Many-to-many relationship
PurchaseRecord
+Amount
+<<ProductName>>//one productname can be linked to Many purchase records.
我需要得到一个给定标签的所有购买的总和。
这是我试过的。
ProductTag thetag//could be some tag
decimal total = myentities.PurchaseRecords
.Where(x => thetag.ProductNames.Any
(a => a.FullName == x.ProductName.FullName))
.Sum(s => s.Amount);
我试过改变一些事情,试过使用Contains
,但我知道我在某个地方根本错了。
我一直得到:
无法创建类型为"ProductName"的常量值。在此上下文中只支持基本类型('如Int32, String和Guid')。
所以在@Alexandre Brisebois的帮助下,它的工作原理是这样的:
var total= item.ProductNames.SelectMany(x => x.PurchaseRecords)
.Sum(s => s.Amount);
当您得到这种类型的错误时,您需要在linq查询之外执行所有计算,并将值作为变量传递。
你的问题是thetag.ProductNames.Any()
断章取义。
此计算不转换为SQL,因为它不是字符串/guid或int。
您需要在查询中查询该对象并从该对象求值。
我不确定这是否清楚。
你需要做一些像
var query1 = (from x in tags where x.tagID = id select x.ProductNames)
.SelectMany(...)
选择许多是因为您正在选择一个集合ProductNames
,并且需要将其作为一个平面集合/集合带回来,以便您可以在下一个查询中对其执行.Any()
。
然后使用这个,并做一个query1.Any(logic)
decimal total = myentities.PurchaseRecords.
Where(x => query1.Any
(a => a.FullName == x.ProductName.FullName))
.Sum(s => s.Amount);
通过这样做,你将保持到实体的linq,而不是转换到对象的linq。
ForEach
不是一个选项,因为它将遍历集合。
你可以在c#中使用AsEnumerable方法来执行查询的某些部分,而不是在sql server上。当内存中有部分数据(对象集合)时,通常需要这样做,因此在查询中使用它们并不容易。你必须在。net端执行部分查询。对于您的问题,请尝试
decimal total = myentities.PurchaseRecords.AsEnumerable()
.Where(x => thetag.ProductNames.Any
(a => a.FullName == x.ProductName.FullName))
.Sum(s => s.Amount);
请访问此链接了解更多关于