Как откатить изменения данных в DBContext, если «SubmitChanges» не удался, но требуются другие отправки? - PullRequest
2 голосов
/ 02 марта 2011

В некоторых бизнес-случаях у моего приложения есть причина ошибки внутри транзакции.Ситуация выглядит следующим образом:

static void MyFunc(DBContext context)
{
    context.MyObjects.InsertOnSubmit(new MyObj{Id=1});
                                         // Id - is a primary key
    context.MyObjects.InsertOnSubmit(new MyObj{Id=1});
                                         // here I force system to fail
                                         // by trying to add record with
                                         // duplicated primary key value

    context.SubmitChanges(); // causes an error (as expected)
}

static void main()
{
    using (DBContext context = new DBContext())
    {
        try
        {
            using (TransactionScope scope = CreateTransactionScope())
            {
                MyFunc(context);

                scope.Complete();
            }
        }
        catch(Exception exc)
        {
            MyLog log = new MyLog{...valid object data... want to log error ... };
            context.MyLogs.InsertOnSubmit(log);
            context.SubmitChanges();
        }
    }
}

проблема здесь в том, что попытка сохранить объект 'log' также вызывает попытку сохранить ранее добавленные объекты в таблицу 'MyObject'!И в результате я не могу сохранить запись в журнале ... и моя функция "main" выдает исключение ...

Как я могу решить эту проблему?Любые мысли приветствуются.

(я использую MS SQL 2005, Linq2Sql, .NET 3.5, идеи для .NET 4.0 также приветствуются!)

PS Я знаю, что это может быть хорошоИдея вызвать 'scope.Rollback', но если я оставлю 'using (TransactionScope scope ...)' без вызова 'Complete', тогда 'Откат должен быть применен автоматически ...

PPS Я мог бы создать новыйОбъект DBContext, но не думайте, что это разумно.

Ответы [ 3 ]

4 голосов
/ 02 марта 2011

Транзакция - это инструмент для группировки действий, которые должны выполняться целиком, а не по частям.Поскольку у вас есть некоторые действия, которые можно (и в вашем случае должны) легко отделить от остальных, представляется более целесообразным использовать две отдельные транзакции.

1 голос
/ 16 мая 2012

вы можете выполнить откат в контексте, как это

public void Rollback()
{
    base.ChangeTracker.Entries().ToList().ForEach(entry => entry.State = System.Data.EntityState.Unchanged);
}
1 голос
/ 02 марта 2011

Вообще говоря, DataContext будет хранить ссылку на все объекты, которые были загружены или прикреплены к нему в памяти. Я могу ошибаться, но я не верю, что изменения в TransactionScope откатываются в объектах «в памяти».

Поэтому SubmitChanges () для контекста в обработчике ошибок попытается повторно отправить все изменения в модель «в памяти». Единственный известный мне способ исправить это - сбросить модель «в памяти», создав новый контекст.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...