using JLHHJSvr.BLL; using JLHHJSvr.Com.Model; using JLHHJSvr.LJException; using LJLib.DAL.SQL; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.ComponentModel; using NPOI.SS.Formula; using System.Web.Configuration; namespace JLHHJSvr.Helper { internal class LockHelper : HelperBase { /// /// 加锁单据 /// /// /// public static void LockBill(SqlCommand cmd, string keyword, int billid, string billcode,string opemp, int lockMinutes = 30) { //return; try { cmd.CommandText = "sp_lock_record"; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@keyword", keyword); cmd.Parameters.AddWithValue("@billid", billid); cmd.Parameters.AddWithValue("@billcode", billcode); cmd.Parameters.AddWithValue("@opemp", opemp); cmd.Parameters.AddWithValue("@lockMinutes", lockMinutes); using (var reader = cmd.ExecuteReader()) { if (reader.Read()) { var arg_rslt = Convert.ToInt32(reader["arg_rslt"]); var arg_msg = Convert.ToString(reader["arg_msg"]); //if (arg_rslt != 1) throw new LJCommonException(arg_msg); } } } finally { cmd.CommandType = CommandType.Text; cmd.CommandText = string.Empty; } } /// /// 解锁单据 /// /// /// public static void UnLockBill(SqlCommand cmd, string keyword, int billid, string opemp, byte is_admin) { //return; try { cmd.CommandText = "sp_unlock_record"; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@keyword", keyword); cmd.Parameters.AddWithValue("@billid", billid); cmd.Parameters.AddWithValue("@opemp", opemp); cmd.Parameters.AddWithValue("@is_admin", is_admin); using (var reader = cmd.ExecuteReader()) { if (reader.Read()) { var arg_rslt = Convert.ToInt32(reader["arg_rslt"]); var arg_msg = Convert.ToString(reader["arg_msg"]); if (arg_rslt != 1) throw new LJCommonException(arg_msg); } } } finally { cmd.CommandType = CommandType.Text; cmd.CommandText = string.Empty; } } /// /// 生成锁提示信息 /// private static string GetLockMessage(SqlCommand cmd, string keyword, string billcode, string opEmp) { string billName = BillNames.GetBillCnName(keyword); return $"{billName}【{billcode}】被用户【{opEmp}】编辑中。"; } #region /// /// DFS方式检查单据及其依赖的锁 /// public static u_lock_table CheckLockAll(SqlCommand cmd, string keyword, int billid, string opemp) { var visited = new Dictionary(); // 防止循环依赖 return GetLockBill(cmd, keyword, billid, opemp, visited); } /// /// 检查单据是否上锁 /// /// /// /// /// /// /// public static bool CheckIsLock(SqlCommand cmd, string keyword, int billid, string opemp,out string arg_msg) { arg_msg = string.Empty; //return false; var item = CheckLockAll(cmd, keyword, billid, opemp); if (item.Code == LockCheckResultCode.LockedByOther) { arg_msg = item.log_msg; return true; } return !(item.Code == LockCheckResultCode.Success || item.Code == LockCheckResultCode.LockedBySelf); } /// /// DFS方式检查单据及依赖链上的锁 /// private static u_lock_table GetLockBill(SqlCommand cmd, string keyword, int billid, string opemp, Dictionary visited) { var key = $"{keyword}:{billid}"; if (visited.TryGetValue(key, out var state)) { if (state == 1) throw new InvalidOperationException($"检测到循环依赖: {key}"); if (state == 2) return new u_lock_table { keyword = keyword, billid = billid, Code = LockCheckResultCode.Success }; } visited[key] = 1; // 标记正在访问 // var mainLock = new u_lock_table { keyword = keyword, billid = billid }; DbSqlHelper.SelectOne(cmd,"u_lock_table","keyword = @keyword AND billid = @billid AND is_locked = 1", new Dictionary { { "@keyword", keyword }, { "@billid", billid } }, mainLock, "keyword,billid,billcode,opemp,is_locked,lock_time,expire_time"); if (mainLock.expire_time < DateTime.Now) mainLock.Code = LockCheckResultCode.Expired; if (mainLock.is_locked == 1) { mainLock.Code = mainLock.opemp.Equals(opemp) ? LockCheckResultCode.LockedBySelf : LockCheckResultCode.LockedByOther; mainLock.log_msg = GetLockMessage(cmd, keyword, mainLock.billcode, mainLock.opemp); return mainLock; } visited[key] = 2; // 标记完成 // var dependencies = BuildDependencies(cmd, keyword, billid); foreach (var dep in dependencies) { var depResult = GetLockBill(cmd, dep.keyword, dep.billid, opemp, visited); if (depResult.Code == LockCheckResultCode.LockedBySelf || depResult.Code == LockCheckResultCode.LockedByOther) return depResult; } mainLock.Code = LockCheckResultCode.Success; return mainLock; } /// /// 根据单据类型构造依赖关系 /// private static List BuildDependencies(SqlCommand cmd, string keyword, int billid) { var dependencies = new List(); if (BillNames.MattressQuote.Equals(keyword)) { dependencies.Add(new u_lock_table { keyword = BillNames.MattressInterface, billid = billid }); var bednetList = GetHelper(cmd) .GetMattressMxMtrl(billid, new List { "u_mattress_formula.formulatype = 99" }); foreach (var bednet in bednetList) { dependencies.Add(new u_lock_table { keyword = BillNames.BedNetQuote, billid = bednet.mtrlid.Value }); } } else if (BillNames.MattressInterface.Equals(keyword)) { dependencies.Add(new u_lock_table { keyword = BillNames.MattressQuote, billid = billid }); } else if (BillNames.BedNetQuote.Equals(keyword)) { var mattressList = GetHelper(cmd) .GetMattressMxMtrl(0, new List { $"u_mattress_formula.formulatype = 99 AND vv_bednet.bednetid = {billid}" }); var idsList = mattressList.GroupBy(t => t.mattressid.Value).Select(t => t.Key).ToList(); foreach (var id in idsList) { dependencies.Add(new u_lock_table { keyword = BillNames.MattressQuote, billid = id }); } } return dependencies; } #endregion } }