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

时间:2017-04-15 09:59:22

标签: c# asp.net-mvc entity-framework

我关注Generic Repository Pattern in 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);
}

和实现类:

    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上:

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

如果我在IEnumerable上切换回IRepository,那么它运行正常。

知道如何让它与IQueryable一起使用,让EF Core以正确的方式运行吗?

query = from m in query
        where categoryIds.Contains(m.CategoryId)
        select m;

1 个答案:

答案 0 :(得分:3)

实体框架DbContext不是线程安全的。您一次只能执行一个查询,否则您将获得如上所述的异常。

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