首页 > 解决方案 > 更新数据时出现 SQL 错误 - 事务(进程 ID)已死锁

问题描述

假设我的应用程序应该管理水果。我有一堆规则应该用来检测我的一种水果是否有问题。您可以在下面找到负责更新这些规则检测到错误的水果的类。

我的问题是,由于我已经并行化了这个过程,我随机得到这个错误:

事务(进程 ID)在锁定资源上与另一个进程死锁,并已被选为死锁牺牲品。

我不知道我的代码有什么问题。

你可以问我任何问题,我的英语不是很完美,我已经更改了一些 var 的名称(我的应用程序不管理水果)。

public class WrongFruitBus : GenericRepository<WrongFruit>, IWrongFruitBusiness, IBaseWrong
{
    public WrongFruitBus() : base() { }
    public WrongFruitBus(ILifetimeScope _Container) : base(_Container) { }

    private readonly object currentProcessLock = new object();

    public UpdateWrongFruits {
        var CurrentProcessBus = new CurrentProcessBusiness();
        var currentProcess = new CurrentProcess();

        var FruitRulesBus = new FruitRulesBusiness(this.Container);
        var FruitViewBus = new FruitViewBusiness();

        var FruitRules = new List<FruitRule>();
        FruitRules = FruitRulesBus.GetMany(x => x.ID == entity.RulesFilterId).ToList();

        List<Task> allRules = new List<Task>();
        foreach (var fruitRule in FruitRules)
        {
            Task task = Task.Factory.StartNew(() =>
            {
                using (ILifetimeScope tempContainer = this.Container.BeginLifetimeScope())
                {
                    var tempWrongFruitBus = new WrongFruitBus(tempContainer);


                    //Get the request associate to the rule
                    var request = fruitRule.Request.JsonDeserialize<BaseFruitSearchSelectionModel>();

                    //Delete all existing detected fruits for this rule 
                    tempWrongFruitBus.GetManyWithSelector(x => x.ID, x => x.RulesFilterId == fruitRule.ID).ToList().ForEach(x => tempWrongFruitBus.Delete(x));

                    var searchList = FruitSearchHelper.BuildSearchRequest(request);
                    var Ids = FruitViewBus.GetCustomList(null, null, searchList, null, null);

                    var RulesLists = Ids
                        .Results
                        .Cast<FruitResult>()
                        .Select(x =>
                            new WrongFruit()
                            {
                                FruitId = x.UId,
                                RulesFilterId = FruitRule.ID,

                            }).ToList();
                    RulesLists.ForEach(x => tempWrongFruitBus.Add(x));

                    tempWrongFruitBus._BusinessUnitOfWork.Commit();

                    //Update of the process progression
                    int PercentageAdvancement = 100 / NumberOfRules;

                    lock (currentProcessLock)
                    {
                        currentProcess = CurrentProcessBus.Get(x => x.TaskName == entity.TaskName);
                        currentProcess.TaskAdvancement = currentProcess.TaskAdvancement + PercentageAdvancement;
                        if (currentProcess.TaskAdvancement > 100)
                        {
                            currentProcess.TaskAdvancement = 100;
                        }
                        CurrentProcessBus.Update(currentProcess);
                    }
                } 
            });
            allRules.Add(task);
        }
        Task.WaitAll(allRules.ToArray());
    }
}

服务器的日志文件

UncaGS.WCF.ErrorHandler.HandleError(:0) System.ServiceModel.Dispatcher.ChannelHandler.AsyncMessagePump > System.ServiceModel.Dispatcher.ChannelHandler.HandleRequest > System.ServiceModel.Dispatcher.ChannelHandler.DispatchAndReleasePump > System.ServiceModel.Dispatcher.MessageRpc.Process > System.ServiceModel.Dispatcher.MessageRpc.ProcessError > System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage8

System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage9 System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessageCleanup System.ServiceModel.Dispatcher.ErrorBehavior.HandleErrorCommon > UncaGS.WCF.ErrorHandler.HandleError System.Reflection.TargetInvocationException: Une exception a été levée par la cible d '不上诉。---> System.Data.Entity.Core.EntityCommandExecutionException:从商店提供者的数据读取器读取时出错。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:事务(进程 ID 57)与另一个进程在锁资源上死锁,并已被选为死锁受害者。à System.Data.SqlClient.SqlConnection.OnError(SqlException 异常, Boolean breakConnection, Action1 wrapCloseInAction) à System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) à System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) à System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows) à System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more) à System.Data.SqlClient.SqlDataReader.Read() à System.Data.Entity.Core.Common.Internal.Materialization.Shaper1.StoreRead() --- Fin de la trace de la Pile d'exception interne --- à System.Data.Entity.Core.Common.Internal.Materialization.Shaper 1.HandleReaderException(Exception e) à System.Data.Entity.Core.Common.Internal.Materialization.Shaper1.StoreRead() à System.Data.Entity。 Core.Common.Internal.Materialization.Shaper 1.SimpleEnumerator.MoveNext() à System.Collections.Generic.List1..ctor(IEnumerable 1 source) à UncaGS.WcfServices.Repositories.Infrastructure.ReadOnlyGenericRepositoryBase 1 选择器,表达式1 collection)
à System.Linq.Enumerable.ToList[TSource](IEnumerable
1.GetManyWithSelector[TOutput](Int32 startAt, Int32 take, Expression1 where, Expression1 orderBy, Expression`1[] includeProperties) --- Fin de la trace de la pile d'exception interne --- à System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)à System .Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) → System.Delegate.DynamicInvokeImpl(Object[] args) → UncaGS.WcfServices.Services.GenericService.GenericService.GenericServiceWorker.ExecuteRequest(CallMethodContractBase callMethodContract,类型 repositoryType) à UncaGS.WcfServices.Services.GenericService.GenericService.GenericServiceWorker.Execute(CallMethodContractBase callMethodContract) à UncaGS.WcfServices.Services.GenericService.GenericService。ExecuteMethod(CallMethodContractBase callMethodContract) à SyncInvokeExecuteMethod(Object , Object[] , Object[] ) à System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] 输入, Object[]& 输出) à System.ServiceModel.Dispatcher。 DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) à System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) à System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) à System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) à System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) à System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) à System.ServiceModel.Dispatcher.MessageRpc.Process(布尔 isOperationContextSet)ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) à System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) à System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) à System.ServiceModel.Dispatcher.MessageRpc.Process(布尔 isOperationContextSet)

标签: c#sqlsql-serverentity-frameworkdeadlock

解决方案


推荐阅读