我有以下方法

public async Task Foo()
    {
        try
        {

            //Do stuff
            bool inserted = false;
            int tries=0;
            while (!inserted && tries<2)
            {
                try
                {
                    inserted = await Bar();
                }
                catch (Exception ex)
                {
                    //log ex and continue
                }
                finally
                {
                  if(!inserted)
                  {
                     tries++;
                  }
                }
            }
        }
        catch (Exception ex)
        {
            //log ex and continue
        }
    }




public async Task<bool> Bar()
    {
        //setup opbject to be inserted to database

        try
        {
            //the table can not have auto incrememnt so we read the max value
            objectToBeAdded.id = Context.Set<object>().Max(o => o.id) + 1;
            await Context.Set<object>().AddAsync(objectToBeAdded);
            await Context.SaveChangesAsync();
            return true;
        }
        catch (Exception ex) {
            return false;
        }
    }


该代码在多线程环境中运行,并且每分钟运行很多次,因此总是有机会发生以下异常。


  Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时发生错误。有关详细信息,请参见内部异常。 ---> MySql.Data.MySqlClient.MySqlException:键'PRIMARY'的条目'XXXXX'重复---> MySql.Data.MySqlClient.MySqlException:键'PRIMARY'的条目'XXXXX'的重复


不幸的是,这是一个很难重现的错误,我们的问题是它使应用程序崩溃,而不是重试并继续前进。

我们不能更改表以支持自动递增主键。

编辑:根据要求的完整堆栈跟踪


  -错误-无法执行DbCommand(8ms)[Parameters = [@ p0 ='?' (DbType = Int64),@ p1 ='?' (DbType =布尔),.....,@ pN ='?' (DbType =十进制)],CommandType =“文本”,CommandTimeout =“ 600”]插入到tableidcol1,.... colN)值(@ p0,@ p1,。 ... @pN);
  -错误-保存上下文类型“实体”的更改时,数据库中发生异常。 Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时发生错误。有关详细信息,请参见内部异常。 ---> MySql.Data.MySqlClient.MySqlException:键'PRIMARY'的条目'XXXXX'重复---> MySql.Data.MySqlClient.MySqlException:键'PRIMARY'的条目'XXXXXX'的重复
  在MySqlConnector.Core.ServerSession.TryAsyncContinuation(Task 1 task) in C:\.......\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 1248 at System.Threading.Tasks.ContinuationResultTaskFromResultTask 2.InnerInvoke()
  在System.Threading.ExecutionContext.RunInternal(ExecutionContext executeContext,ContextCallback回调,对象状态)
  ---从之前引发异常的位置开始的堆栈结束跟踪---
  在System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task&currentTaskSlot)
  ---从之前引发异常的位置开始的堆栈结束跟踪---
  在C:........ \ mysqlconnector \ src \ MySqlConnector \ Core \ ResultSet.cs:line 42中的MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior)
  ---内部异常堆栈跟踪的结尾---
  在C:........ \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs:line 80处的MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet(ResultSet resultSet)
  在C:.............. \ mysqlconnector \ src \ MySqlConnector \ MySql.Data.MySqlClient \ MySqlDataReader.cs:line 302的MySql.Data.MySqlClient。
  在C:.............. :第287行
  在C:..............
  在Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteAsync(IRelationalConnection连接,DbCommandMethod executeMethod,IReadOnlyDictionary 2 parameterValues, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple 2参数,CancellationToken cancelledToken)
  在Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync [TState,TResult](Func 4 operation, Func 4验证成功,TState状态,CancellationToken cancelledToken)处
  在Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync [TState,TResult](Func 4 operation, Func 4验证成功,TState状态,CancellationToken cancelledToken)处
  在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList`1 entryToSave,CancellationToken cancelToken)
  在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess,CancellationToken cancelToken)
  在Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess,CancellationToken cancelledToken)

最佳答案

据我所知,您没有从DbContext中删除​​添加的对象,因此重复键仍然存在。

你应该


要么remove(detach)
还是每次都要重新创建一个新的DbContext以确保。

关于c# - DbUpdateException-当我捕获所有异常时,出现重复的键错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54851734/

10-11 07:46