IRepository.cs
public interface ICommonRepository<T>
{
Task<int> CountAsync(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>,IOrderedQueryable<T>> orderBy = null,List<Expression<Func<T, object>>> includes = null);
}
Repository.cs:
public class Repository<T> : IRepository<T> where T : class, new()
{
protected readonly MyDbContext _context;
protected readonly ILogger<Repository<T>> _logger;
protected readonly DbSet<T> _dbSet;
public CommomRepository(MyDbContext context, ILogger<Repository<T>> logger)
{
_context = context;
_logger = logger;
if (_context != null)
{
_dbSet = _context.Set<T>();
}
else
{
}
}
internal IQueryable<T> _Select(Expression<Func<T, bool>> filter = null
, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null
, List<Expression<Func<T, object>>> includes = null
, int? pageIndex = null
, int? pageSize = null)
{
IQueryable<T> query = _dbSet;
if (includes != null)
{
query = includes.Aggregate(query, (current, include) => current.Include(include));
}
if (orderBy != null)
{
query = orderBy(query);
}
if (filter != null)
{
query = query.Where(filter);
}
if (pageIndex != null && pageSize != null)
{
query = query.Skip((pageIndex.Value - 1) * pageSize.Value).Take(pageSize.Value);
}
return query;
}
public async Task<int> CountAsync(Expression<Func<T, bool>> filter = null
, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null
, List<Expression<Func<T, object>>> includes = null)
{
var query = _Select(filter, orderBy, includes);
return await query.CountAsync();
}
}
用法(控制器):
var singleCheckTask = _Repo.CountAsync(x=> x.id== item.id);
var nameCheckTask = _Repo.CountAsync(x=> x.name== item.name);
var ipCheckTask = _Repo.CountAsync(x=> x.ip == item.ip);
await Task.WhenAll(singleCheckTask, nameCheckTask, ipCheckTask);
例外情况:
Microsoft.EntityFrameworkCore.Query.Internal.SqlServerQueryCompilationContextFactory | ERROR |在迭代查询结果时数据库中发生异常。 System.InvalidOperationException:在异步操作挂起时无法启动另一个操作。
我测试过,如果我不使用Task.whenAll,var testSingleCheck = _Repo.CountAsync(x=> x.id== item.id).Result;
这样就可以了。
答案 0 :(得分:3)
很简单,您无法与EF并行运行查询(既不是EF6也不是EF Core)。
一个原因是,EF不是线程安全的。
线程安全
虽然线程安全会使异步更有用,但它是一个正交特征。目前还不清楚我们是否可以在最常见的情况下实现对它的支持,因为EF与用户代码组成的图形交互以维持状态,并且没有简单的方法来确保此代码也是线程安全的。
目前,EF将检测开发人员是否尝试同时执行两个异步操作并抛出。