Подтвердить что ты не робот

Передача объекта подключения DB к методам

Интересно, рекомендуется ли использовать объект подключения к базе данных (для других модулей) или позволить методу (в другом модуле) позаботиться о его настройке. Я склоняюсь к тому, чтобы позволить методу настроить его, чтобы не проверять состояние соединения перед его использованием, и просто чтобы вызывающий передал любые необходимые данные вызывающему методу, который потребуется для настройки соединения.

4b9b3361

Ответ 1

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

Основным преимуществом при прохождении соединений было то, что вы могли передавать транзакцию; однако TransactionScope - это более простой способ совместного использования транзакции между методами.

Поскольку классы специфичны для реализации, я буду писать каждый, чтобы открыть собственную собственную транзакцию. В противном случае вы можете использовать методы ado.net factory для создания соответствующего типа из файла конфигурации (имя поставщика).

Ответ 2

Лично мне нравится хранить стек моего текущего открытого соединения и транзакций поверх Thread Local Storage с помощью SetData и GetData. Я определяю класс, который управляет моими подключениями к базе данных и позволяет использовать шаблон размещения. Это избавляет меня от необходимости проходить соединения и транзакции, что, по-моему, затрудняет и усложняет код.

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

Итак, я получаю что-то в этом направлении (полностью непроверенный):

class DatabaseContext : IDisposable {

    List<DatabaseContext> currentContexts;
    SqlConnection connection;
    bool first = false; 

    DatabaseContext (List<DatabaseContext> contexts)
    {
        currentContexts = contexts;
        if (contexts.Count == 0)
        {
            connection = new SqlConnection(); // fill in info 
            connection.Open();
            first = true;
        }
        else
        {
            connection = contexts.First().connection;
        }

        contexts.Add(this);
    }

   static List<DatabaseContext> DatabaseContexts {
        get
        {
            var contexts = CallContext.GetData("contexts") as List<DatabaseContext>;
            if (contexts == null)
            {
                contexts = new List<DatabaseContext>();
                CallContext.SetData("contexts", contexts);
            }
            return contexts;
        }
    }

    public static DatabaseContext GetOpenConnection() 
    {
        return new DatabaseContext(DatabaseContexts);
    }


    public SqlCommand CreateCommand(string sql)
    {
        var cmd = new SqlCommand(sql);
        cmd.Connection = connection;
        return cmd;
    }

    public void Dispose()
    {
        if (first)
        {
            connection.Close();
        }
        currentContexts.Remove(this);
    }
}



void Test()
{
    // connection is opened here
    using (var ctx = DatabaseContext.GetOpenConnection())
    {
        using (var cmd = ctx.CreateCommand("select 1"))
        {
            cmd.ExecuteNonQuery(); 
        }

        Test2(); 
    }
    // closed after dispose
}

void Test2()
{
    // reuse existing connection 
    using (var ctx = DatabaseContext.GetOpenConnection())
    {
        using (var cmd = ctx.CreateCommand("select 2"))
        {
            cmd.ExecuteNonQuery();
        }
    }
    // leaves connection open
}

Ответ 3

Для целей автоматического тестирования обычно проще передать его. Это называется инъекция зависимостей.

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

Ответ 4

Я лично стараюсь максимально централизовать доступ к данным, однако, если это невозможно, я ВСЕГДА открываю новое соединение в других классах, так как обнаруживаю, что существует слишком много других вещей, которые могут оказаться в пути при передаче фактический объект соединения.

Ответ 5

Настройка подключения является потенциально дорогостоящей и потенциально добавляет туда и обратно. Поэтому, опять же, возможно, лучший дизайн - передать объект соединения.

Я говорю потенциально, потому что, если вы являетесь приложением Microsoft ADO, вы, вероятно, используете пул соединений...

Ответ 6

Вот немного больше понимания этой проблемы. У меня есть класс, который управляет соединениями db и имеет 2 класса, которые реализуют интерфейс. Один из классов для SQL, а другой - OLAP. Менеджер - тот, кто знает, какое соединение использовать, чтобы оно могло передавать точное соединение с типом, или тип может создать свое собственное соединение.

Ответ 7

Вы можете передавать объекты соединения без каких-либо проблем (например, Microsoft Enterprise Library позволяет передавать статические вызовы методов в соединении), или вы можете управлять им извне до своего дизайна, нет прямых технических компромиссов.

Будьте осторожны с переносимостью, чтобы не передавать определенное соединение, если ваше решение будет перенесено в другие базы данных (это означает, что вы не передаете SqlConnection, с которым вы планируете работать с другими базами данных)

Ответ 8

Я бы предположил, что вы различаете объект соединения и его состояние (открытое, закрытое).

У вас может быть один метод (или свойство), который считывает строку соединения из web.config. Использование той же версии строки подключения каждый раз гарантирует, что вы выиграете от пула соединений.

Вызовите этот метод, когда вам нужно открыть соединение. В самый последний момент, после настройки всех свойств SqlCommand, откройте соединение, используйте его и закройте. В С# вы можете использовать оператор using, чтобы убедиться, что соединение закрыто. Если нет, обязательно закройте соединение в блоке finally.

Ответ 9

Я бы использовал web.config

<configuration>
    <connectionStrings>
        <add name="conn1" providerName="System.Data.SqlClient" connectionString="string here" />
        <add name="conn2" providerName="System.Data.SqlClient" connectionString="string here" />
    </connectionStrings>
</configuration>

Затем вы можете ссылаться на него из любого места приложения