Open SerhiyBalan opened 1 year ago
Is there a suggested approach on how to support this? @SerhiyBalan - did you have a workaround?
@StuartBale-Xero
My project uses UnitOfWork / GenericRepository pattern
So instead of using native EF's ExecuteUpdateAsync / ExecuteDeleteAsync extensions I use own methods at the Generic Repository:
public class GenericRepository<TEntity> : IRepository<TEntity>
where TEntity : class, new()
{
public GenericRepository(DbContext dbContext)
{
ArgumentNullException.ThrowIfNull(dbContext);
DbSet = dbContext.Set<TEntity>();
}
protected DbSet<TEntity> DbSet { get; }
...
public virtual Task<int> ExecuteUpdateAsync(
Expression<Func<TEntity, bool>> predicate,
Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls,
CancellationToken cancellationToken = default)
=> DbSet
.AsQueryable()
.Where(predicate)
.ExecuteUpdateAsync(setPropertyCalls, cancellationToken);
public virtual Task<int> ExecuteDeleteAsync(
Expression<Func<TEntity, bool>> predicate,
CancellationToken cancellationToken = default)
=> DbSet
.AsQueryable()
.Where(predicate)
.ExecuteDeleteAsync(cancellationToken);
}
In code instead of
await _unitOfWork
.GetRepository<User>()
.AsQueryable()
.Where(user => user.Id == id)
.ExecuteDeleteAsync(); // Native Entity Framework extension
I use my own methods:
await _unitOfWork
.GetRepository<User>()
.ExecuteDeleteAsync(user => user.Id == id); // My method in GenericRepository
Since they are no more extensions, I can easily mock them
Hi, guys!
Any update on this? I don't use the UoW / repository and it would be really interesting if MockQueryable could support these methods.
Hi, guys!
Any update on this? I don't use the UoW / repository and it would be really interesting if MockQueryable could support these methods.
same here...
Hello. Thanks for you contribution. Sorry for the late answer. Unfortunately I'm very busy at the moment. If you provide a pull request with fix of the issue I would be happy to include it to the next release. Please don't forget to cover the case by additional tests to minimize possibility of regressions for the future. Thanks for the understanding.
@StuartBale-Xero
My project uses UnitOfWork / GenericRepository pattern
So instead of using native EF's ExecuteUpdateAsync / ExecuteDeleteAsync extensions I use own methods at the Generic Repository:
public class GenericRepository<TEntity> : IRepository<TEntity> where TEntity : class, new() { public GenericRepository(DbContext dbContext) { ArgumentNullException.ThrowIfNull(dbContext); DbSet = dbContext.Set<TEntity>(); } protected DbSet<TEntity> DbSet { get; } ... public virtual Task<int> ExecuteUpdateAsync( Expression<Func<TEntity, bool>> predicate, Expression<Func<SetPropertyCalls<TEntity>, SetPropertyCalls<TEntity>>> setPropertyCalls, CancellationToken cancellationToken = default) => DbSet .AsQueryable() .Where(predicate) .ExecuteUpdateAsync(setPropertyCalls, cancellationToken); public virtual Task<int> ExecuteDeleteAsync( Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default) => DbSet .AsQueryable() .Where(predicate) .ExecuteDeleteAsync(cancellationToken); }
In code instead of
await _unitOfWork .GetRepository<User>() .AsQueryable() .Where(user => user.Id == id) .ExecuteDeleteAsync(); // Native Entity Framework extension
I use my own methods:
await _unitOfWork .GetRepository<User>() .ExecuteDeleteAsync(user => user.Id == id); // My method in GenericRepository
Since they are no more extensions, I can easily mock them
@SerhiyBalan But does it work well? since ExecuteUpdate doesn't follow UoW and repository pattern. My project has same scenario where existing code is using repository pattern and UoW since I need to implement bulk update action, I'm clueless how to do it if I already have repository pattern in place
Hello!
I've been using MockQueryable with .NET6 a lot Recently my project migrated to .NET 7 (EF Core 7) And I started to use new EF7 features:
ExecuteDeleteAsync implementation is here https://github.com/dotnet/efcore/blob/main/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs#L316
ExecuteUpdateAsync implementation is here https://github.com/dotnet/efcore/blob/main/src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs#L372
I use MockQueryable using a standard pattern:
ToListAsync(), FirstOrDefaultAsync() and others works perfectly with this pattern.
Unfortunately ExecuteUpdateAsync / ExecuteDeleteAsync doesn't work at all :(
When I try to run a unit test, a mocked
GetQueryable
method works nicely as usual, but it throws an exception on ExecuteDeleteAsyncException throws here on
.Invoke(this, new object[] { expression });
https://github.com/romantitov/MockQueryable/blob/master/src/MockQueryable/MockQueryable.EntityFrameworkCore/TestQueryProviderEfCore.cs#L25Same exception throws at ExecuteUpdateAsync (but it says
There is no method 'ExecuteUpdate' on type 'Microsoft.EntityFrameworkCore.RelationalQueryableExtensions' that matches the specified arguments
)The extensions
custom logic
pattern doesn't work because ExecuteUpdateAsync / ExecuteDeleteAsync are IQueryableThank you very much