TanvirArjel / EFCore.GenericRepository

This repository contains Generic Repository implementation for Entity Framework Core
MIT License
583 stars 85 forks source link

Add predicate to ExecuteUpdateAsync #42

Closed NotAsea closed 9 months ago

NotAsea commented 9 months ago

ExecuteUpdateAsync of EFCore rely on the source IQueryable has already been filtered by Where Linq, but in your version, i can not see anywhere to add filter for your repository, which mean whenever we call something like

await repository.ExecuteUpdateAsync<Person>(
    sp => sp.SetProperty(t => t.IsDeleted, true)
)
// translate to
/*
UPDATE People SET IsDeleted = true;
*/

whole record will get updated immediately, maybe you can add an predicate to your ExecuteUpdateAsync to let consumer supply their own filter condition just like what we can do in EFCore

await context.People
    .Where(p => p.CreatedDate <= DateTime.Now.AddDays(-30))
    .ExecuteUpdateAsync(sp =>  sp => sp.SetProperty(t => t.IsDeleted, true)) );
// now we have where clause
/*
UPDATE People SET IsDeleted = false
WHERE CreatedDate <= @p__linq__0;
*/
NotAsea commented 9 months ago

Browsing around source code i find your implementation like this

public async Task<int> ExecuteUpdateAsync<TEntity>(
                    Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls,
                    CancellationToken cancellationToken = default)
                    where TEntity : class
{
     int count = await _dbContext.Set<TEntity>().ExecuteUpdateAsync(setPropertyCalls, cancellationToken);
     return count;
}

So instead of calling ExecuteUpdateAsync directly in DbSet, you can change function a little like so

public async Task<int> ExecuteUpdateAsync<TEntity>(
                    Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls,
                    Expression<Func<TEntity, bool>>? predicate = null
                    CancellationToken cancellationToken = default)
                    where TEntity : class
{
    var dbSet = _dbContext.Set<TEntity>();
    if (predicate != null) dbSet = dbSet.Where(predicate);
    return await dbSet.ExecuteUpdateAsync(setPropertyCalls, cancellationToken);
}

Anyway, your library is already good, filter in ExecuteUpdateAsync is some niche thing

TanvirArjel commented 9 months ago

@NotAsea Thank you so much for reaching out. Surely I am taking care of it.

NotAsea commented 9 months ago

closing as @TanvirArjel has already had planned for it