我有一个应用程序,它有许多不同类型的对象,每个对象都会自行返回db。到目前为止,这没有交易工作正常,我不打算去添加它们。但是,在整个对象集合开始更新之前,偶尔需要启动事务,以确保只有在集合中的所有对象都成功时才实际更新数据库。
例如,假设我有一系列苹果。该命令被发送到集合以更新所有苹果。 [事务开始应该在这里]每个苹果执行代码来更新自己。 [事务提交/回滚应该在这里发生]。
我遇到的问题是每个更新现在都是原子的(未明确包装在事务中)。我可以将一个id传递给每个“apple”以识别已经存储在某种缓存中的事务,但是存在缓存在更新期间无效并导致不必要问题的风险。
那么最好的方法是什么?
答案 0 :(得分:4)
首先,我不会在页面中处理事务逻辑。编写某种类型的业务类来实现这一点 - 服务,数据实用程序类,您可以从ASP.Net中抽象出来。
接下来,如果您使用的数据库可以订阅像SQL Server这样的分布式事务,您可以查看使用 TransactionScope 类(在System.Transactions命名空间中,引用System.Transactions.dll)。
using(TransactionScope scope = new TransactionScope())
{
SaveObjectOne(); //these are just psuedo-code statements
SaveObjectTwo(); //replace these with your code that saves various objs
SaveObjectThree();
scope.Complete(); //this commits the transaction, unless exception throws
}
TransactionScope实现IDisposable,因此当使用调用 Dispose()时,如果从未调用 Complete(),事务将回滚。您需要启用分布式事务处理协调器以使用 TransactionScope 。
答案 1 :(得分:1)
OP表示集合管理事务中所有其他对象的保存,因此将事务代码放在此处似乎显而易见。如果您使用的是ADO.Net,那么打开连接并在集合中开始事务然后将其传递给其他每个对象似乎是最简单的选择。我假设这里的每个对象都继承自Layer Supertype Class,而你使用的是SQL Server。
public void Save()
{
using (SqlConnection connection = new SqlConnection("Connection String"))
{
using (SqlTransaction trans = connection.BeginTransaction())
{
foreach (BusinessObject obj in this)
{
obj.Save(connection);
}
trans.Commit();
}
}
}
答案 2 :(得分:1)
ado.net 2.0中的交易非常简单 我建议使用transactionscope并让框架为您处理交易:
阅读所有相关信息on MSDN:
交易流程管理
交易范围可以直接嵌套 和间接的。直接范围嵌套只是一个嵌套的范围 在另一个内部,如例5所示。
示例5.直接范围嵌套
using(TransactionScope scope1 = new TransactionScope()) { using(TransactionScope scope2 = new TransactionScope()) { scope2.Complete(); } scope1.Complete(); }
调用使用a的方法时会发生间接作用域嵌套
TransactionScope
来自使用其自己的范围的方法 示例6中RootMethod()
的情况。示例6.间接范围嵌套
void RootMethod() { using(TransactionScope scope = new TransactionScope()) { /* Perform transactional work here */ SomeMethod(); scope.Complete(); } } void SomeMethod() { using(TransactionScope scope = new TransactionScope()) { /* Perform transactional work here */ scope.Complete(); } }
答案 3 :(得分:0)