我有以下方法
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”]插入到
table
(id
,col1
,.... 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/