实体框架核心:在上一个操作完成之前,在此上下文上启动了第二个操作 [英] Entity Framework Core: A second operation started on this context before a previous operation completed

查看:312
本文介绍了实体框架核心:在上一个操作完成之前,在此上下文上启动了第二个操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Entity Framework Core进行ASP.Net Core 2.0项目

I'm working on a ASP.Net Core 2.0 project using Entity Framework Core

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.1" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0"/>

在我的一种列表方法中,出现此错误:

And in one of my list methods I'm getting this error:

InvalidOperationException: A second operation started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe.
Microsoft.EntityFrameworkCore.Internal.ConcurrencyDetector.EnterCriticalSection()

这是我的方法:

    [HttpGet("{currentPage}/{pageSize}/")]
    [HttpGet("{currentPage}/{pageSize}/{search}")]
    public ListResponseVM<ClientVM> GetClients([FromRoute] int currentPage, int pageSize, string search)
    {
        var resp = new ListResponseVM<ClientVM>();
        var items = _context.Clients
            .Include(i => i.Contacts)
            .Include(i => i.Addresses)
            .Include("ClientObjectives.Objective")
            .Include(i => i.Urls)
            .Include(i => i.Users)
            .Where(p => string.IsNullOrEmpty(search) || p.CompanyName.Contains(search))
            .OrderBy(p => p.CompanyName)
            .ToPagedList(pageSize, currentPage);

        resp.NumberOfPages = items.TotalPage;

        foreach (var item in items)
        {
            var client = _mapper.Map<ClientVM>(item);

            client.Addresses = new List<AddressVM>();
            foreach (var addr in item.Addresses)
            {
                var address = _mapper.Map<AddressVM>(addr);
                address.CountryCode = addr.CountryId;
                client.Addresses.Add(address);
            }

            client.Contacts = item.Contacts.Select(p => _mapper.Map<ContactVM>(p)).ToList();
            client.Urls = item.Urls.Select(p => _mapper.Map<ClientUrlVM>(p)).ToList();
            client.Objectives = item.Objectives.Select(p => _mapper.Map<ObjectiveVM>(p)).ToList();
            resp.Items.Add(client);
        }

        return resp;
    }

我有点迷茫,特别是因为它在本地运行时可以工作,但是当我部署到我的登台服务器(IIS 8.5)时,我得到了这个错误,并且它可以正常工作.当我增加一个模型的最大长度后,该错误开始出现.我还更新了相应视图模型的最大长度.而且还有许多其他列表方法非常相似,并且都可以使用.

I'm a bit lost especially because it works when I run it locally, but when I deploy to my staging server (IIS 8.5) it gets me this error and it was working normally. The error started to appear after I increase the max length of one of my models. I also updated the max length of the corresponding View Model. And there are many other list methods that are very similar and they are working.

我正在运行一个Hangfire作业,但是该作业没有使用相同的实体.我认为这就是很重要的.关于什么可能导致这种情况的任何想法?

I had a Hangfire job running, but this job doesn't use the same entity. That's all I can think to be relevant. Any ideas of what could be causing this?

推荐答案

我不确定您是否正在使用IoC和依赖注入在任何可能使用DbContext的地方进行解析.如果这样做,并且您正在使用来自.NET Core(或任何其他IoC-Container)的本机IoC,并且遇到此错误,请确保将DbContext注册为瞬态.做

I am not sure if you are using IoC and Dependency Injection to resolve your DbContext where ever it might be used. If you do and you are using native IoC from .NET Core (or any other IoC-Container) and you are getting this error, make sure to register your DbContext as Transient. Do

services.AddTransient<MyContext>();

OR

services.AddDbContext<MyContext>(ServiceLifetime.Transient);

代替

services.AddDbContext<MyContext>();

AddDbContext将上下文添加为作用域,这可能在使用多个线程时引起麻烦.

AddDbContext adds the context as scoped, which might cause troubles when working with multiple threads.

使用异步Lambda表达式时,异步/等待操作可能会导致这种行为.

Also async / await operations can cause this behaviour, when using async lambda expressions.

将其添加为瞬态也有其缺点.您将无法在使用上下文的多个类上对某些实体进行更改,因为每个类都将获得自己的DbContext实例.

Adding it as transient also has its downsides. You will not be able to make changes to some entity over multiple classes that are using the context because each class will get its own instance of your DbContext.

对此的简单解释是,DbContext实现不是线程安全的.您可以阅读有关此此处

The simple explanation for that is, that the DbContext implementation is not thread-safe. You can read more about this here

这篇关于实体框架核心:在上一个操作完成之前,在此上下文上启动了第二个操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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