DataContext.SubmitChanges()提交不需要的数据

时间:2014-10-14 21:17:29

标签: c# linq-to-sql datacontext

我的网站上有下一个代码(例如,SO的例子非常简化):

XDataContext dataContext = new XDataContext();
int currentUserId = GetCurrentUserIdFromSession();
XUser currentUser = dataContext.Users.Single(u => u.Id == currentUserId);

try
{
    using (var t = new TransactionScope())
    {
        int orderId = GetOrderIdFromSession();
        XOrder order = dataContext.Orders.Single(o => o.Id == orderId);
        order.Status = XOrderStatus.Completed;
        order.TransactionId = SomeCalculations(); // exception here
        order.CompletedOn = DateTime.UtcNow;
        dataContext.SubmitChanges(); // 1
        t.Complete();
    }
}
catch (Exception ex)
{
    XExceptionEvent exceptionEvent = new XExceptionEvent();
    exceptionEvent.User = currentUser;
    dataContext.ExceptionEvents.InsertOnSubmit(exceptionEvent);
    dataContext.SubmitChanges(); // 2
}

SomeCalculations()抛出异常时,order对象处于不一致状态(其StatusXOrderStatus.Completed,但未设置CompletedOndataContext.SubmitChanges(); // 1没有被调用,这里的一切都很好。但。你看到dataContext.SubmitChanges(); // 2了吗?它被称为。与XExceptionEvent一起,它将order的不需要的更改提交到我的数据库。

好。我尝试为异常创建另一个XDataContext。但exceptionsDataContext.SubmitChanges();表示currentUser是通过不同的XDataContext加载的。有任何想法吗?是否有任何优雅的方法可以取消order的无效更改?

1 个答案:

答案 0 :(得分:2)

您的TransactionScope确保范围内的所有数据库操作都写入数据库,或者根本不写入。

它不会以任何方式影响内存中对象的更改,包括order

一个简单的解决方案是丢弃您当前使用的DataContext并实例化一个新的(假设可以放弃未保存的实体更改)。

对于其他选项,请查看相关的

How can I reject all changes in a Linq to SQL's DataContext?

,具体而言

http://graemehill.ca/discard-changes-in-linq-to-sql-datacontext/

  

LINQ to SQL DataContext提供了出色的功能,可以管理对数据库的一组本地更改,只需调用SubmitChanges()即可将其推送到服务器。不可避免地会出现您想要丢弃所做更改的情况,从而有效地允许您继续使用DataContext,就好像这些更改从未进行过一样。不幸的是,没有DataContext.DiscardChanges()方法。一个小小的研究表明这是设计的,你应该简单地在这些情况下重新创建DataContext,但当然,没有什么是那么简单。现在,您需要重置来自原始DataContext的每个对象,以使用新对象来保证可预测的行为。