Esempio n. 1
0
        /// <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;
            }));
        }
Esempio n. 3
0
        /// <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);
            }));
        }
Esempio n. 4
0
        /// <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);
        }
Esempio n. 5
0
        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);
            }
        }