【问题标题】:ASP.NET Core 3.1 InvalidOperationException: A second operation started on this context before a previous operation completedASP.NET Core 3.1 InvalidOperationException:在前一个操作完成之前在此上下文上启动了第二个操作
【发布时间】:2022-02-04 21:31:47
【问题描述】:

在使用 _context.savechanges() 或使用存储库时,我在 asp.net core 3.1 中遇到了一些问题。

InvalidOperationException: A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext. For more information on how to avoid threading issues with DbContext, see https://go.microsoft.com/fwlink/?linkid=2097913.

更多信息出现在浏览器中,

if (bill_VM.Custoemr_selected != null)
{
    custId = bill_VM.Custoemr_selected.Id != 0 ? bill_VM.Custoemr_selected.Id : 0;
    _shoppingCart.AddCust(custId);
}
//var selectedItem = await  _context.Items.Where(p => p.Id == itemId).FirstOrDefaultAsync();
var selectedItem = _itemRepository.GetById(itemId); < ---this point
if (selectedItem != null)
{
    _shoppingCart.AddToCart(selectedItem, itemQty, AdjPrice, userid);
}
return RedirectToAction("SalesIndex", "Sales");

我的仓库

public class Repository<T> : IRepository<T> where T : class
{
    protected readonly ApplicationDbContext _context;
    public Repository(ApplicationDbContext context)
    {
        _context = context;
    }
    protected void Save() => _context.SaveChanges();
    protected async Task<int> SaveAsync() => await _context.SaveChangesAsync();
          ........ // some get and create methods are here
            public T GetById(int Id)
    {
        return _context.Set<T>().Find(Id);
    }
    private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

我的 ApplicationDbContext

     public class ApplicationDbContext : IdentityDbContext
    {

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }

        public DbSet<ApplicationUser> ApplicationUsers { get; set; }
        public DbSet<ApplicationRole> ApplicationRoles { get; set; }
        ....... // DbSet
}

服务

 services.AddIdentity<ApplicationUser, ApplicationRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();
        //start Repo
        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
        services.AddTransient<ICategoryRepository, CategoryRepository>();

任何人,请帮助我。它工作正常。在我使用事务的多重 SaveChanges 方法之前。现在我回到我之前的代码,我只使用了一个 savechanges() 。之后我收到此错误 =>(第二个操作开始...)。

  • =>任何异步等待问题...?或
  • =>不清楚 Dispose() 我的 dbcontext...?或
  • =>需要添加任何服务..?

【问题讨论】:

  • 你能发布异常的堆栈跟踪吗?你能说明ApplicationDbContext 是如何创建的吗?
  • @PauloMorgado public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext(DbContextOptions&lt;ApplicationDbContext&gt; options) : base(options) { } public DbSet&lt;ApplicationUser&gt; ApplicationUsers { get; set; } public DbSet&lt;ApplicationRole&gt; ApplicationRoles { get; set; } ........ } }
  • 我们仍然不知道实例是如何被提供给Repository&lt;T&gt;的构造函数的。
  • @Paulo 我应该通过存储库传递 T 吗?能解释清楚吗?
  • 我们需要知道异常的完整堆栈跟踪以及ApplicationDbContext 是如何被实例化的以便能够提供帮助。

标签: multithreading async-await dbcontext asp.net-core-3.1


【解决方案1】:

你尝试使用ServiceLifetime.Transient

在 startup.cs - ConfigureServices - 在配置您的数据库上下文时

services.AddDbContext<DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);

【讨论】:

  • 感谢您的建议。现在我正在对我的编码进行重大更改,我将尝试你的代码并返回结果。在此之前你能解释清楚ServiceLifetime.Transient是什么。它是如何工作的......?请。!
  • 它只是用于设置服务的生命周期,在将 db 设置为 Transient 之后,它将为每个请求创建,所以每个线程应该有它自己的 db context 'when request it',从官方阅读更多文档docs.microsoft.com/en-us/aspnet/core/fundamentals/…
  • 是的。现在我的编码工作了,谢谢你的建议。我的错误是我使用了async-await,有时我只使用dbcontext 而不使用async-await,最后,将我所有的Asynchronous呼叫(包括我在DB中的Repository Interface也改为@987654332) @)。我也试过ServiceLifetime.Transient。但事实是没有ServiceLifetime.Transient 它的工作,我只是出于安全目的使用它。 [链接](thecodebuzz.com/…)
【解决方案2】:

我可能认为这是由于 Async 和 Await 造成的。我之前也遇到过同样的问题,但我忘记了我为此做了什么。如果可行,请尝试使用同步方法。

【讨论】:

  • 是的。现在我的编码工作了,谢谢你的建议。我的错误是我使用了async-await 有时我只使用dbcontext 而不使用async-await,最后,将它打到await 我所有的Asynchronous 电话。 [链接](thecodebuzz.com/…)
【解决方案3】:

我在控制台应用程序上遇到了同样的问题,并尝试了几个建议,包括异步和等待,但没有一个奏效。

最后我在添加实体后添加了延迟,它起作用了。

                var entity = _context.Contracts.Add(contract_);
                System.Threading.Thread.Sleep(4000);//delay
                var afftected =  _context.SaveChanges();

【讨论】:

    猜你喜欢
    • 2018-11-07
    • 1970-01-01
    • 2020-09-30
    • 2020-11-06
    • 2022-01-01
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 2020-01-22
    相关资源
    最近更新 更多