稍微复杂的多对多linq查询使我陷入困境

问题描述

|| 因此,我使用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);
    

解决方法

遇到这种错误时,您需要在linq查询之外进行所有评估,并将值作为变量传递。 您查询的问题是
thetag.ProductNames.Any()
不在上下文中。 此评估不是字符串/ guid或int,因此不会转换为SQL。 您将需要在查询中查询该对象,然后从该对象进行评估。 我不确定是否很清楚。 您需要做类似的事情
var query1 = (from x in tags where x.tagID = id select x.ProductNames)
                                                          .SelectMany(...)
选择很多是因为您正在选择一个集合ѭ6,并且需要将其作为一个平面集/集合带回去,您可以在下一个查询中对其进行一个
.Any()
。 然后用它做一个
query1.Any(logic)
decimal total = myentities.PurchaseRecords.
                           Where(x => query1.Any
                                (a => a.FullName == x.ProductName.FullName))
                                .Sum(s => s.Amount); 
这样,您将停留在linq to实体中,而不会转换为linq to objects。 不能选择“ 10”,因为这会遍历整个集合。     ,您可以使用AsEnumerable方法在C#中而不是在SQL Server上执行查询的某些部分。当内存中有部分数据(对象的集合)时,通常需要这样做,因此在查询中使用它们并不容易。您必须在.net端执行部分查询执行。对于您的问题请尝试
decimal total = myentities.PurchaseRecords.AsEnumerable()
                    .Where(x => thetag.ProductNames.Any
                         (a => a.FullName == x.ProductName.FullName))
                         .Sum(s => s.Amount);
请访问此链接以找到有关AsEnumerable的更多信息