【问题标题】:IRepositoy.InsertOrUpdateAsync throwing concurrency exceptionIRepositoy.InsertOrUpdateAsync 抛出并发异常
【发布时间】:2019-04-14 15:33:35
【问题描述】:

我正在使用 entityframework 和 .net 核心在 ABP 上创建一个内容管理系统。使用 InsertOrUpdateAsync 时,我得到并发 exccetion。我的表中没有任何数据。

请找到用于创建表的模型。

   [Table("CMSContents")]
   public class CMSContent:Entity<int>
   {
       public const int MAXTITLELENGHT = 128;

       public const int MAXCONTENTLENGTH = 10000;

       [Key]
       [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
       public override int Id { get; set; }
       /// <summary>
       /// The title of the content.
       /// </summary>
       [Required]
       [StringLength(MAXTITLELENGHT)]
       public virtual string PageName { get;  set; }

       /// <summary>
       /// The Cms Content
       /// </summary>
       public virtual  string PageContent { get; set; }

       protected CMSContent()
       {

       }

       public static CMSContent CreateContent(int id,string title ,string contents)
       {
           var @content = new CMSContent
           {
               Id =  id, 
               PageName = title,
               PageContent = contents
           };

           return @content;
       }
   }
}

下面是用于调用存储库的应用程序服务。

public async Task<CMSContent> InsertOrUpdateCMSContent(CreateContentInput input)
        {
            var @content = CMSContent.CreateContent(input.Id,input.PageName, input.PageContent);
            return await _contentManager.InsertOrUpdateAsync(@content);
        }

从 Swagger 调用此 API 时出现异常,

Mvc.ExceptionHandling.AbpExceptionFilter - 数据库操作预计会影响 1 行,但实际上会影响 0 行。自加载实体以来,数据可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=527962。 Abp.Domain.Uow.AbpDbConcurrencyException:数据库操作预计会影响 1 行,但实际上影响了 0 行。自加载实体以来,数据可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=527962。 ---> Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预计会影响 1 行,但实际上影响了 0 行。自加载实体以来,数据可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅http://go.microsoft.com/fwlink/?LinkId=527962。 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex,Int32 expectedRowsAffected,Int32 rowsAffected) 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagationAsync(Int32 commandIndex,RelationalDataReader 阅读器,CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader 阅读器,CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection 连接,CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _,ValueTuple2 parameters, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 操作,Func4 verifySucceeded, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList1 entriesToSave,CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(布尔型 acceptAllChangesOnSuccess,CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(布尔型 acceptAllChangesOnSuccess,CancellationToken cancelToken) 在 D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\AbpDbContext.cs:line 224 中的 Abp.EntityFrameworkCore.AbpDbContext.SaveChangesAsync(CancellationTokenCancellationToken) --- 内部异常堆栈跟踪结束 --- 在 D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\AbpDbContext.cs:line 230 中的 Abp.EntityFrameworkCore.AbpDbContext.SaveChangesAsync(CancellationToken cancelToken) 在 D:\Github\aspnetboilerplate\src\Abp.ZeroCore.EntityFrameworkCore\Zero\EntityFrameworkCore\AbpZeroCommonDbContext.cs: 170 中的 Abp.Zero.EntityFrameworkCore.AbpZeroCommonDbContext`3.SaveChangesAsync(CancellationToken cancelToken) 在 D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\Uow\EfCoreUnitOfWork.cs:line 167 中的 Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.SaveChangesInDbContextAsync(DbContext dbContext) 在 D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\Uow\EfCoreUnitOfWork.cs:line 68 中的 Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.SaveChangesAsync() 在 D:\Github\aspnetboilerplate\src\Abp.EntityFrameworkCore\EntityFrameworkCore\Uow\EfCoreUnitOfWork.cs:line 83 中的 Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.CompleteUowAsync() 在 D:\Github\aspnetboilerplate\src\Abp\Domain\Uow\UnitOfWorkBase.cs:line 273 中的 Abp.Domain.Uow.UnitOfWorkBase.CompleteAsync() 在 D:\Github\aspnetboilerplate\src\Abp.AspNetCore\AspNetCore\Mvc\Uow\AbpUowActionFilter.cs:line 51 中的 Abp.AspNetCore.Mvc.Uow.AbpUowActionFilter.OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync() 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext 上下文)

【问题讨论】:

  • 从 Google 的一些结果来看,您可能需要将您的语句包装在一个工作单元中。
  • 你不应该设置Id,因为它是DatabaseGenerated
  • @aaron 由于 InsertOrUpdate 基于 id 值工作,是否应该在语句中提供?
  • @poke 你能给我一些代码示例吗?

标签: entity-framework asp.net-core asp.net-boilerplate


【解决方案1】:

我尝试了以下方法来使其工作,作为答案发布,因为评论不允许这么多字符。

      public async Task<CMSContent> InsertOrUpdateCMSContent(CreateContentInput input)
    {
        var exists = await _contentRepository
            .GetAll()
            .AnyAsync(e => e.Id == input.Id);
        if (!exists)
        {
           var @content = CMSContent.CreateContent(input.PageName, input.PageContent);
            return await _contentRepository.InsertAsync(@content);
        }
        else
        {
            var @content = CMSContent.CreateContent(input.Id, input.PageName, input.PageContent);
            return await _contentRepository.UpdateAsync(@content);
        }            
    }

【讨论】:

  • 那么它有效吗?为什么为新实体设置Id
  • @aaron 我在想 insertorupdate 方法将通过检查数据库上的 id 值来插入记录。因此,为了检查这一点,我填写了 ID。
  • 这没有意义。你用随机数填充Id
猜你喜欢
  • 2018-12-08
  • 2012-09-15
  • 2013-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多