Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# DbUpdateException-捕获所有异常时,复制密钥错误不会受到影响_C#_Mysql_Entity Framework Core - Fatal编程技术网

C# DbUpdateException-捕获所有异常时,复制密钥错误不会受到影响

C# DbUpdateException-捕获所有异常时,复制密钥错误不会受到影响,c#,mysql,entity-framework-core,C#,Mysql,Entity Framework Core,我有以下方法 public async Task Foo() { try { //Do stuff bool inserted = false; int tries=0; while (!inserted && tries<2) { try {

我有以下方法

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
        }
    }
公共异步任务Foo()
{
尝试
{
//做事
bool-inserted=false;
int=0;
而(!inserted&&try o.id)+1;
wait Context.Set().AddAsync(objectToBeAdded);
wait Context.saveChangesSync();
返回true;
}
捕获(例外情况除外){
返回false;
}
}
代码在多线程环境中运行,每分钟运行多次,因此始终有可能出现以下异常

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

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

我们无法更改表以支持自动递增主键

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

-错误-执行DbCommand(8ms)[参数=[@p0='?'(DbType=Int64),@p1='?'(DbType=Boolean),…,@pN='?'(DbType=Decimal)],CommandType='Text',CommandTimeout='600']插入
id
col1
,…
colN
)值(@p0,@p1,../pN); -错误-保存对上下文类型“Entities”的更改时,数据库中发生异常。Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参见内部异常。-->MySql.Data.MySqlClient.MySqlException:键“PRIMARY”的重复条目“XXXXX”-->MySql.Data.MySqlClient.MySqlException:键“PRIMARY”的重复条目“XXXXXX” 在C:\…\MySqlConnector\src\MySqlConnector\Core\ServerSession.tryasyncontuation(Task
1 Task)中的MySqlConnector.Core.ServerSession.tryasyncontuation处:第1248行
位于System.Threading.Tasks.ContinuationResultTaskFromResultTask
2.InnerInvoke() 位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext,ContextCallback回调,对象状态) ---来自引发异常的上一个位置的堆栈结束跟踪--- 位于System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task和currentTaskSlot) ---来自引发异常的上一个位置的堆栈结束跟踪--- 在C中的MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior IOBehavior)处:…..\MySqlConnector\src\MySqlConnector\Core\ResultSet.cs:第42行 ---内部异常堆栈跟踪的结束--- 在C:..\mysqlconnector\src\mysqlconnector\MySql.Data.MySqlDataReader.ActivateResultSet(ResultSet ResultSet)中的MySql.Data.MySqlClient.MySqlDataReader.cs:第80行 在C中的MySql.Data.MySqlClient.MySqlDataReader.ReadFirstResultSetAsync(IOBehavior IOBehavior)处:…..\mysqlconnector\src\mysqlconnector\MySql.Data.MySqlClient\MySqlDataReader.cs:第302行 在C中的MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(MySqlCommand命令,CommandBehavior,ResultSetProtocol ResultSetProtocol,IOBehavior IOBehavior)处:…\mysqlconnector\src\mysqlconnector\MySql.Data.MySqlClient\MySqlDataReader.cs:第287行 在C中的MySqlConnector.Core.TextCommandExecutor.ExecuteReaderAsync(字符串commandText,MySqlParameterCollection参数Collection,CommandBehavior,IOBehavior,IOBehavior,CancellationToken CancellationToken)处:…..\MySqlConnector\src\MySqlConnector\Core\TextCommandExecutor.cs:第37行 在Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteAsync(IRelationalConnection连接,DbCommandMethod executeMethod,iRelationalDYDictionary
2参数值,CancellationToken CancellationToken)
位于Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection连接,CancellationToken CancellationToken)
---内部异常堆栈跟踪的结束---
位于Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection连接,CancellationToken CancellationToken)
在Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext,ValueTuple
2参数,CancellationToken CancellationToken) 在Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func
4操作,Func
4验证成功,TState状态,CancellationToken CancellationToken) 在Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func
4操作,Func
4验证成功,TState状态,CancellationToken CancellationToken) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesSync(IReadOnlyList`1 EntriesToken保存,CancellationToken CancellationToken) 位于Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesSync(布尔接受ChangesOnSuccess,CancellationToken CancellationToken) 在Microsoft.EntityFrameworkCore.DbContext.SaveChangesSync(布尔值AcceptillChangesOnSuccess,CancellationToken CancellationToken)


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

你应该

  • 要么
  • 或者每次从头开始创建一个新的
    DbContext
    ,以确保安全

  • 就我所见,您没有从
    DbContext
    中删除添加的对象,因此重复键仍然存在

    你应该

  • 要么
  • 或者每次从头开始创建一个新的
    DbContext
    ,以确保安全

  • 我想,让这个错误难以重现的原因是,代码是异步运行的。 您通过在中查询当前最大id来获取新的最大id
    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;
            }
        }
    
    private object _lockObject = new object();
    public async Task<bool> Bar()
    {
       //setup object to be inserted to database
    
        try
        {
            // lock your changes, so they run in a safe order
            lock (_lockObject)
            {
                //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;
        }
    }