所以我在使用asp.net mvc项目的Linq-To-Entities上。
我总是对这种查询感到有些困惑。
我的架构是:
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);
答案 0 :(得分:1)
当您遇到此类错误时,您需要在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
不是一个选项,因为这会迭代集合。
答案 1 :(得分:0)
您可以使用AsEnumerable方法在C#中执行查询的某些部分,而不是在sql server上执行。当你在内存中有部分数据(对象集合)时通常需要这样做,所以在查询中使用它们并不容易。你必须在.net端执行部分查询执行。为你的问题PLZ尝试
decimal total = myentities.PurchaseRecords.AsEnumerable()
.Where(x => thetag.ProductNames.Any
(a => a.FullName == x.ProductName.FullName))
.Sum(s => s.Amount);
请访问此link以查找有关AsEnumerable
的更多信息