Sql Transactions: лучший способ реализовать в ASP.Net - PullRequest
4 голосов
/ 24 ноября 2008

У меня есть приложение, в котором есть много разных типов объектов, каждый из которых сохраняется в БД. До сих пор это работало нормально, без транзакций, и я не собираюсь задирать, добавляя их. Но иногда возникает необходимость начать транзакцию до того, как начнется обновление всей коллекции объектов, чтобы убедиться, что база данных фактически обновляется только в случае успешного выполнения всех объектов в коллекции.

Например, скажем, у меня есть коллекция яблок. Команда выдается в коллекцию для обновления всех яблок. [запуск транзакции должен быть здесь] Каждое яблоко выполняет код для обновления. [фиксация / откат транзакции должна происходить здесь].

Недостаток, который у меня есть, заключается в том, что каждое обновление сейчас является атомарным (явно не заключено в транзакцию). Я мог бы передать идентификатор каждому «яблоку», чтобы идентифицировать транзакцию, которая была сохранена в каком-то кеше, но тогда есть риск, что кеш будет признан недействительным в процессе обновления и вызовет ненужную проблему.

Так каков лучший подход к этому?

Ответы [ 4 ]

4 голосов
/ 24 ноября 2008

Во-первых, я бы не стал обрабатывать транзакционную логику на странице. Для этого напишите какой-нибудь бизнес-класс - сервис, класс утилит данных, который можно абстрагировать от ASP.Net.

Далее вы можете использовать класс TransactionScope (в пространстве имен System.Transactions, ссылка на System.Transactions.dll), если вы используете базу данных, которая может подписаться на распределенные транзакции, такие как SQL Server.

using(TransactionScope scope = new TransactionScope())
{
  SaveObjectOne(); //these are just psuedo-code statements
  SaveObjectTwo(); //replace these with your code that saves various objs
  SaveObjectThree();
  scope.Complete(); //this commits the transaction, unless exception throws
}

TransactionScope реализует IDisposable, поэтому, когда с использованием вызывает Dispose () транзакция откатится, если Complete () никогда не вызывался. Вам необходимо разрешить Координатору распределенных транзакций использовать TransactionScope .

1 голос
/ 13 октября 2009

Транзакции действительно просты в ado.net 2.0 Я бы предложил использовать транзакцию и позволить платформе управлять транзакцией для вас:

читать все об этом на MSDN :

Управление потоком транзакций

Области транзакций могут быть вложены одновременно и косвенно. Прямое вложение области - просто одна вложенная область внутри другого, как показано в примере 5.

Пример 5. Прямое вложение области действия

using(TransactionScope scope1 = new TransactionScope())
{
   using(TransactionScope scope2 = new TransactionScope())
   {
      scope2.Complete();
   }
   scope1.Complete();
}

При вызове метода, использующего TransactionScope из метода, который использует собственную область видимости, как случай с RootMethod() в Примере 6.

Пример 6. Косвенное вложение области действия

void RootMethod()
{
   using(TransactionScope scope = new TransactionScope())
   {
      /* Perform transactional work here */
      SomeMethod();
      scope.Complete();
   }
}

void SomeMethod()
{
   using(TransactionScope scope = new TransactionScope())
   {
      /* Perform transactional work here */
      scope.Complete();
   }
}
1 голос
/ 24 ноября 2008

ОП говорит, что коллекция управляет сохранением всех других объектов в транзакции, поэтому было бы очевидным поместить здесь код транзакции. Если вы используете ADO.Net, казалось бы, проще всего открыть соединение и начать транзакцию в коллекции, а затем просто передать ее каждому из других объектов. Я предполагаю, что каждый из объектов здесь наследуется от класса супертипа Layer, и вы используете SQL Server.

public void Save()
{
    using (SqlConnection connection = new SqlConnection("Connection String"))
    {
        using (SqlTransaction trans = connection.BeginTransaction())
        {
            foreach (BusinessObject obj in this) 
            { 
                obj.Save(connection); 
            } 
            trans.Commit();
        }            
    }
}
0 голосов
/ 24 ноября 2008
  1. Я бы предпочел декларативные транзакции, а не ручные транзакции с БД.
  2. Как уже упоминал Митч Уит, транзакция имеет контекст и основана на соединении, поэтому она будет включать ваши изменения, происходящие на странице / методе, и фиксацию, если все в порядке, или откат, если было исключение.
  3. Я могу ошибаться , но у меня есть ощущение, что «Транзакция страницы» использует модель Enterprise Services из .NET 1.1 и работает через MSDTC (координатор распределенных транзакций, зарегистрированная служба COM +) ...
  4. Я бы предпочел System.Transactions и LTM (облегченный менеджер транзакций) для декларативных транзакций в .NET 2.0
  5. Я бы предпочел транзакции среды Spring.NET (доступные как для ADO.NET, так и для версий NHibernate), поскольку я считаю, что они поддерживают лучшее разделение задач на основе AOP (аспектно-ориентированное программирование), вам не придется связывать свой код код транзакции, и в основном потому, что эти парни уже много лет проводят транзакции в Java, и я просто доверяю им, что они знают, что делать.
...