在实体框架6.0中实现事务逻辑单数据库与多数据库上下文类的最佳方法
本文关键字:数据库 多数据 上下文 方法 最佳 框架 实体 事务 实现 | 更新日期: 2023-09-27 18:03:37
任何一次建议我如何实现具有多个上下文类的同一数据库的实体事务逻辑。
我已经实现了DB上下文以下…
WMS数据库上下文(保持包裹处理过程)。
public WMSContext()
: base("Name=shopOrderContext")
//: base("Name=WMSContext")
{
var adapter = (IObjectContextAdapter)this;
var objectContext = adapter.ObjectContext;
objectContext.CommandTimeout = 15 * 60; // value in seconds
}
第二个是订单处理数据库(它有客户订单)。
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);
}
你可以在代码中看到我的注释b/w。我已经处理了更新或插入数据库查询多个方法调用,并且我传递每个方法当前数据库上下文来处理事务。
我的问题很明确:1)我处理事务逻辑的方式正确吗?
2)如果我处理像这样的事务逻辑事务Id(WMSContext事务Id或ShopOrderContext事务Id)我的代码将被考虑提交,否则请建议我如何维护具有多个DB上下文类的相同数据库的事务逻辑。
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);
虽然实体框架为数据库提供了一个很好的抽象(作为一个ORM),它有多个EF Context对象,甚至可以映射同一个表,但它不会为你提供一个开箱的事务完整性解决方案。
我认为你唯一能做到的三种方法是:
- 把所有你需要的表放在一个EF上下文中。
- 或者保持你的方式,现在欢迎来到试图保持并行"工作"(线程)的噩梦,每个线程都在处理每个事务,然后你需要在它们之间实现一种"信号"机制,以便提供成功/错误(回滚)机制....
- 如果你确切地知道你需要做什么,只需在SQL中创建一个存储过程,并将所有复杂的逻辑放在那里,然后在c#中调用。
就我个人而言,为了保持EF的精神,我会选择选项#1