Filtering in Linq with where condition - c#

I want to get the users based on the continent for my application. I used the following code for this. Now I want to show all users if the continentId is null. How can I achieve this?
public async Task<IEnumerable<User>> GetUsersByContinent(int? continentId)
{
var users = await _context.Users
.Include(u => u.Country).ThenInclude(c => c.Continent)
.Where(u => u.Country.ContinentId == continentId)
.OrderBy(u => u.Username)
.ToListAsync();
return users;
}

You can use use method chaining to solve your problem.
public async Task<IEnumerable<User>> GetUsersByContinent(int? continentId)
{
var baseQuery= _context.Users.Include(u => u.Country).ThenInclude(c => c.Continent);
if (continentId.HasValue){
baseQuery = baseQuery.Where(u => u.Country.ContinentId == continentId)
}
return await baseQuery.OrderBy(u => u.Username).ToListAsync();
}

I would probably use #Jehof solution, but it's worth mentioning alternative solution.
.Where(u => continentId == null || u.Country.ContinentId == continentId)

Related

Resharper warns that it may be null, but will I run into problems in the future?

I recently converted my code to more LINQ based code. But ReSharper warns me that the FindAsync function may return null. I don't want to check for null as I'm a bit obsessed with order. Does not checking for null cause problems in the future?
One of the old methods:
public async Task<IList<Post>> GetPostsByTagIdAsync(int tagId)
{
var posts = new List<Post>();
var postIds = context.PostsTags
.Where(pt => pt.TagId == tagId)
.Select(p => p.PostId);
foreach (var id in postIds)
posts.Add(await context.Posts.FindAsync(id));
return posts;
}
New version:
public async Task<IList<Post>> GetPostsByTagIdAsync(int tagId) =>
await context.PostsTags
.Where(pt => pt.TagId == tagId)
.Select(p => context.Posts.FindAsync(p.PostId).Result)
.ToListAsync();
Both versions are ineffective. Better to ask for Posts in one database roundtrip.
public Task<IList<Post>> GetPostsByTagIdAsync(int tagId)
{
var query =
from pt in context.PostsTags
join p in context.Posts on pt.PostId equals p.Id
where pt.TagId == tagId
select p;
return query.ToListAsync();
}
Also query can be simplified if you have right navigation properties
public Task<IList<Post>> GetPostsByTagIdAsync(int tagId) =>
context.PostsTags
.Where(pt => pt.TagId == tagId)
.Select(pt => pt.Post)
.ToListAsync();
Note that, I have removed async - it will also speedup execution, because compiler do not create additional state machine for handling asynchronous operations.

.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.

Why Where clause in not working with Virtual property in LINQ

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

The best way to order included entities in entity framework?

What is the best practice to order the comment entity?
public async Task<IList<Post>> GetPosts() {
var posts = _context.Posts
.Include(u => u.User)
.ThenInclude(p => p.Photos)
.Include(c => c.Comments) <---- THIS
.OrderByDescending(p => p.Created)
.ToListAsync();
return await posts;
}
Before you return the posts, you can order the Comments attached to each post:
var posts = await _context.Posts
.Include(u => u.User)
.ThenInclude(p => p.Photos)
.Include(c => c.Comments)
.OrderByDescending(p => p.Created)
.ToListAsync();
foreach(var post in posts)
{
post.Comments = post.Comments
.OrderBy(comment => comment.DateCreated)
.ToList();
}
return posts;
I did the ordering above based on a property called DateCreated. You have to change this to the comment object property, on which you want to base the ordering.

OrderByDescending with multiple fields

I want to be able to sort by d.DateUpdated but only when it's not DateTime.MinValue. If it's DateTime.MinValue then I would need it to be able to sort by d.DateCreated. It there a way to do this with in the following line of code?
return database.Table<Announcement>()
.Where(i => i.GroupId == groupId)
.OrderByDescending(d => d.DateUpdated)
.ToListAsync();
You might as well use ThenBy method
return database.Table<Announcement>()
.Where(i => i.GroupId == groupId)
.OrderByDescending(d => d.DateUpdated)
.ThenByDescending(d => d.DateCreated)
.ToListAsync();
Something like that?
return database.Table<Announcement>()
.Where(i => i.GroupId == groupId)
.OrderByDescending(d => d.DateUpdated == null ? d.DateCreated : d.DateUpdated)
.ToListAsync();

Categories

Resources