c# - Entity Framework 核心线程安全吗?

标签 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: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.

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

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

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

最佳答案

Entity Framework DbContext 不是线程安全的。你一次只能执行一个查询,否则你会像上面那样得到一个异常。

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

关于c# - Entity Framework 核心线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43424674/

相关文章:

c# - 使用 Json.Net 反序列化,将子对象反序列化为包含 json 的字符串/类似字符串?

c# - Html Helper 可能缓存输入值

mysql - 将 MySQL 存储过程添加到 Entity Framework 上下文时出现外键约束错误

performance - LINQ AsNoTracking 运行缓慢

linq - C# Generic List.Any() 抛出 System.NullReferenceException

c# - 我如何将 C# string[] 编码(最好在 SWIG 中)到 C++ string*?

c# - 什么是根目录或如何在 DotNetZip 中设置目录

json - Web.config 在 Asp.net 5 mvc6 中消失了,非 Web 配置怎么样?

c# - GridView 检索每一行中的数据

c# - 将 product.GetSeName() 更改为 Product.SeName Nopcommerce 2.40