public void RemoveAuthorWithBooksUsingTransaction()
        {
            var transactionTask = new TransactionTask(dbContext =>
            {
                var firstAuthor = dbContext.Set <Author>().FirstOrDefault(a => a.Books.Any());

                dbContext.Remove(firstAuthor);

                dbContext.SaveChanges();
            });

            var transanctionTaskResult = transactionTaskManager.UseTransaction(transactionTask);

            transanctionTaskResult.Failure.Should().BeTrue();
            transanctionTaskResult.Exception.Should().BeAssignableTo <DbUpdateException>();
        }
        private TransactionTaskResult TryUseTransaction(TransactionTask transactionTask)
        {
            using (var dbContext = _newDbContext())
                using (var transaction = dbContext.Database.BeginTransaction())
                    try
                    {
                        transactionTask.Action(dbContext);
                        dbContext.SaveChanges();

                        transaction.Commit();

                        var transactionTaskSuccess = new TransactionTaskResult(transaction.TransactionId, transactionTask);
                        return(transactionTaskSuccess);
                    }
                    catch (Exception e)
                    {
                        transaction.Rollback();
                        var transactionTaskFailure = new TransactionTaskResult(transaction.TransactionId, transactionTask, e);
                        return(transactionTaskFailure);
                    }
        }
        public void InsertAndUpdateBooksUsingTransaction()
        {
            var newAuthor = fakerAuthor.Generate();

            var transactionTask = new TransactionTask(dbContext =>
            {
                var authorDbSet = dbContext.Set <Author>();
                var bookDbSet   = dbContext.Set <Book>();

                authorDbSet.Add(newAuthor);
                var authorsInserted = dbContext.SaveChanges();

                var firstAuthor      = authorDbSet.FirstOrDefault();
                var booksFirstAuthor = bookDbSet.AsTracking().Where(b => b.AuthorId == firstAuthor.AuthorId).ToList();

                booksFirstAuthor.ForEach(b => b.AuthorId = newAuthor.AuthorId);
                var booksUpdated = dbContext.SaveChanges();
            });

            var transanctionTaskResult = transactionTaskManager.UseTransaction(transactionTask);

            transanctionTaskResult.Success.Should().BeTrue();
        }
예제 #4
0
 /// <summary>
 /// 取分布式锁(基于DB方式)
 /// </summary>
 /// <param name="moduleFlag">模块标识,模块表名/类名</param>
 /// <param name="method_Flag">方法名标识</param>
 /// <param name="expirtime">自定义过期时间(秒)</param>
 /// <param name="des">锁描述</param>
 /// <returns></returns>
 public static string DistributeDbLock(string moduleFlag, string method_Flag, double?expirtime = null, string des = null)
 {
     try
     {
         if (WebConfigHelper.GetAppSettingValue("EnabledDistributeLock") != "true") //未启用分布式锁
         {
             return(string.Empty);
         }
         string hostname  = System.Net.Dns.GetHostName();            //当前服务器
         string processId = ApplicationObject.GetCurrentProcessId(); //当前进程
         string threadId  = ApplicationObject.GetCurrentThreadId();  //当前线程
         lock (tempObjDistriLock)
         {
             string       errMsg   = string.Empty;
             int          timeout  = 30; //30秒超时
             DateTime     initTime = DateTime.Now;
             DatabaseType dbType   = DatabaseType.MsSqlServer;
             string       connStr  = ModelConfigHelper.GetModelConnStr(typeof(Other_DistributedLock), out dbType, false);
             while ((DateTime.Now - initTime).TotalSeconds <= timeout)
             {
                 double updateTimesamp            = Globals.GetTimestamp(DateTime.Now);                                                                 //当前时间戳
                 double invalidTimesamp           = expirtime.HasValue && expirtime.Value > 0 ? updateTimesamp + expirtime.Value : updateTimesamp + 20; //过期时间戳
                 Other_DistributedLock methodLock = CommonOperate.GetEntity <Other_DistributedLock>(x => x.ModuleFlag == moduleFlag && x.Method_Flag == method_Flag && x.Invalid_Timesamp > updateTimesamp, null, out errMsg);
                 //锁存在,继续循环再取
                 if (methodLock != null)
                 {
                     Thread.Sleep(10);
                     continue;
                 }
                 //锁不存在,取得锁成功,插入锁标识
                 methodLock = new Other_DistributedLock()
                 {
                     ModuleFlag       = moduleFlag,
                     Method_Flag      = method_Flag,
                     Update_Timesamp  = updateTimesamp,
                     Invalid_Timesamp = invalidTimesamp,
                     Maching          = hostname,
                     ProcessId        = processId,
                     ThreadId         = threadId,
                     Des = des
                 };
                 TransactionTask tranAction = (conn) =>
                 {
                     CommonOperate.DeleteRecordsByExpression <Other_DistributedLock>(x => x.ModuleFlag == moduleFlag && x.Method_Flag == method_Flag, out errMsg, false, connStr, dbType, conn);
                     if (!string.IsNullOrEmpty(errMsg))
                     {
                         throw new Exception(errMsg);
                     }
                     CommonOperate.OperateRecord <Other_DistributedLock>(methodLock, ModelRecordOperateType.Add, out errMsg, null, false, false, connStr, dbType, conn);
                     if (!string.IsNullOrEmpty(errMsg))
                     {
                         throw new Exception(errMsg);
                     }
                 };
                 CommonOperate.TransactionHandle(tranAction, out errMsg, connStr, dbType);
                 //取锁成功
                 if (string.IsNullOrEmpty(errMsg))
                 {
                     return(string.Empty);
                 }
                 else
                 {
                     WritLockLog(moduleFlag, method_Flag, errMsg);
                 }
                 //取锁失败,继续循环取
                 Thread.Sleep(10);
             }
             return("获取分布式锁超时"); //取锁失败
         }
     }
     catch
     {
         return(string.Empty);
     }
 }
예제 #5
0
 /// <summary>
 /// 执行事务
 /// </summary>
 /// <param name="transTask">事务处理函数</param>
 /// <param name="errorMsg">异常信息</param>
 /// <param name="connString">数据库连接字符串</param>
 public abstract void TransactionHandle(TransactionTask transTask, out string errorMsg, string connString = null);
예제 #6
0
 /// <summary>
 /// 执行事务
 /// </summary>
 /// <param name="transTask">事务处理函数</param>
 /// <param name="errorMsg">异常信息</param>
 /// <param name="connString">数据库连接字符串</param>
 public void TransactionHandle(TransactionTask transTask, out string errorMsg, string connString = null)
 {
     errorMsg = string.Empty;
     _dal.TransactionHandle(transTask, out errorMsg, connString);
 }
 public TransactionTaskResult UseTransaction(TransactionTask transactionTask)
 => transactionTask is null
         ? throw new ArgumentNullException(nameof(transactionTask))