Как мне интегрировать унаследованный код SqlTransaction с TranactionScope? - PullRequest
1 голос
/ 04 января 2010

У меня есть приложение, которое использует много вызовов SqlTranaction. При создании приложения мы получаем кучу кода, который выглядит примерно так (обработка ошибок и т. Д. Для краткости удалена):

Using transaction As SqlTransaction = Database.CreateSqlTransaction()
    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then
        Me.FitnessSession.Insert(transaction)
    Else
        Me.FitnessSession.Update(transaction)
    End If
    SaveTestScores(transaction)

    Database.CommitTransaction(transaction) 'This essentially just calls transaction.Commit()

 End Using

Мы находимся в процессе отказа от DAL и перехода на Linq to SQL, но это будет постепенно, поскольку у нас нет бюджета, чтобы просто отказаться от всего нашего унаследованного кода. Таким образом, у нас будут области, где нам нужно использовать как старый код, так и код Linq to SQL, все в одной транзакции. Я считаю, что это можно сделать так:

Using scope As New TransactionScope()
Using transaction As SqlTransaction = Database.CreateSqlTransaction()
    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then
        Me.FitnessSession.Insert(transaction)
    Else
        Me.FitnessSession.Update(transaction)
    End If
    SaveTestScores(transaction)

    Database.CommitTransaction(transaction)

 End Using
 End Using

Что мне непонятно, так это то, какой коммит звонить, нужно ли мне звонить scope.Complete() или Database.CommitTransaction(transaction)? Или есть какой-то другой вариант связать два бита кода вместе?

Контрольный вопрос
Спасибо @ program-hero, который действительно полезен, в чем я сейчас не уверен, когда мне следует закрывать соединения sql? Код внутри методов DAL проверяет, прошла ли транзакция, если она прошла, то использует соединение для этой транзакции и не закрывает соединение после его завершения, если транзакция не передана, то новая соединение открыто и закрыто для операции. Если я закрою SqlConnection внутри TransactionScope, это вызовет проблему для внешней транзакции? Я спрашиваю, потому что, если я закрою SqlConnection, у которого есть объект SqlTransaction, транзакция откатывается.

1 Ответ

2 голосов
/ 04 января 2010

Цель пространства имен System.Transactions - позволить вам контролировать транзакции из одной модели во всем приложении. При использовании модели транзакции, предоставленной System.Transactions, вам следует избегать использования каких-либо явных транзакций, таких как SqlTransaction; смешивание явных транзакций значительно усложнит вашу жизнь, так как вам придется вручную управлять обеими моделями.

Отличная новость для вас: Когда вы используете компоненты ADO.NET, вы получаете встроенную поддержку встроенных транзакций. Это означает, что вы можете удалить все ссылки на SqlTransaction и экземпляры объектов передаваемых транзакций. вокруг, так как модель System.Transactions позаботится обо всем за вас.

Модель окружающих транзакций работает как оболочка и координатор для различных других конкретных транзакций. Компоненты ADO.NET знают, что нужно искать внешнюю транзакцию и настраивать свои собственные конкретные транзакции внутри себя (например, SqlTransaction). Компоненты System.Transactions предупреждают все перечисленные транзакции о состоянии «глобальной» транзакции, которой управляют блоки TransactionScope.

При условии, что ваш код выполняется в блоке TransactionScope, будет доступна окружающая транзакция, доступная для компонентов с поддержкой транзакций. В вашем коде доступа к данным все взаимодействия будут происходить в одной транзакции, независимо от являются ли они частью вашего собственного компонента DAL или Linq to SQL. Все, что вам нужно знать, это то, что они будут подключаться к внешней транзакции, когда она присутствует.

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

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

Учитывая все это, ваш код может выглядеть так:

Using scope As New TransactionScope()

    If Not Me.FitnessSession.FitnessTestSessionID.HasValue Then
        Me.FitnessSession.Insert()
    Else
        Me.FitnessSession.Update()
    End If

    SaveTestScores()

    scope.Complete()

End Using

Все ссылки на транзакции, связанные с базой данных, удалены. Все операции будут происходить в рамках внешней транзакции, предоставленной TransactionScope. В этом блоке вы также можете сделать прямой вызов с использованием SqlCommand или использовать объект Linq-to-SQL без указания каких-либо явных транзакций, и они будут участвовать в транзакции окружения.

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