简体   繁体   English

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

[英]slightly complex many-to-many linq query got me stuck

So I'm on Linq-To-Entities with an asp.net mvc project. 所以我在一个asp.net mvc项目上使用Linq-To-Entities。

I always get a little stumped with this sort of query. 我总是对这种查询有些困惑。

My schema is: 我的架构是:

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.

I need to get the sum of all purchases for a given tag. 我需要获取给定标签的所有购买金额之和。

This is what I've tried. 这就是我尝试过的。

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);

I've tried changing a couple of things, tried using Contains , but I know I'm fundamentally wrong somewhere. 我尝试过更改一些事情,尝试使用Contains ,但是我知道我在某处根本上是错的。

I keep getting : 我不断得到:

Unable to create a constant value of type 'ProductName'. 无法创建类型为“ ProductName”的常量值。 Only primitive types ('such as Int32, String, and Guid') are supported in this context. 在这种情况下,仅支持基本类型(例如Int32,String和Guid)。

Update So with @Alexandre Brisebois 's help below it worked simply like this: 更新因此,在下面的@Alexandre Brisebois的帮助下,它的工作原理如下:

var total= item.ProductNames.SelectMany(x => x.PurchaseRecords)
                                             .Sum(s => s.Amount);

When you get this sort of error, you need to do all evaluations outside of the linq query and pass the values in as variables. 遇到此类错误时,您需要在linq查询之外进行所有评估,并将值作为变量传递。

the problem with your query is that thetag.ProductNames.Any() is out of context. 您查询的问题是thetag.ProductNames.Any()不在上下文中。

This evaluation is not converted to SQL since it is not a string/guid or int. 此评估不是字符串/ guid或int,因此不会转换为SQL。

You will need to query for this object within your query and evaluate from this object. 您将需要在查询中查询该对象,然后从该对象进行评估。

I'm not sure if that was clear. 我不确定是否很清楚。

You would need to do something like 您需要做类似的事情

var query1 = (from x in tags where x.tagID = id select x.ProductNames)
                                                          .SelectMany(...)

The select many is because you are selecting a collection ProductNames and need to bring it back as a flat set/collection fo that you can do a .Any() on it in the next query. 选择许多是因为您正在选择一个集合ProductNames并且需要将其作为一个平面集/集合带回,您可以在下一个查询中对其执行.Any()

Then use this and do an query1.Any(logic) 然后使用它并执行query1.Any(logic)

decimal total = myentities.PurchaseRecords.
                           Where(x => query1.Any
                                (a => a.FullName == x.ProductName.FullName))
                                .Sum(s => s.Amount); 

By doing this you will stay in linq to entity and not convert to linq to objects. 这样,您将停留在linq to实体中,而不会转换为linq to objects。

The ForEach is not an option since this will iterate over the collection. ForEach不是一个选项,因为它将遍历整个集合。

you can use AsEnumerable method to perform certain portions of query in C# rather than on sql server. 您可以使用AsEnumerable方法在C#中而不是在SQL Server上执行查询的某些部分。 this is usually required when you have part of data in memory (Collection of objects) so using them in query is not easy. 当内存中有部分数据(对象的集合)时,通常需要这样做,因此在查询中使用它们并不容易。 you have to perform part of query execution on .net side. 您必须在.net端执行部分查询执行。 for your problem plz try 对于您的问题请尝试

decimal total = myentities.PurchaseRecords.AsEnumerable()
                    .Where(x => thetag.ProductNames.Any
                         (a => a.FullName == x.ProductName.FullName))
                         .Sum(s => s.Amount);

plz visit this link to find more about AsEnumerable 请访问此链接以找到有关AsEnumerable的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM