2014-10-14 2 views
0

У меня есть следующий код в моем веб-сайте (например, очень-очень упрощен для SO, конечно):DataContext.SubmitChanges() представляет нежелательные данные

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 объект находится в несоответствующее состояние (Status - XOrderStatus.Completed, но CompletedOn не установлен). dataContext.SubmitChanges(); // 1 не называется, здесь все хорошо. НО. Вы видите dataContext.SubmitChanges(); // 2. Это называется. И вместе с XExceptionEvent он отправляет нежелательные изменения order в мою базу данных.

Хорошо. Я попытался создать еще один XDataContext для исключений. Но exceptionsDataContext.SubmitChanges(); говорит, что currentUser загружается через разные XDataContext. Есть идеи? Есть ли элегантный способ отмены недействительных изменений моего order?

ответ

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 к SQL DataContext обеспечивает отличную функциональность для управления набором локальных изменения в базе данных, которые могут быть перенесены на сервер с помощью одного вызова метода SubmitChanges(). Неизбежно возникнут ситуации, когда вы хотите отказаться от внесенных вами изменений, что позволит вам продолжать использовать DataContext, как если бы эти изменения не были сделаны. К сожалению, не существует метода DataContext.DiscardChanges(). Небольшое исследование показывает, что это по дизайну и что вы должны просто воссоздать DataContext в этих случаях, но, конечно, ничего не так просто. Каждый объект, который есть у исходного DataContext, теперь должен быть сброшен, чтобы использовать новый, чтобы гарантировать предсказуемое поведение.

+0

Как я уже отмечал, я попытался отказаться от 'XDataContext', но у меня есть« XUser currentUser », созданный в этом контексте. Поэтому я вынужден использовать старый XDataContext, и в настоящее время я искал способ отбросить все изменения элегантно. – Denis

+1

Это относится к категории «это * не * ОК, чтобы отменить несохраненные изменения сущности». Взгляните на http://graemehill.ca/discard-changes-in-linq-to-sql-datacontext/ –

+0

Это работает! Спасибо. – Denis

Смежные вопросы