I have two table like this :
CREATE TABLE [dbo].[Transactions](
[Id] uniqueidentifier NOT NULL,
[CustomerId] uniqueidentifier NOT NULL, // equals to AspNetUsers.Id
[CoinId] uniqueidentifier NOT NULL,
[Amount] [decimal](18, 8) NOT NULL,
[Balance] [decimal](18, 8) NOT NULL,
[CreatedOn] [datetime2](7) NOT NULL
)
CREATE TABLE [dbo].[AspNetUsers](
[Id] uniqueidentifier NOT NULL,
[FullName] nvarchar(256) NOT NULL
)
CREATE TABLE [dbo].[Coins](
[Id] uniqueidentifier NOT NULL,
[Name] nvarchar(256) NOT NULL
)
I want to create a report that shows howmuch balance has every customer. my linq query is :
var q = (from t in _db.Transactions
join u in _db.Users on t.CustomerId equals u.Id
group t by new { t.CustomerId, u.FullName } into grp
where grp.OrderByDescending(c => c.CreatedOn).Select(c => c.Balance).First() > 0
select new
{
CustomerId = grp.Key.CustomerId,
CustomerFullName = grp.Key.FullName,
Balance = grp.OrderByDescending(c => c.CreatedOn).Select(c => c.Balance).FirstOrDefault()
});
var balances = q.ToList();
this query is ok in linqpad, but in the project (aspnet core 3.1 - netstandard2.1 (my query layer) - Microsoft.EntityFrameworkCore version 5.0.12) got error bellow:
The LINQ expression 'GroupByShaperExpression:
KeySelector: new {
CustomerId = t.CustomerId,
FullName = a.FullName
},
ElementSelector:EntityShaperExpression:
EntityType: Transaction
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
.OrderByDescending(c => c.CreatedOn)' could not be translated. Either rewrite the query in a
form that can be translated, or switch to client evaluation explicitly by inserting a call to
'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Finally I realized that ef can't handle group by and First(), so I tried to use another strategy.
the solution is using subquery instead of grouping. here is the query :
as you can see, I start with user table, add a subquery from transactions table in select part and check nullables.
at the end I simply use the 'query' to add some extra conditions