在Entity Framework 6.0中实现具有多个DB上下文类的事务逻辑单个数据库的最佳方法

时间:2015-07-21 06:02:37

标签: c# transactions asp.net-mvc-5 entity-framework-6

任何曾经建议我如何为具有多个上下文类的相同数据库实现实体事务逻辑。

我已经实施了数据库上下文......

WMS数据库上下文(保留包裹处理流程)。

public WMSContext()
        : base("Name=shopOrderContext")
    //: base("Name=WMSContext")
    {
        var adapter = (IObjectContextAdapter)this;
        var objectContext = adapter.ObjectContext;
        objectContext.CommandTimeout = 15 * 60; // value in seconds
    }

第二个是订单处理DB(它有客户订单)。

 public shopOrderContext()
        : base("Name=shopOrderContext")
    {
        var adapter = (IObjectContextAdapter)this;
        var objectContext = adapter.ObjectContext;
        objectContext.CommandTimeout = 15 * 60; // value in seconds
    }

为了维护交易,我已按以下方式实施......

 public ActionResult WarehouseConfirmVesselDate(string ConfrimVesselDate, string manifestNumber, string manifestStatus, string Remarks = null)
    {
        string Result = "Failed";
        //
        ManifestMaster manifestMasterList = new ManifestMaster();
        try
        {
            string UserName = Convert.ToString(Session["userName"]);
            TempData["TempManifestNumber"] = manifestNumber;
            if (!String.IsNullOrEmpty(ConfrimVesselDate))
            {
                using (objWmsContext = new WMSContext())
                {
                    using (var transScope = objWmsContext.Database.BeginTransaction(System.Data.IsolationLevel.Serializable))
                    {
                        try
                        {
                            #region Update Confirm Vessel Date form Warehouse User
                            GLSLabelRepository GlsRepbo = new GLSLabelRepository();
                            manifestMasterList = objWmsContext.ManifestMasterRecordes.Where(p => p.ManifestNumber == manifestNumber).FirstOrDefault();
                            if (manifestMasterList.Status == GlsRepbo.ShipmentOpen)
                            {
                                if (manifestMasterList.VesselDate == null || manifestMasterList.VesselDate == Convert.ToDateTime(ConfrimVesselDate))
                                {
                                    try
                                    {
                                        if (manifestMasterList.Country.ToUpper() == inCode.ToUpper())
                                        {
                                            // Update Vessel Date 
                                            Result = objWhRepository.UpdateConfirmVesselDate(ConfrimVesselDate, UserName, manifestNumber, manifestStatus, Remarks, objWmsContext);
                                        }
                                        else
                                        {
                                            //Comments by Prakash on Sprint 15 dated on 05-11-2014.
                                            //In Sprint 15 ,Warehouse Shipment processed based on the Manifest Number.Because of that the Process changed into the Following manner.
                                            //Step 1 : On Giving Vessel Date(Warehouse Module).New Process need to update the Only Vessel Date 
                                            //Step 2 : On Close Shipment .To block the Franchisee to add more parcel in that shipment list(based on the Country,Ready to Shipment Date and Vessel(Air/Ocean).
                                            //Step 3 : On Complete Shipment.Update the ShipmentStatus=True,OrderStatus= "Sent From VA" and Send Email to Customer.

                                            //Update Only Vessel Date.If this is the Case i need to work on the Vessel Report
                                            Result = objWhRepository.UpdateConfirmVesselDateManifest(ConfrimVesselDate, UserName, manifestMasterList.ManifestNumber, manifestStatus, Remarks, objWmsContext);
                                        }
                                        ManifestMaster MMbo = objWmsContext.ManifestMasterRecordes.Where(p => p.ManifestNumber == manifestNumber).FirstOrDefault();
                                        MMbo.VesselDate = Convert.ToDateTime(ConfrimVesselDate);

                                        MMbo.ModificationHistory = manifestMasterList.ModificationHistory + "  --  WAREHOUSE CONFIRMATION VESSELDATE --  USER :  " + UserName + "  Vessel Date :  " + Convert.ToDateTime(ConfrimVesselDate);
                                        if (MMbo.Country.ToUpper() == inCode)
                                        {
                                            //For India shipment Warehouse does not required to process Completed shipment.Because BOMBIO Shipment Label print form their sevice.
                                            MMbo.Status = GlsRepbo.ShipmentCompleted;
                                            MMbo.ShipmentUnits = 1;
                                            MMbo.Remarks = "For India there is no shipment label printing process.That why as soon as updating Vessel Date WMS made to complete the Shipment and Default Pallet Label is One. " + "<br/>---------- " + Convert.ToString(HttpContext.User.Identity.Name) + " and WMS System Comments ADDED on Complete Shipment at  " + DateTime.Now.ToString() + " ---------------- <br/><br/>" + MMbo.Remarks;
                                        }
                                        objWmsContext.SaveChanges();
                                        transScope.Commit();
                                        transScope.Dispose();
                                        Session["MNumber"] = MMbo.ManifestNumber;
                                        if (Result != "Failed" && !Result.Contains("Transaction aborted"))
                                        {
                                            //manifestMasterList.VesselDate = Convert.ToDateTime(ConfrimVesselDate);
                                            //manifestMasterList.ModificationHistory = manifestMasterList.ModificationHistory + " --WAREHOUSE CONFIRMATION VESSELDATE-- USER : " + UserName + " Vessel Date : " + Convert.ToDateTime(ConfrimVesselDate);
                                            //objWmsContext.SaveChanges();

                                            if (MMbo.Country.ToUpper() == dkCode || MMbo.Country.ToUpper().Trim() == seCode)
                                            {
                                                var syncResult = GlsRepbo.CompareVesselListAndSynchedRecordCount(MMbo.Country, MMbo.ReadyToShipDate, MMbo.ManifestNumber);
                                                if (syncResult == "Failed")
                                                    Result = "NotSynched";
                                            }
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Result = "ERROR while Updating" + ex.ToString();
                                        throw;
                                    }

                                }
                                else
                                {
                                    Result = " Manifest List should have same VesselDate :: " + manifestMasterList.VesselDate;
                                }
                            }
                            else
                            {
                                Result = " Manifest List was closed it seems.";
                            }
                            #endregion
                        }
                        catch (TransactionAbortedException trex)
                        {
                            transScope.Rollback();
                            transScope.Dispose();
                            objRepository.writeToLogFile(" Exception :" + trex.Message + "Source :" + trex.Source);
                            objRepository.writeToLogFile(" UpdateConfirmVesselDateManifest  Transaction Aborted Exception message : " + trex.Message);
                            if (trex.InnerException != null)
                            {
                                objRepository.writeToLogFile("UpdateConfirmVesselDateManifest  Transaction Aborted InnerException message : " + trex.InnerException.Message);
                            }
                            Result = "Transaction aborted. Same data is accessed by another user. Reload the data and Try after some time";
                        }
                        catch (Exception ex)
                        {
                            transScope.Rollback();
                            transScope.Dispose();
                            objRepository.writeToLogFile(" Exception :" + ex.Message + "Source :" + ex.Source);
                            objRepository.writeToLogFile(" UpdateConfirmVesselDateManifest  Transaction Aborted Common Exception block message : " + ex.Message);
                            if (ex.InnerException != null)
                            {
                                objRepository.writeToLogFile("UpdateConfirmVesselDateManifest  Transaction Aborted Common InnerException block message : " + ex.InnerException.Message);
                            }
                            Result = "Common block Exception Transaction aborted. Same data is accessed by another user. Reload the data and Try after some time";
                        }

                    }
                }
            }
            else
            {
                Result = "Server Received Selected WarehouseNos and ConfirmVessel Date is Empty,Retry Once Again...";
            }
        }
        catch (Exception ex)
        {
            loggfile.writeToLogFile("Confirm Vessel List got failed for this Manifest#(" + manifestNumber + ") : Message :- " + ex.Message);
            if (ex.InnerException != null)
            {
                loggfile.writeToLogFile("InnerException" + ex.InnerException.Message);
            }

        }
        return this.Json(Result);
    }

您可以在代码中查看我的注释。我已经处理了Update或Insert DB查询多方法调用,并且我传递了每个方法Current DB Context来处理事务。

我的明确问题在这里: 1)我是否正确处理交易逻辑?

2)我处理事务逻辑,这样哪个事务ID(WMSContext Transaction Id或ShopOrderContext Transaction Id)我的代码将被认为是Commit或者请建议我如何使用多个DB维护SAME数据库的事务逻辑上下文类..

3)我为ShopOrderContext和WMSContext提供了单独的服务方法类。一些场景我必须与两者交互,这里我的问题是否需要重载方法以将当前事务上下文对象传递给每个方法。

我这样用过......

//Update Only Vessel Date.If this is the Case i need to work on the Vessel Report
Result = objWhRepository.UpdateConfirmVesselDateManifest(ConfrimVesselDate, UserName, manifestMasterList.ManifestNumber, manifestStatus, Remarks, objWmsContext);

1 个答案:

答案 0 :(得分:0)

虽然实体框架为DB提供了一个很好的抽象(通过成为一个ORM),它有多个甚至可能映射同一个表的EF Context对象,但是不会为您提供现成的交易完整性解决方案。

我认为你能做到的唯一三种方式是:

  • 只在一个EF上下文中放置您需要的所有表格。
  • 或者保持你的方式,现在欢迎尝试保持平行的噩梦&#34;工作&#34; (线程),每个人都在处理每个事务,然后你需要实现一个&#34;信号的机制&#34;之间为了提供成功/错误(回滚)机制....
  • 如果您确切知道自己需要做什么,只需在SQL中创建一个存储过程并将所有复杂逻辑放在那里并在C#上调用它。

就个人而言,为了保持EF的精神,我会选择#1选项。