Why Where clause in not working with Virtual property in LINQ - c#

I am trying to do something like this
var users = await _dbContext.Users.AsNoTracking().AsQueryable()
.Include(user => user.AdminRoles)
.Where(u => u.AdminRoles.Roles.Contains("admin2022"))
.ToListAsync();
Here the list is getting 0 results, but when I do
var users = (await _dbContext.Users.AsNoTracking().AsQueryable()
.Include(user => user.AdminRoles).ToListAsync())
.Where(u => u.AdminRoles.Roles.Contains("admin2022"))
.ToList();
Then it yields all the required results. Could some one please help me how can I make the first way work ?

Try:
var users = await _dbContext.Users
.AsNoTracking()
.AsQueryable()
.Include(user => user.AdminRoles.Where(x => x.Roles.Contains("admin2022")))
.ToListAsync();

Related

.NET 6 : context.db.Where().Orderby().ToListAsync() does not work

Here is my code:
public async Task<IEnumerable<Command>> GetCommandsByPlatform(Guid platformId)
{
return await _context.Commands
.Where(c => c.PlatformId == platformId)
.ToListAsync();
}
public async Task<IEnumerable<Command>> GetCommandsByPlatform(Guid platformId)
{
return await _context.Commands
.Where(c => c.PlatformId == platformId)
.OrderBy(c => c.Platform.Name)
.ToListAsync();
}
The only difference is that the second code has OrderBy() after Where(). The first code snippet successfully returns a list of commands, but the second one only returns an empty list.
Thank you for answering.
At first glance, you need an Include(x => x.Platform) in your query:
public async Task<IEnumerable<Command>> GetCommandsByPlatform(Guid platformId)
{
return await _context.Commands
.Include(c => c.Platform) // this generates a join
.Where(c => c.PlatformId == platformId)
.OrderBy(c => c.Platform.Name)
.ToListAsync();
}
I'm like 75% sure that in EF Core, the Include is not needed, while in full EF6 it won't generate a join without it.

The LINQ expression cannot be translated on Grouping

I have LINQ expression to take top 15 most frequently used answers
Here is expression
var latestAnswers = await _dbContext.TextAnswers.Include(x => x.CompanySurvey).ThenInclude(x => x.Survey)
.Where(x => x.CompanySurvey.Survey.FiscalYear == 2022)
.GroupBy(x => x.Answer)
.OrderByDescending(g => g.Count())
.Take(15)
.ToListAsync();
But I get this error
The LINQ expression 'DbSet() .Include(x => x.CompanySurvey) .ThenInclude(x => x.Survey) .Where(x => x.CompanySurvey.Survey.FiscalYear == (int?)2022) .GroupBy(x => x.Answer) .OrderByDescending(g => g .AsQueryable() .Count()) .Take(__p_0)' 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.
I can't understood why it cant be translated.
How I can fix this?
EF Core 6 has to support such queries, but looks like full implementation support is moved to EF Core 7
After conversation looks like it is not needed to get grouped records from database, but just grouping key and Count
var latestAnswers = await _dbContext.TextAnswers
.Where(x => x.CompanySurvey.Survey.FiscalYear == 2022)
.GroupBy(x => x.Answer)
.Select(g => new { Answer = g.Key, Count = g.Count() })
.OrderByDescending(x => x.Count)
.Take(15)
.ToListAsync();
I rewrite my code like this
var latestAnswersQuery = await _dbContext.TextAnswers
.Include(x => x.CompanySurvey).ThenInclude(x => x.Survey)
.Where(x => x.CompanySurvey.Survey.FiscalYear == 2022)
.ToListAsync();
var latestAnswers = latestAnswersQuery.GroupBy(x => x.Answer).OrderByDescending(g => g.Count()).Take(15);
return latestAnswers;
And now everything great

Linq: GroupBy not show result for the .Include clause

Why in the result "Titolare" is null?
If I don't use GroupBy, "Titolare" has value.
Thank you.
var ben = context.Benefici.Include("Titolare").Include("Titolare.ComuneDomicilio")
.Where(b => !b.Titolare.SD1_DAT_DECESSO.HasValue)
.OrderByDescending(b => b.SDB_DAT_INIZIO)
.GroupBy(b => b.SDB_CODDIS)
.ToList()
.Select(b => b.First())
.ToList();
It is because of GroupBy limitation - you cannot get grouped items using LINQ to Entities. It should be fixed in EF Core 6.
To get first item of the group, you have to rewrite your query. It is mimic of what will be generated by EF Core 6:
var itemsQuery = context.Benefici
.Where(b => !b.Titolare.SD1_DAT_DECESSO.HasValue);
var benQuery =
from u in itemsQuery.Select(b => new { b.SDB_CODDIS }).Distinct()
join b in itemsQuery
.Include(x => x.Titolare.ComuneDomicilio)
.Where(x => x.SDB_CODDIS == u.SDB_CODDIS)
.OrderByDescending(x => x.SDB_DAT_INIZIO)
.Take(1)
select b;
var ben = benQuery.ToList();

EF 6 complex query with Include not including relations

i have a somewhat complex structure i wont get into,
but what i try doing is:
Get all ShopItems, who's SourceItem has changed,
Get and update them according to their Source/Shop data.
i conjured the following:
var query = _ctx.ShopItems
.Include(si => si.Shop)
.Include(si=>si.SourceItem)
.Include(si => si.SourceItem.Source)
.Include(si=>si.Shop.ShopType)
.GroupBy(i => i.SourceItem)
.Where(g => g.Key.LastUpdate > lastUpdate)
.OrderBy(g => g.Key.LastUpdate)
.Take(updateCountLimit);
the query seems to work, but when itterating the Groups:
groupItem.Key.Source is null.
I somewhat solved it by Removing the Include()s, saving the Entities to an Array, and explicitly loading the references using
_ctx.Entry(updatedSourceItem.Key).Reference(src=>src.Source).Load();
How can i perform the query i want without round-tripping the DB for explicit loading ?
Not sure, but it's backwards to start with ShopItems and then group by SourceItem. Try just starting with SourceItem, something like
:
var query = _ctx.SourceItems
.Include(i => i.ShopItems)
.Include(i => i.Source)
.Include(i => i.ShopItems.Select( si => si.Shop))
.Include(i => i.ShopItems.Select( si => si.Shop).ShopType)
.Where(i => i.LastUpdate > lastUpdate)
.OrderBy(i => i.LastUpdate)
.Take(updateCountLimit);
//or
var query = _ctx.SourceItems
.Include("ShopItems")
.Include("Source")
.Include("ShopItems.Shops")
.Include("ShopItems.Shops.ShopType")
.Where(i => i.LastUpdate > lastUpdate)
.OrderBy(i => i.LastUpdate)
.Take(updateCountLimit);

could not resolve property: PropertyName of: Class error in NHibernate

I'm using NHibernate first time and in this line it throws exception for me
var total = session
.QueryOver<Comment>().Where(p => p.Entry.Author == username)
.ToRowCountQuery()
.FutureValue<int>();
var results = session
.QueryOver<Comment>().Where(p => p.Entry.Author == username)
.Fetch(x => x.Entry).Eager()
.OrderBy(x => x.Posted).Desc()
.Skip(skip)
.Take(take)
.List();
The Exception is
could not resolve property: Entry.Author of: FunnelWeb.Model.Comment
I guess, the problem is that Entry object doesn't loaded here. How can I do that trick with Nhibernate?
QueryOver is just a strongly-typed wrapper for Criteria, and doesn't allow implicit deep references.
You'd have to use:
session.QueryOver<Comment>()
.JoinQueryOver(x => x.Entry)
.Where(x => x.Author == username)
Or you can use Query<> instead (LINQ) which will work with the syntax you've tried.
You'd need to JoinAlias or JoinQueryOver. I have an example below on how to use Future queries...
Entry entryAlias = null;
var q = session.QueryOver<Comment>()
.JoinAlias(x => x.Entry, () => entryAlias)
.Where(() => entryAlias.Author == username);
var totalFuture = q.ToRowCountQuery().FutureValue<int>(); //ToRowcountQuery clones the query, we can reuse it for results
var resultsFuture = q
//.Fetch(x => x.Entry).Eager() //already joined
.OrderBy(x => x.Posted).Desc()
.Skip(skip)
.Take(take)
.Future<Comment>();
var results = resultsFuture.ToList(); //both future queries are executed in the same batch
var total = totalFuture.Value;

Categories

Resources