Сделка с Dapper. NET - PullRequest
       7

Сделка с Dapper. NET

1 голос
/ 26 марта 2020

В настоящее время у меня есть два класса в одном слое, которые выполняют включение данных в базу данных:

using Dapper;
using System;
using System.Data.SqlClient;
using System.Linq;

namespace repositories
{
    public class DAOBook
    {
        private readonly string _connection;

        public DAOBook(string databaseConnection)
        {
            _connection = databaseConnection;
        }

        public bool IncludeBook(string title)
        {
            try
            {
                using (var connection = new SqlConnection(_connection))
                {
                    var sql = $@"
                                INSERT INTO books
                                  (title)
                                VALUES
                                  ('{title}' ";

                    var result = connection.Execute(sql);

                    return result != 0;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"{ex.Message}", ex);
            }
        }
    }
}

using Dapper;
using System;
using System.Data.SqlClient;
using System.Linq;

namespace repositories
{
    public class DAOBookTag
    {
        private readonly string _connection;

        public DAOBookTag(string databaseConnection)
        {
            _connection = databaseConnection;
        }

        public bool IncludeBookTag(string tag, int userid)
        {
            try
            {
                using (var connection = new SqlConnection(_connection))
                {
                    var sql = $@"
                                INSERT INTO bookTag
                                  (tag, userid)
                                VALUES
                                  ('{tag}', {userid} ";

                    var result = connection.Execute(sql);

                    return result != 0;
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"{ex.Message}", ex);
            }
        }
    }
}

В моем слое обслуживания я могу нормально вызывать эти два класса, и они вставляют их в базу данных.

try
{
    var connectionString = "<my_connection_string>";
    var daoBook = new DAOBook(connectionString);
    var daoBookTag = new DAOBookTag(connectionString);

    dao.IncludeBook("Alice");
    dao.IncludeBookTag("Romance", 1);
}
catch (Exception ex)
{
    throw new Exception($"{ex.Message}", ex);
}

Однако я хочу разместить элемент управления транзакцией, чтобы в случае ошибки при вставке второго класса он отменял транзакцию в catch, что-то как это:

try
{
    var connectionString = "<my_connection_string>";
    var daoBook = new DAOBook(connectionString);
    var daoBookTag = new DAOBookTag(connectionString);

    // begin transaction    
    dao.IncludeBook("Alice");
    dao.IncludeBookTag("Romance", 1);
    // commit
}
catch (Exception ex)
{
    // rollback
    throw new Exception($"{ex.Message}", ex);
}

Я знаю, что это вопрос новичка, но я не могу найти способ для двух классов постоянства совместно использовать одну транзакцию.

Я видел пример реализации управления транзакциями Dapper, но я не знаю, как я мог бы реализовать его на своем уровне обслуживания (вместо уровня постоянства). https://riptutorial.com/dapper/example/22536/using-a-transaction

Спасибо

Ответы [ 2 ]

1 голос
/ 26 марта 2020

Использование TransactionScope :

using (var transactionScope = new TransactionScope())
{
    var connectionString = "<my_connection_string>";
    var daoBook = new DAOBook(connectionString);
    var daoBookTag = new DAOBookTag(connectionString);

    // begin transaction    
    dao.IncludeBook("Alice");
    dao.IncludeBookTag("Romance", 1);
    //commit
    transactionScope.Complete();
}

https://dapper-tutorial.net/transaction

0 голосов
/ 26 марта 2020

Существует два способа обработки транзакций в ADO.NET; обычно предпочтительным механизмом является транзакция ADO. NET, т.е. BeginTransaction. Это имеет ограничения, но очень эффективно и изначально привязано к большинству провайдеров. Основное ограничение транзакции ADO. NET состоит в том, что она охватывает только одно соединение, и ваше соединение должно длиться как минимум столько же времени, сколько транзакция.

С точки зрения использования Dapper, вы также должны передать транзакцию. в вызов; например:

using (var conn = new SqlConnection(connectionString))
{
    connection.Open();
    using (var tran = connection.BeginTransaction())
    {
        // ... your work
        tran.Commit();
    }
}

, где "ваша работа" здесь эффективно использует те же экземпляры conn и tran, используя:

var result = conn.Execute(sql, args, transaction: tran);

много * lazier способ использовать TransactionScope. Это проще в использовании, но более сложным. Я обычно советую против этого, но это работает.


Вы также должны параметризовать:

var sql = @"
INSERT INTO bookTag (tag, userid)
VALUES (@tag, @userId)";
var result = connection.Execute(sql, new { tag, userId });
...