我有2个表(为简单起见,许多字段已删除)
tblOrder - OrderId - 订购日期 - UserId
tblOrderDetail - OrderDetailId - OrderId - ProductId - Qantity
我继续创建我的对象,我希望在一个事务中将所有内容保存在内存中,因为如果订单细节中的某些内容失败,我不希望保存订单。我使用以下代码,但我不明白如何在一次交易中正确地执行此操作。
Order newOrder = new Order();
OrderDetailCollection newOrderDetails = new OrderDetailCollection();
OrderDetail newOrderDetail;
newOrder.OrderDate = DateTime.Now();
newOrder.UserId = 1;
newOrderDetail = new OrderDetail();
// newOrderDetail.OrderId = newOrder.OrderId; // Can't do that yet, newOrder is not saved and OrderId is Null.
newOrderDetail.ProductId = 1;
newOrderDetail.Quantity = 25;
newOrderDetails.Add(newOrderDetail);
newOrderDetail = new OrderDetail();
// newOrderDetail.OrderId = newOrder.OrderId; // Can't do that yet, newOrder is not saved and OrderId is Null.
newOrderDetail.ProductId = 1;
newOrderDetail.Quantity = 25;
newOrderDetails.Add(newOrderDetail);
//只有两个用于测试目的。
现在我可以轻松地做到这一点
using (System.Transactions.TransactionScope ts = new TransactionScope()) {
using (SharedDbConnectionScope scs = new SharedDbConnectionScope()) {
try {
newOrder.Save();
foreach(OrderDetail anOrderDetail in newOrderDetails) {
anOrderDetail.OrderId = newOrder.OrderId;
}
newOrderDetails.BatchSave();
ts.Complete();
}
catch (Exception ex) {
//Do stuff with exception or throw it to caller
}
}
}
但这似乎不是最优雅的解决方案:
因为我必须遍历表中的每个项目来设置ID,然后保存批次。
因为出错,我在数据库中丢失了一个ID。 (即,如果发生错误,首先保存,OrderId = 1将丢失,下一个OrderId将为2)
不适用于具有其他子表的非常大的事务。在这个解决方案中,我使用Order表和Order Detail表构建了一个例子,但在我的实际应用程序中,OrderDetail OrderDetailCreditMember和OrderDetailCreditCompany下还有另外两个级别,在任何购买时,一小笔金额记入会员和公司(多行)所以我最终得到一个包含1个订单的树,其中包含2个订单详细信息,每个订单详细信息包含2个成员信用额度和3个公司信用额度。
所以有人有更好的方法来做到这一点。
答案 0 :(得分:2)
老实说,我认为你可能会在这里过早优化。
你在内存中进行迭代,你的事务中只有两个SQL调用,对我来说似乎效率不高。
这真的是一个问题吗,你经常会发生错误的发生,我假设你在尝试保存它们之前验证了你的对象,所以你真的应该很少得到错误(例如可以连接到db)所以我不相信这是一个问题。如果你遇到很多错误,那就是需要单独解决的问题。
是的,这里可能存在扩展问题,但你在谈论1 x 2 x 2 x 3 = 12次迭代的内存循环和3次SQL调用。除非你经常发生这种情况,否则这不应该是一个太大的问题。您多久预期会调用此方法?