【发布时间】:2011-03-12 09:15:31
【问题描述】:
我有一个父对象(DAL 的一部分),其中包含子对象的集合 (List<t>)。
当我将对象保存回数据库时,我输入/更新父对象,然后遍历每个子对象。为了可维护性,我将孩子的所有代码都放在了一个单独的私有方法中。
我打算使用标准的 ADO 事务,但在旅途中,我偶然发现了 TransactionScope 对象,我相信这将使我能够将所有数据库交互(以及子方法中的所有交互)包装在一笔交易。
到目前为止一切顺利..?
所以下一个问题是如何在这个 TransactionScope 内创建和使用连接。我听说使用多个连接,即使它们连接到同一个数据库也会迫使 TransactionScope 认为它是一个分布式事务(涉及一些昂贵的 DTC 工作)。
是这样吗?或者,正如我似乎在其他地方读到的那样,使用相同的连接字符串(这将有助于连接池)的情况会很好吗?
更实际地说,我是不是……
- 在父级和子级中创建单独的连接(尽管使用相同的连接字符串)
- 在父级中创建一个连接并将其作为参数传递(对我来说似乎很笨拙)
- 做点别的...?
更新:
虽然看起来我可以使用我常用的 .NET3.5+ 和 SQL Server 2008+,但该项目的另一部分将使用 Oracle (10g),所以我不妨练习一种可以跨项目一致使用。
所以我将简单地将连接传递给子方法。
选项 1 代码示例:
using (TransactionScope ts = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(connString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Connection.Open();
cmd.CommandType = CommandType.StoredProcedure;
try
{
//create & add parameters to command
//save parent object to DB
cmd.ExecuteNonQuery();
if ((int)cmd.Parameters["@Result"].Value != 0)
{
//not ok
//rollback transaction
ts.Dispose();
return false;
}
else //enquiry saved OK
{
if (update)
{
enquiryID = (int)cmd.Parameters["@EnquiryID"].Value;
}
//Save Vehicles (child objects)
if (SaveVehiclesToEPE())
{
ts.Complete();
return true;
}
else
{
ts.Dispose();
return false;
}
}
}
catch (Exception ex)
{
//log error
ts.Dispose();
throw;
}
}
}
}
【问题讨论】:
-
见TransactionScope automatically escalating to MSDTC on some machines?。有几个很好的答案,但我链接的一个是最简洁的(并且与您的问题相关)。结果是,如果您使用的是 .NET 2.0 和 SQL Server 2005,即使使用具有相同连接字符串的两个连接,您也会升级。这不是 .NET 3.5 和 SQL Server 2008 的问题。
-
我 am 通常使用 .NET 3.5/4 和 SQL 2008,但偶尔我可能会使用 SQL2005/2000,所以无论如何都值得记住。谢谢
-
谁能给我一些关于什么是分布式事务的知识。举例说明。
标签: c# transactions transactionscope distributed-transactions