Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在DAL中处理DB连接的最佳方法是创建还是传递?_C#_Asp.net_Connection_Data Access Layer - Fatal编程技术网

C# 在DAL中处理DB连接的最佳方法是创建还是传递?

C# 在DAL中处理DB连接的最佳方法是创建还是传递?,c#,asp.net,connection,data-access-layer,C#,Asp.net,Connection,Data Access Layer,我希望我的数据访问层非常模块化。 因此,我有一些数据检索方法,有时直接从业务层调用,有时由其他数据检索方法调用,以创建对象依赖关系 在DAL中处理数据库连接的最佳方法是什么 a)在每个方法中创建一个新连接,并在以后进行处理。 好:易于编写和使用。 错误:正在打开和关闭许多连接。(性能?) b)将连接作为(可选)参数传递。 好:我可以对多个命令重复使用打开的连接。 坏:我必须跟踪连接的所有权(谁必须关闭它?),不能使用非常简洁的“using”语句 还有别的吗?(可能是单身人士的连接? 这是我第一次

我希望我的数据访问层非常模块化。
因此,我有一些数据检索方法,有时直接从业务层调用,有时由其他数据检索方法调用,以创建对象依赖关系

在DAL中处理数据库连接的最佳方法是什么

a)在每个方法中创建一个新连接,并在以后进行处理。
好:易于编写和使用。
错误:正在打开和关闭许多连接。(性能?)

b)将连接作为(可选)参数传递。
好:我可以对多个命令重复使用打开的连接。
坏:我必须跟踪连接的所有权(谁必须关闭它?),不能使用非常简洁的“using”语句

还有别的吗?(可能是单身人士的连接?

这是我第一次写一篇真正的DAL,所以我真的需要你们这些有经验的人的帮助


编辑:看起来很重要,这是一个ASP.Net网站项目。

如果您使用的是ASP.Net,选项A是您的朋友

为每个请求创建一个新连接,在请求完成时释放()。确保使用相同的连接字符串。连接(默认情况下)将保持打开状态,并通过连接池可用

有关连接池的更多信息,请参阅

在web服务器中,您几乎必须这样做,这样您就不会有并发问题。一切都需要线程安全(你不知道有多少并发工作线程在你的应用程序中执行)

[编辑以添加示例代码]

作为一个例子,这里我将是一个典型的执行存储过程的方法。这来自我编写的自定义代码生成器-手写代码看起来可能会有点不同-但它应该足以让人理解这一点:

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 ;

}

最好的选择是有一个连接池,您可以在其中获得连接。让conenction池处理连接的生存期,并在需要时获取已打开的连接!
这方面的一个例子是

无论如何,大多数提供程序都会在ODBC级别或.NET级别共享连接。因此,选项A既安全又可能同样具有良好的性能

见:


并且:

使用这三种方法

将连接作为可选参数写入。如果未传入任何(null),则从某些(可能是单例)共享源创建连接,以便所有DAL类都使用相同的连接字符串创建连接(如@Nicholas Carey所述的池)。仅当您创建它时才打开和关闭它


如果传入了连接,则假定该连接已打开,而不关闭它。在更高的级别上,当调用此方法时,可以使用using语句来处理连接的关闭。

我们使用选项a的变体

我们实际上使用实体框架,这样我们就可以利用LINQ等。实体框架管理自己的连接池,因此创建和删除上下文的成本很低。然后,我们利用依赖项注入来管理连接的实际创建,如下所示:

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);
        }
    }
}
公共类MyDao
{
IFactory\u contextFactory;
公共MyDao(IFactory上下文工厂)
{
_contextFactory=contextFactory;
}
公共Foo GetFooById(intfooid)
{
使用(var context=_contextFactory.Get())
{
返回context.Foos.Single(f=>f.FooId==FooId);
}
}
}

这样,如果我们决定使用不同的连接字符串或更复杂的东西来创建上下文,我们只需在一个地方更改依赖项注入绑定,而不必查找对
new MyDataContext()

的每个调用可能是相切的,但是FWIW,我宁愿使用nhibernate,让它来处理这一切。i、 只需使用nhibernate提供的会话对象即可。是的,这是一个ASP.Net网站。谢谢你的链接和答案。但是我不明白传递连接怎么会是并发问题?@atticae:只有当连接对象最终被多个线程使用时,它才会成为并发问题。这是否会发生取决于代码的结构,但是,如果您在数据访问方法的上下文中创建和处理连接,则意外发生的可能性要小得多。您可能希望传递SqlConnection的唯一时间是在同一个SqlTransaction中需要多个DAL方法的情况下。这可能是最好避免的。