将DB Connection对象传递给方法

想知道是否建议传递数据库连接对象(到其他模块)或让方法(在另一个模块中)负责设置它。 我倾向于让方法设置为不必在使用之前检查连接的状态,只是让调用者将任何所需的数据传递给设置连接所需的调用方法。

我个人喜欢使用严格的连接; 打开它们,使用它们并关闭它们(在“使用”块中,所有都在本地方法中)。 在大多数情况下,连接池将处理重新使用连接,因此这种方法没有实际开销。

传递连接的主要优点是,您可以传递事务; 但是, TransactionScope是一种在方法之间共享TransactionScope的简单方法。

由于这些类是特定于实现的,因此我会编写每个类来打开它自己的本机事务。 否则,您可以使用ado.net工厂方法从配置文件(提供程序名称)创建相应的类型。

就个人而言,我喜欢使用SetData和GetData在Thread Local Storage之上存储我当前打开的连接和事务的堆栈。 我定义了一个类来管理我与数据库的连接,并允许它使用dispose模式。 这使我无需传递连接和事务,这是我认为使代码混乱和复杂化的问题。

我强烈建议不要在每次需要数据时都要打开连接方法。 这将导致一个非常糟糕的情况,即整个应用程序都很难管理事务,并且打开和关闭了太多的连接(我知道连接池,从池中查找连接的成本仍然比它更昂贵重用一个对象)

所以我最终得到了这些内容(完全未经测试):

 class DatabaseContext : IDisposable { List currentContexts; SqlConnection connection; bool first = false; DatabaseContext (List 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 DatabaseContexts { get { var contexts = CallContext.GetData("contexts") as List; if (contexts == null) { contexts = new List(); 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 } 

出于自动化测试的目的,通常更容易将其传入。这称为dependency injection 。

当您需要编写测试时,您可以创建一个模拟数据库连接对象并传递它而不是真实的。 这样,您的自动化测试将不依赖于每次都需要重新填充数据的实际数据库。

我个人努力尽可能集中我的数据访问,但是,如果不可能我总是在其他类中打开一个新连接,因为我发现在传递实际连接时有太多其他东西可能会妨碍我宾语。

以下是对此问题的更深入了解。 我有一个管理数据库连接的类,并有2个实现接口的类。 其中一个类是SQL,另一个是OLAP。 管理器是知道要使用哪个连接的管理器,因此它可以传递与该类型的确切连接,或者类型可以创建自己的连接。

您可以毫无问题地传递连接对象(例如Microsoft Enterprise Library允许通过连接传递静态方法调用),或者您可以在外部管理它直到您的设计,没有直接的技术权衡。

如果您的解决方案将移植到其他数据库,请注意不要传递特定连接的可移植性(意味着不要传递您计划与其他数据库一起使用的SqlConnection)

建立连接可能很昂贵,并可能增加往返。 因此,再次,可能,更好的设计是传递连接对象。

我可能会说,因为如果你是一个Microsoft ADO应用程序,你可能正在使用连接池….

我建议你区分连接对象和它的状态(打开,关闭)。

您可以使用单个方法(或属性)从web.config读取连接字符串。 每次使用相同版本的连接字符串可确保您从连接池中受益。

需要打开连接时调用该方法。 在最后一刻,在设置所有SqlCommand属性后,打开连接,使用它,然后关闭它。 在C#中,您可以使用using语句来确保连接已关闭。 如果没有,请务必关闭finally块中的连接。

我会使用web.config

       

然后,您可以从应用程序的任何位置引用它