Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core 3 GroupBy multiple columns Count Throws with extensions but linq works

Here is the one that throws full exception:

            var duplicateCountOriginal = _db.TableName
                                .GroupBy(g => new {g.ColumnA, g.ColumnB, g.ColumnC})
                                .Count(g => g.Count() > 1);

Exception: System.ArgumentException: Expression of type 'System.Func2[System.Linq.IGrouping2[Microsoft.EntityFrameworkCore.Storage.ValueBuffer,Microsoft.EntityFrameworkCore.Storage.ValueBuffer],Microsoft.EntityFrameworkCore.Storage.ValueBuffer]' cannot be used for parameter of type 'System.Func2[Microsoft.EntityFrameworkCore.Storage.ValueBuffer,Microsoft.EntityFrameworkCore.Storage.ValueBuffer]' of method 'System.Collections.Generic.IEnumerable1[Microsoft.EntityFrameworkCore.Storage.ValueBuffer] Select[ValueBuffer,ValueBuffer](System.Collections.Generic.IEnumerable1[Microsoft.EntityFrameworkCore.Storage.ValueBuffer], System.Func2[Microsoft.EntityFrameworkCore.Storage.ValueBuffer,Microsoft.EntityFrameworkCore.Storage.ValueBuffer])' (Parameter 'arg1')

But the same thing works when it is written as linq (I prefer extensions)

            var duplicateCount =
                    from a in _db.TableName
                    group a by new {a.ColumnA, a.ColumnB, a.ColumnC}
                    into g
                    where g.Count() > 1
                          select g.Key;
            duplicateCount.Count()

I am unable to understand why one works or the other doesn't. Also if I change the first one a little bit based on EF Core 3 changes like the following

            var duplicateCountOriginal = _db.TableName
                                .GroupBy(g => new {g.ColumnA, g.ColumnB, g.ColumnC})
                                .AsEnumerable()
                                .Count(g => g.Count() > 1);

I get the following exception: System.InvalidOperationException: Client projection contains reference to constant expression of 'Microsoft.EntityFrameworkCore.Metadata.IPropertyBase' which is being passed as argument to method 'TryReadValue'. This could potentially cause memory leak. Consider assigning this constant to local variable and using the variable in the query instead. See https://go.microsoft.com/fwlink/?linkid=2103067 for more information.

According to me, the link given by ms has no meaning to the whatever problem here is.

Please LMK if there is any logical explanation.

like image 354
SevDer Avatar asked Jan 11 '20 17:01

SevDer


1 Answers

There is no logical explanation. Just EF Core query translation is still far from perfect and have many defects/bugs/unhandled cases.

In this particular the problem is not the query syntax or method syntax (what you call extensions), but the lack of Select after GroupBy. If you rewrite the method syntax query similar to the one using query syntax, i.e. add .Where, .Select and then Count:

var duplicateCount = _db.TableName
    .GroupBy(g => new {g.ColumnA, g.ColumnB, g.ColumnC})
    .Where(g => g.Count() > 1)
    .Select(g => g.Key)
    .Count();

then it will be translated and executed successfully.

like image 178
Ivan Stoev Avatar answered Nov 08 '22 07:11

Ivan Stoev