实体框架核心线程安全吗?

nam*_* vo 8 c# asp.net-mvc entity-framework

我遵循ASP.NET Core 中的通用存储库模式,但在IRepository,我使用IQueryable而不是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);
}
Run Code Online (Sandbox Code Playgroud)

和实现类:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

服务等级:

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);
        }
}
Run Code Online (Sandbox Code Playgroud)

在 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>();
    }
Run Code Online (Sandbox Code Playgroud)

此代码引发错误:

InvalidOperationException:在上一个操作完成之前,在此上下文中启动了第二个操作。不保证任何实例成员都是线程安全的。

如果我切换回IEnumerableon IRepository,那么它运行良好。

知道如何让它工作IQueryable,使 EF Core 以正确的方式运行吗?

query = from m in query
        where categoryIds.Contains(m.CategoryId)
        select m;
Run Code Online (Sandbox Code Playgroud)

And*_*nov 9

实体框架DbContext不是线程安全的。您一次只能执行一个查询,否则您会像上面那样得到异常。

我想您在同一请求期间多次使用我们的存储库,这就是您收到异常的原因。如果您不为每个请求创建一个事务,您可以简单地使存储库成为瞬态。在这种情况下,将为您的服务的每个实例创建新的存储库,您将避免并发问题。