entity framework核心:在上一个操作完成之前,在此上下文中启动了第二个操作
我正在使用Entity Framework Core开发ASP.Net Core 2.0项目
在我的一个列表方法中,我收到此错误:
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 GetClients([FromRoute] int currentPage, int pageSize, string search) { var resp = new ListResponseVM(); 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(item); client.Addresses = new List(); foreach (var addr in item.Addresses) { var address = _mapper.Map(addr); address.CountryCode = addr.CountryId; client.Addresses.Add(address); } client.Contacts = item.Contacts.Select(p => _mapper.Map(p)).ToList(); client.Urls = item.Urls.Select(p => _mapper.Map(p)).ToList(); client.Objectives = item.Objectives.Select(p => _mapper.Map(p)).ToList(); resp.Items.Add(client); } return resp; }
我有点迷失,特别是因为它在我本地运行它时有效,但是当我部署到我的登台服务器(IIS 8.5)时,它会让我出现这个错误并且它正常工作。 在我增加一个模型的最大长度后,错误开始出现。 我还更新了相应视图模型的最大长度。 还有许多其他列表方法非常相似,它们正在工作。
我运行了一个Hangfire作业,但是这个作业不使用同一个实体。 这就是我能想到的所有相关内容。 有什么可能导致这个的想法?
该exception意味着_context
正被两个线程同时使用; 同一请求中的两个线程,或两个请求。
您的_context
是否可以声明为静态? 它不应该。
或者您是否在代码中的其他位置的同一请求中多次调用GetClients
?
您可能已经这样做了,但理想情况下,您将为DbContext
使用dependency injection,这意味着您将在Startup.cs中使用AddDbContext
,并且您的控制器构造函数将如下所示:
private readonly MyDbContext _context; //not static public MyController(MyDbContext context) { _context = context; }
如果您的代码不是这样,请告诉我们,也许我们可以提供更多帮助。
我不确定您是否正在使用IoC和dependency injection来解析您可能使用的DbContext。 如果您这样做并且您正在使用.NET Core中的本机IoC,请确保将DbContext注册为Transient。 做
services.AddTransient();
要么
services.AddDbContext(ServiceLifetime.Transient);
代替
services.AddDbContext();
AddDbContext将上下文添加为作用域,这可能会在处理多个线程时引起麻烦。
当使用异步lambda表达式时, async / await操作也会导致此行为。
将其添加为瞬态也有其缺点。 您将无法在使用上下文的多个类上对某个实体进行更改,因为每个类都将获得其自己的DbContext实例。
我遇到了同样的问题但原因不在于上面列出的问题。 我创建了一个任务,在任务中创建了一个范围,并要求容器获取服务。 这工作正常,但后来我在任务中使用了第二个服务,我忘了也要求它到新的范围。 因此,第二个服务使用已经处理的DbContext。
Task task = Task.Run(() => { using (var scope = serviceScopeFactory.CreateScope()) { var otherOfferService = scope.ServiceProvider.GetService(); // everything was ok here. then I did: productService.DoSomething(); // (from the main scope) and this failed because the db context associated to that service was already disposed. ... } }
我应该这样做:
var otherProductService = scope.ServiceProvider.GetService(); otherProductService.DoSomething();
我只是设法让它再次运作。 它没有多大意义,但它起作用:
- 从StartUp中删除Hangfire(我在那里创建我的工作)
- 删除了hangfire数据库
- 重启服务器
我稍后会进行调查,但是我用hangfire调用的方法会收到一个DBContext,这是可能的原因。
- 有没有为WebAPI项目生成C#HTTPClient包装器的方法?
- ASP.NET Core Web API:程序不包含适用于入口点的静态“Main”方法
- 为什么在web api中返回一个具有一对多关系的实体会导致错误?
- C# – OData:无法使用带有’new’属性的Type构建System.Web.Http.OData.Delta
- Web Api不会使用jQuery Ajax和Basic Auth下载文件
- 使用Simple Injector将依赖项注入OWIN Middleware和每个Web请求
- 如何在Web API中为所有数据成员全局设置EmitDefaultValue为false?
- 一小时后,身份从持有人令牌中消失
- validation在unit testing中失败