2011-01-26 36 views
5

我希望我的数据访问层构建得非常模块化。
因此,我有数据检索方法,有时直接从业务层调用,有时被其他数据检索方法调用来创建对象依赖关系。在DAL中处理数据库连接的最佳方式 - 创建或传递?

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

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

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

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

这是我第一次写真正的DAL,所以我真的可以使用一些经验丰富的人帮忙。

编辑:它似乎很重要,它是一个ASP.Net网站项目。

+0

可能是切线,但FWIW,我宁愿使用nhibernate,让它掌握所有这一切。即只使用nhibernate提供的会话对象。 – Biswanath 2011-01-26 21:16:46

回答

5

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

为每个请求创建一个新的连接,Dispose() - 当请求完成时。确保你使用相同的连接字符串。连接将(默认情况下)保持打开并通过连接池可用。有关连接池的更多信息,请参阅http://msdn.microsoft.com/en-us/library/8xx3tyca.aspx

你几乎必须在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 ; 

} 
+0

是的,它是一个ASP.Net网站。感谢您的链接和答案。但我不明白如何传递连接可以是一个并发问题? – magnattic 2011-01-26 21:43:37

1

使用所有三个

写连接,可选参数。如果传入none(null),则从一些(单独的,也许是)共享源创建一个连接,以便所有的DAL类创建具有相同确切连接字符串的连接(用于@Nicholas Carey提到的池化)。只有在创建它时才打开并关闭它。

如果传入连接,则假定它已经打开并且不关闭它。在更高层次上,当您调用此方法时,可以使用using语句来处理关闭连接。

2

我们使用选项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); 
     } 
    } 
} 

这样一来,如果我们决定,我们想用一个不同的连接字符串,甚至一些更棘手的创造我们的环境,我们可以简单地在一个位置更改依赖注入绑定,而不必查找每个对new MyDataContext()的调用。

相关问题