I am new to .NET. I have micro services using .NET Core. This service is used to become a Kafka consumer. In the consumer function there is a function to insert into the SQL Server database. This function often experiences deadlock
errors, but sometime when traffic is low this code work with no error. I attached the function code. This function is simple, just to insert into the database using the transaction set identity insert on
. Please help if anyone has experienced something like this. The error looks like this.
An exception occurred in the database while saving changes for context type 'Entities.RepositoryContext'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details.
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 414) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
private async Task insertData(Dto data)
{
var dataFromDB = _repository.myRepo.FirstOrDefaultWithNoLock(p => p.ID.Equals(data.ID));
if (dataFromDB == null)
{
dataFromDB = _mapper.Map<Model>(data);
_repository.myRepo.Create(dataFromDB);
_repository.myRepo.SaveChangesWithIdentityInsert();
return;
}
return;
}
I attached code inside SaveChangesWithIdentityInsert
public static void EnableIdentityInsert<T>(this DbContext context) => SetIdentityInsert<T>(context, true);
public static void DisableIdentityInsert<T>(this DbContext context) => SetIdentityInsert<T>(context, false);
private static void SetIdentityInsert<T>([NotNull] DbContext context, bool enable)
{
if (context == null) throw new ArgumentNullException(nameof(context));
var entityType = context.Model.FindEntityType(typeof(T));
var value = enable ? "ON" : "OFF";
context.Database.ExecuteSqlRaw($"SET IDENTITY_INSERT dbo.{entityType.GetTableName()} {value}");
}
public static void SaveChangesWithIdentityInsert<T>([NotNull] this DbContext context)
{
if (context == null) throw new ArgumentNullException(nameof(context));
var strategy = context.Database.CreateExecutionStrategy();
strategy.Execute(
() =>
{
using var transaction = context.Database.BeginTransaction(isolationLevel: System.Data.IsolationLevel.ReadUncommitted);
context.EnableIdentityInsert<T>();
context.SaveChanges();
context.DisableIdentityInsert<T>();
transaction.Commit();
});
context.ChangeTracker.Clear();
}
I have try to use with no lock
. I have searching to auto retry consumer when deadlock occur but not found anything.