4

我有一个 C# 应用程序,它跨多个函数和类进行许多 SQL 调用。数据库是 SQL Server 2008 R2。目前,每个类或函数在需要向数据库读/写数据时都会打开自己的 SQL 连接:

using (SqlConnection connection = new SqlConnection(connectionString))

这是处理连接管理的正确方法吗?另外我刚刚开始添加事务,所以如果我没记错的话,事务应该在同一个连接上完成。这是一些代码的示例:

try
{
   Class1 class1 = new Class1();
   class1.data = "somedata";
   class1.save(); // new sql connnection

   Class2 class2 = new Class2();
   class2.data = GetSomeData(); // new sql connection
   class2.save(); // new sql connection
}

catch (Exception e)
{
}

我查看了 TransactionScope 和 SqlTransaction,但我不确定我当前的连接结构是否适合此实现。任何指导将不胜感激。

4

4 回答 4

4

为每个操作“打开”一个新连接并不像人们想象的那样耗费资源。

原因是今天所有的 ADO.NET 提供程序都在内部使用连接池。这意味着每次您.Close()建立连接时,它实际上只是返回到池中。

当您开始在事务中涉及多个连接时,性能就会受到影响,因为这意味着事务被提升为分布式事务。也就是说,涉及第三方事务管理器并控制事务。

所以答案是,只要您的实体没有依赖关系,就没有理由从事务开始或停止使用多个连接。

什么时候需要交易?

但是,如果实体 A 依赖于实体 B,则必须使用事务。

依赖关系也可以由业务规则指定。让我们举个例子。

您有一笔银行转账,应该从账户 A 提取资金并存入账户 B。如果没有交易,资金可能会从账户 A 提取但不会存入 B(由于错误)。

于 2013-05-20T13:40:18.057 回答
2

您可以将两个保存调用包含在启动事务的 using 子句中。

每当您的系统想要启动连接时,它都会检查父事务(如果有的话)。

在http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx结帐样本

于 2013-05-20T13:46:53.757 回答
0

至少创建一个处理对象持久性的数据访问类——只需将对象传递给知道如何处理它的类方法。只有当类是一个孤立的实体时,在整个类中传播持久性代码才有意义,而这很可能不是(大多数对象与其他对象交互)。您应该使用 .NET--SQLMetal(命令行)或 Visual Studio 中的 LINQ-to-SQL ORM 设计器中提供的 ORM 功能。这样您就不会遇到现在遇到的问题,而是可以专注于您真正尝试对代码执行的操作。

于 2013-05-20T13:53:01.033 回答
0

是的,在using执行对象和 SQL Server 之间的实际数据封送处理的同一代码块中包含子句是正确的方法。原因很简单,如果发生错误,那么您不会泄漏连接,这可能会导致其他非常难以定位的问题。

问题实际上是您是否应该save对每个单独的类进行调用,或者是否应该使用数据访问提供程序之类的东西来处理与数据库服务器的通信。

如果实体 B 依赖于实体 A,这意味着必须保存 A 并返回 ID,然后 B 才能正确保存,那么您可以选择。要么 A 需要引用 B 并处理它的保存,要么将两个对象都传递给处理正确保存的数据访问类。此处的一个示例是,如果实体 A 是订单标题而 B 是行项目。在这种情况下,A 应该引用 B 的集合。当A.Save()被调用时,它应该迭代该集合并调用B.Save()自身。

无论哪种方式都可以很容易地在单个连接的上下文中实现事务。

于 2013-05-20T13:56:15.347 回答