当前位置: 首页 > 编程语言 > C#

TransactionScope:避免分布式事务共享

时间:2023-04-11 02:59:37 C#

TransactionScope:避免分布式事务我有一个包含子对象集合(List)的父对象(DAL的一部分)。当我将对象保存回数据库时,我输入/更新父对象,然后遍历每个子对象。为了可维护性,我把孩子的所有代码都放在一个单独的私有方法中。我打算使用标准的ADO事务,但在我的旅行中,我偶然发现了TransactionScope对象,我相信它将允许我在一个事务包中拥有父方法中的所有数据库交互(以及子方法中的所有交互)向上。到目前为止,一切都很好..?下一个问题是如何在TransactionScope中创建和使用连接。我听说使用多个连接,即使它们属于同一个数据库,也会迫使TransactionScope认为这是一个分布式事务(涉及一些昂贵的DTC工作)。是这样吗?或者,正如我似乎在其他地方读到的那样,使用相同的连接字符串(它本身用于连接池)是否可以?更实际地说,我...在父子节点中创建单独的连接(尽管具有相同的连接字符串)在父节点中创建连接并将其作为参数传递(对我来说似乎很笨拙)做某事...?更新:虽然看起来我可以使用我常用的.NET3.5+和SQLServer2008+,但该项目的另一部分将使用Oracle(10g),所以我不妨练习一种可以跨项目使用的技术。所以我只是将连接传递给sub方法。选项1代码示例:cmd.Connection.Open();cmd.CommandType=CommandType.StoredProcedure;try{//create&addparameterstocommand//将父对象保存到数据库cmd.ExecuteNonQuery();if((int)cmd.Parameters["@Result"].Value!=0){//不行//回滚事务ts.Dispose();返回假;}else//查询已保存OK{if(update){enquiryID=(int)cmd.Parameters["@EnquiryID"].价值;}//保存车辆(子对象)if(SaveVehiclesToEPE()){ts.Complete();返回真;}else{ts.Dispose();返回假;}}}catch(Exceptionex){//记录错误ts.Dispose();扔;当您使用TransactionScope跨多个连接进行交易时,许多数据库ADO提供程序(例如OracleODP.NET)确实会启动分布式事务——即使它们共享相同的连接字符串。某些提供程序(例如.NET3.5+中的SQL2008)会识别何时在引用相同连接字符串的事务范围内创建新连接,并且不会导致DTC工作。但是连接字符串中的任何差异(例如调整参数)都可以防止这种情况发生-并且该行为将恢复为使用分布式事务。不幸的是,在不创建分布式事务的情况下确保事务协同工作的唯一可靠方法是将连接对象(或IDbTransaction)传递给需要在同一事务上“继续”的方法。有时它有助于提升与您正在处理的类的成员的连接,但这会造成尴尬的情况-并使控制生命周期和连接对象的处置变得复杂(因为它通常会排除使用using语句)。根据经验,我已经确定(对于SQLServer提供程序)如果进程可以利用连接池在父进程和子进程之间共享连接(和事务),那么DTC不一定涉及。这是一个很大的“如果”,但是,根据您的示例,父进程创建的连接不能由子进程共享(在调用子进程之前不要关闭/释放连接)。这将导致一个事务跨越两个实际连接,这将导致事务被提升为分布式事务。重构代码来避免这种情况似乎很容易:只需在调用子进程之前关闭父进程创建的连接即可。在您的示例中,TransactionScope仍在方法的上下文中,您可以简单地创建一个包含多个命令的SqlTransaction。如果要将事务移出方法(例如,移至方法的调用者或访问多个数据库),请使用TransactionScope。更新:没关系,我刚刚发现孩子的电话。在这种情况下,您可以将连接对象传递给子类。此外,您不需要手动处理TransactionScope-使用块就像try-finally块一样,即使在特殊情况下也会执行处理。更新2:更好的是,将IDbTransaction传递给子类。可以从中检索连接。以上就是C#学习教程:TransactionScope:避免分布式事务分享的全部内容。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处: