实体框架核心线程安全吗? [英] Entity Framework Core thread safe?

查看:86
本文介绍了实体框架核心线程安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆