Home > OS >  Better way to do a SelectAll, Filter, Update (on all results)
Better way to do a SelectAll, Filter, Update (on all results)

Time:11-27

So I have this piece of code which I think can be improved but I don't know how

IList<User> users = await _unitOfWork.UserRepository.SelectAllAsync();
users = users.Where(x => x.Field == MyField).ToList();
foreach (var user in users)
{
   user.Active = IsActive;
   await _unitOfWork.UserRepository.UpdateAsync(user);
}

What I want to achieve is:

1) get all entries
2) filter them
3) on the filtered list, update their active status

How can I improve this code, both performance-wise and clean-wise?

Thanks.

CodePudding user response:

No idea what's inside your _unitOfWork object, but the code seems to imply you are implementing the reporistory pattern. EF Core already impliments that, so you are not achieving anything by adding another repository on top of it.

If you use a DbContext directly, you can improve your code as follows...

IList<User> users = await _ctx.Users
  .Where(x => x.Field == MyField)
  .ToListAsync();
foreach (var user in users)
{
   user.Active = IsActive;
}
await _ctx.SaveChangesAsync()

This has two advantags over your code...

  1. Your code pulls all users out of the repository and then filters in memory. Depending on the number of users, this can be inefficient. My cde only pulls out the users that you want.

  2. Your code calls the database for every user. As my code is just updating the local context, it only needs to call the database once, when all the udpates are done.

CodePudding user response:

This is completely memory insufficient and wrong in all aspects. Your code seems to me that has a repository pattern and you have a repository in which you are implementing a type of T repository -if it's not type of T simply replace T with your type like User- so your first and most problematic part is why you get all your entries and then you select the records that match the where condition. in this pattern you scan all your records two times while there is no need for that. try to add where clause in your parameters in your repository like below:

public async Task<List<T>> SelectAllAsync(Expression<Func<T, bool>>? filter = null)
{
    IQueryable<T> query = dbSet;
            if (filter != null)
            {
                // now you can put your wher clause here
                query = query.Where(filter);
            }
    return await query.ToListAsync();
}

And when calling it you can simply do the following:

IList<User> users = await _unitOfWork.UserRepository.SelectAllAsync(filter: x => x.Field == MyField);

with this you only scan your database once and you don't need to filter the result again Second, if you use this User table a lot to get all the Users Based on IsActive Column add an index for it since it is too much job

  • Related