Лучший способ справиться с подключением к БД в DAL - создать или передать? - PullRequest
5 голосов
/ 27 января 2011

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

Каков наилучший способ обработки соединений с базой данных в DAL?

a) Создайте новое соединение в каждом методе и утилизируйте его впоследствии.
Хорошо: Легко писать и работать.
Плохо: Многие соединения открываются и закрываются.(производительность?)

b) Передать соединение в качестве (необязательного) аргумента.
Хорошо: Я мог бы повторно использовать открытое соединение для нескольких команд.
Плохо: Я должен отслеживать право собственности на соединение (кто должен его закрывать?) И не могу использовать очень аккуратные операторы "using".

c) Что-то другое?(Возможно, соединение как синглтон?)

Это первый раз, когда я пишу настоящий DAL, так что я действительно мог бы использовать некоторую помощь от вас, опытные люди.по сути, это веб-сайт ASP.Net Project.

Ответы [ 5 ]

4 голосов
/ 27 января 2011

Если вы используете ASP.Net, вариант А - ваш друг.

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

См. http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx для получения дополнительной информации о пуле соединений.

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

[отредактировано для добавления примера кода]

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

public int Exec(  int? @iPatientID )
{
  using ( SqlConnection  conn = new SqlConnection( this.ConnectString ) )
  using ( SqlCommand     cmd  = conn.CreateCommand() )
  using ( SqlDataAdapter sda  = new SqlDataAdapter( cmd ) )
  {
    cmd.CommandText = STORED_PROCEDURE_NAME ;
    cmd.CommandType = CommandType.StoredProcedure ;

    if ( this.TimeoutInSeconds.HasValue )
    {
      cmd.CommandTimeout = this.TimeoutInSeconds.Value ;
    }

    //
    // 1. @iPatientID
    //
    SqlParameter p1 = new SqlParameter( @"@iPatientID" , SqlDbType.Int ) ;
    if ( @iPatientID == null )
    {
      p1.Value = System.DBNull.Value ;
    }
    else
    {
      p1.Value = @iPatientID ;
    }
    cmd.Parameters.Add( p1 ) ;

    // add return code parameter
    SqlParameter pReturnCode = new SqlParameter() ;
    pReturnCode.SqlDbType    = System.Data.SqlDbType.Int ;
    pReturnCode.Direction    = System.Data.ParameterDirection.ReturnValue ;
    cmd.Parameters.Add( pReturnCode ) ;

    DataSet ds = new DataSet() ;

    conn.Open() ;
    sda.Fill( ds ) ;
    conn.Close() ;

    this.ResultSet  = ( ds.Tables.Count > 0 ? ds.Tables[0] : null ) ;
    this.ReturnCode = (int) pReturnCode.Value ;

  }

  return this.ReturnCode ;

}
2 голосов
/ 27 января 2011

Мы используем вариант варианта А.

На самом деле мы используем Entity Framework, чтобы мы могли использовать LINQ и тому подобное. Entity Framework управляет своим собственным пулом соединений, поэтому создание и удаление контекстов обходится дешево. Затем мы используем Dependency Injection для управления фактическим созданием соединения, например:

public class MyDao 
{
    IFactory<MyDataContext> _contextFactory;
    public MyDao(IFactory<MyDataContext> contextFactory)
    {
        _contextFactory = contextFactory;
    }

    public Foo GetFooById(int fooId)
    {
        using (var context = _contextFactory.Get())
        {
            return context.Foos.Single(f => f.FooId == fooId);
        }
    }
}

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

1 голос
/ 27 января 2011

Использовать все три

Записать соединение как необязательный параметр. Если ни один (ноль) не передан, создайте соединение из какого-то (синглтонного, возможно) общего источника, чтобы все ваши классы DAL создавали соединения с одинаковыми точными строками соединения (для объединения, как упомянуто @Nicholas Carey). Открывайте и закрывайте его, только если вы его создали.

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

1 голос
/ 27 января 2011

Большинство провайдеров в любом случае объединяют пулы соединений либо на уровне ODBC, либо на уровне .NET. Таким образом, вариант А является более безопасным и, вероятно, одинаково хорошим с точки зрения производительности.

См .: http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

А: http://msdn.microsoft.com/en-us/library/ms254502.aspx

1 голос
/ 27 января 2011

Наилучшим вариантом будет наличие пула соединений, в котором вы сможете получать свои соединения. Позвольте пулу соединений управлять временем жизни соединений и получать уже открытые, когда они вам нужны! Примером этого является http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

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