简体   繁体   中英

LINQ GroupBy Clause System.NotSupportedException error

I have this query and I faced this error when I want to check the date inside the Min() Method. Can anyone explain the reason? I just know a little about Expression<Func> and Func<> .

var s2 = md.Tb_order
    .GroupBy(x => x.orderid)
    .Where(x => x.Min(p => p.date > 2))
    .Select(x => x);

System.NotSupportedException: 'The specified method 'Boolean Min[Tb_order,Boolean](System.Collections.Generic.IEnumerable 1[SqlServer_LinqTest.Tb_order], System.Func 2[SqlServer_LinqTest.Tb_order,System.Boolean])' on the type 'System.Linq.Enumerable' cannot be translated into a LINQ to Entities store expression because no overload matches the passed arguments.'*

if I check the date outside of the Method it works fine

var s2 = md.Tb_order
    .GroupBy(x => x.orderid)
    .Where(x => x.Min(p => p.date) > 2)
    .Select(x => x);

EDITED

When I see the explanation of the Where() method it seems there must be a parameter of Func<> . What is the relation between p.date and Func<> type? Does p.date return something of IEnumerable ?

According to this , Min is Min<TSource, TResult> .

TSource The type of the elements of source.

TResult The type of the value returned by selector (in this case the min date).

but you are passing a condition there which is not what is expecting, it is expecting a sequence of values to determine the minimum value of.

Answering your question what is the relation between p.date and Func<> type?

p.date is pointer to the attribute date for your enumerable x which is the value of your group dictionary, group result in dictionary which is <key,value> , where key is the order id, and value is a list of orders that have the same group key (order id), so when you are writing Min(p => p.date) you are asking linq to get the min date of this sequence (the value list).

so when you are doing this Min(p => p.date) > 2 you are comparing the min value (result from min) to 2 which is fine, but when you are passing Min(p => p.date > 2) you are passing something LINQ can't translate as we previously mention it is expecting a sequence of values, not a condition.

Summary

if you are doing the right way, you are telling linq to group all orders based on order id, and then exclude the groups where group min date is not more than 2 (you exclude the whole group list). maybe this is what you want,

or maybe you want this.

var s2 = md.Tb_order
    .Where(x => x.date > 2)
    .GroupBy(x => x.orderid);

which will return all orders where date is more than 2, then group them.

This differs from the first one, since the first will ignore all orders belonging to the same id when there is one of them doesn't meet date > 2, but this one will ignore only the ones where date > 2.

Can anyone explain the reason?

Min() is an aggregate function . You cannot aggregate on a method - eg p.date > 2 . You can, however aggregate on an expression - eg p.date .

I assume you're trying to find the order, HAVING the minimal date which is greater than 2. Indeed, the Min() method can find the minimal date , but that's it. It can't check other condition(s). To do that, you should restrict your records to include only orders with dates greater than whatever you're interested in, and then do the aggregation:

var s2 = md.Tb_order
    .Where(x => x.date > 2)
    .GroupBy(x => x.orderid)
    .Min(x => x.date);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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