实体框架核心线程安全吗? [英] Entity Framework Core thread safe?
问题描述
我遵循 ASP.NET Core中的通用存储库模式,但在IRepository
上,我使用IQueryable
而不是IEnumerable
:
I follow Generic Repository Pattern in ASP.NET Core, but on IRepository
, I use IQueryable
instead of IEnumerable
:
public interface IRepository<T> where T: BaseEntity
{
IQueryable<T> Table { get; }
IEnumerable<T> TableNoTracking { get; }
T Get(long id);
void Insert(T entity);
void Update(T entity);
void Delete(T entity);
}
和实现类:
public class EFRepository<T> : IRepository<T> where T : BaseEntity
{
private readonly ApplicationDbContext _ctx;
private DbSet<T> entities;
string errorMessage = string.Empty;
public EFRepository(ApplicationDbContext context)
{
this._ctx = context;
entities = context.Set<T>();
}
public virtual IQueryable<T> Table => this.entities;
}
服务类别:
public class MovieService : IMovieService
{
private readonly IRepository<MovieItem> _repoMovie;
public MovieService(IRepository<MovieItem> repoMovie)
{
_repoMovie = repoMovie;
}
public async Task<PaginatedList<MovieItem>> GetAllMovies(int pageIndex = 0, int pageSize = int.MaxValue,
IEnumerable<int> categoryIds = null)
{
var query = _repoMovie.Table;
if (categoryIds != null)
{
query = from m in query
where categoryIds.Contains(m.CategoryId)
select m;
}
return await PaginatedList<MovieItem>.CreateAsync(query, pageIndex, pageSize);
}
}
在Startup.cs上:
On Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddMvc();
services.AddScoped(typeof(IRepository<>), typeof(EFRepository<>));
services.AddTransient<IMovieService, MovieService>();
services.AddTransient<ICategoryService, CategoryService>();
}
此代码引发错误:
InvalidOperationException:在上一个操作完成之前,第二个操作在此上下文上开始.不保证任何实例成员都是线程安全的.
InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
如果我在IRepository
上切换回IEnumerable
,则运行正常.
If I switch back to IEnumerable
on IRepository
, then it runs fine.
有什么想法如何使其与IQueryable
配合使用,以使EF Core以正确的方式运行?
Any idea how to get it to work with IQueryable
, to make to EF Core to run in the right way ?
query = from m in query
where categoryIds.Contains(m.CategoryId)
select m;
推荐答案
实体框架DbContext
不是线程安全的.您一次只能执行一个查询,否则会像上面一样出现异常.
Entity Framework DbContext
is not thread safe. You can execute only one query at a time otherwise you will get an exception like you did above.
我想您在同一请求中多次并行使用我们的存储库,这就是为什么您会得到异常的原因.如果您不按请求创建事务,则只需将存储库设置为瞬态即可.在这种情况下,将为服务的每个实例创建新的存储库,从而避免了并发问题.
I suppose that you use our repository multiple times during same request in parallel that's why you get the exception. If you don't create a transaction per request you can simply make repository transient. In this case new repository will be created fro each instance of your service and you will avoid concurrency issue.
这篇关于实体框架核心线程安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!