/// <summary> /// 参加指定标识的分布式事务,直到事务执行完成。一个分布式事务包含若干本地事务 /// </summary> /// <param name="identity">标识一个分布式事务</param> /// <returns></returns> public bool AttendTransaction(string identity) { DistTransInfo info = new DistTransInfo(); info.ClientIdentity = base.CurrentContext.Request.ClientIdentity; info.CurrentDTCState = DistTrans3PCState.CanCommit; info.LastStateTime = DateTime.Now; info.TransIdentity = identity; //DTResourceList.Add(info); DateTime dtcStart = DateTime.Now; //获取一个当前事务标识的协调器线程 DTController controller = DTController.CheckStartController(identity); CurrentDTCState = DistTrans3PCState.CanCommit; while (CurrentDTCState != DistTrans3PCState.Completed) { //获取资源服务器的事务状态,资源服务器可能自身或者因为网络情况出错 if (!SendDTCState(info, controller, identity)) { break; } } SendDTCState(info, controller, identity); DTController.RemoveController(identity); Console.WriteLine("DTC Current Use time:{0}(s)", DateTime.Now.Subtract(dtcStart).TotalSeconds); return(true); }
/// <summary> /// 生成订单的服务方法 /// </summary> /// <param name="orderId">订单号</param> /// <param name="userId">用户号</param> /// <param name="buyItems">购买的商品简要清单</param> /// <returns>订单是否创建成功</returns> public bool CreateOrder(int orderId, int userId, IEnumerable <BuyProductDto> buyItems) { //在分布式事务的发起端,需要先定义分布式事务标识: string DT_Identity = System.Guid.NewGuid().ToString(); //使用3阶段提交的分布式事务,保存订单到数据库 OrderDbContext context = new OrderDbContext(); DTController controller = new DTController(DT_Identity); return(controller.DistTrans3PCRequest <bool>(DTS_Proxy, context.CurrentDataBase, db => { //先请求商品服务,扣减库存,并获取商品的仓库信息 ServiceRequest request = new ServiceRequest(); request.ServiceName = "ProductService"; request.MethodName = "UpdateProductOnhand"; request.Parameters = new object[] { DT_Identity, buyItems }; List <SellProductDto> sellProducts = productProxy.RequestServiceAsync <List <SellProductDto> >(request).Result; #region 构造订单明细和订单对象 // List <OrderItemEntity> orderItems = new List <OrderItemEntity>(); OrderEntity order = new OrderEntity() { ID = orderId, OwnerID = userId, OrderTime = DateTime.Now, OrderName = "Prudoct:" }; foreach (BuyProductDto item in buyItems) { //注意:在商品数据库上,前面更新商品,但还没有提交事务,下面这个查询直接使用的话会导致查询等待,因为SQLSERVER的事务隔离级别是这样的 //所以 GetProductInfo 的实现需要注意。 ProductDto product = this.GetProductInfo(item.ProductId).Result; OrderItemEntity temp = new OrderItemEntity() { OrderID = orderId, ProductID = product.ID, BuyNumber = item.BuyNumber, OnePrice = product.Price, ProductName = product.ProductName }; temp.StoreHouse = (from i in sellProducts where i.ProductId == temp.ProductID select i.StoreHouse).FirstOrDefault(); orderItems.Add(temp); order.OrderName += "," + temp.ProductName; order.AmountPrice += temp.OnePrice * temp.BuyNumber; } // #endregion //保存订单数据到数据库 context.Add <OrderEntity>(order); context.AddList <OrderItemEntity>(orderItems); return true; })); }
/// <summary> /// 更新商品库存,并返回商品售卖简要信息 /// </summary> /// <param name="transIdentity">分布式事务标识</param> /// <param name="buyItems">购买的商品精简信息</param> /// <returns></returns> public List <SellProductDto> UpdateProductOnhand(string transIdentity, IEnumerable <BuyProductDto> buyItems) { ProductDbContext context = new ProductDbContext(); DTController controller = new DTController(transIdentity); return(controller.DistTrans3PCRequest <List <SellProductDto> >(DTS_Proxy, context.CurrentDataBase, c => { return InnerUpdateProductOnhand(context, buyItems); })); }
/// <summary> /// 检查并开启一个分布式事务协调器对象 /// </summary> /// <param name="transIdentity"></param> /// <returns></returns> public static DTController CheckStartController(string transIdentity) { DTController controller = null; lock (sync_obj) { if (dictDTC.ContainsKey(transIdentity)) { controller = dictDTC[transIdentity]; } else { controller = new DTController(transIdentity); dictDTC.Add(transIdentity, controller); } } controller.AddResourceCount(); return(controller); }
private bool SendDTCState(DistTransInfo info, DTController controller, string identity) { string clientIdentity = string.Format("[{0}:{1}-{2}]", base.CurrentContext.Request.ClientIP, base.CurrentContext.Request.ClientPort, base.CurrentContext.Request.ClientIdentity); try { Console.WriteLine("DTC Service Callback {0} Message:{1}", clientIdentity, CurrentDTCState); info.CurrentDTCState = base.CurrentContext.CallBackFunction <DistTrans3PCState, DistTrans3PCState>(CurrentDTCState); info.LastStateTime = DateTime.Now; CurrentDTCState = controller.GetDTCState(info.CurrentDTCState); return(true); } catch (Exception ex) { Console.WriteLine("DTC Service Callback {0} Error:{1}", clientIdentity, ex.Message); return(false); } }