多个方法调用的函数委托
本文关键字:函数 调用 方法 | 更新日期: 2023-09-27 18:24:50
我之前问过使用SqlConnection转换为Func委托
如何使用以下委托使用同一事务进行多个调用?更复杂的是,其中一个调用我希望返回一个值。
我有以下代理功能定义
protected TResult UsingSqlTransaction<TResult>(Func<SqlTransaction, TResult> myFunction)
{
using (SqlConnection sqlConn = new SqlConnection(ConnectionString))
{
sqlConn.Open();
using (SqlTransaction sqlTrans = sqlConn.BeginTransaction())
{
var result = myFunction(sqlTrans);
sqlTrans.Commit();
return result;
}
}
}
当前使用
public Guid? InsertUpdate(News entity)
{
return UsingSqlTransaction(sqlTrans => data.InsertUpdate(sqlTrans, entity));
}
解决方案-查看已接受的答案
public Guid? InsertUpdate(News entity)
{
return UsingSqlTransaction(sqlTrans =>
{
var token = data.InsertUpdate(sqlTrans, entity);
data.DoSomethingElse(sqlTrans, entity);
return token;
});
}
//-- The above UsingSqlTransaction remains unchanged
您可以使用'block'lambda。代替:
public Guid? InsertUpdate(News entity)
{
return UsingSqlTransaction(sqlTrans => data.InsertUpdate(sqlTrans, entity));
}
您可以使用(注意大括号和分号):
public List<Guid?> InsertUpdate(News entity)
{
return UsingSqlTransaction(sqlTrans =>
{
var result = new List<Guid?>();
result.Add(data.InsertUpdate(sqlTrans, entity));
result.Add(data.DoSomethingElse(sqlTrans, entity));
return result;
});
}
回复:您的更新。我会这样写(注意,你可以存储token
并在lambda的末尾返回它,就像普通方法一样):
public Guid? InsertUpdate(News entity)
{
return UsingSqlTransaction(sqlTrans =>
{
var token = data.InsertUpdate(sqlTrans, entity);
data.DoSomethingElse(sqlTrans, entity);
return token;
});
}
我的程序中有相同的方法,但它是这样的:
void RunTransaction(Action<IDbCommand> action)
{
using(var cnn=GetConnection)
cnn.Open();
using(var trans=cnn.BeginTransaction())
{
var command=cnn.CreateCommand();
action(command);
trans.Commit();
}
}
此方法只负责管理事务,而不负责其他事务。它不在乎我们是在查询数据库还是在插入值。处理这些事情是调用者的责任,有了闭包的美妙之处,这是一项简单的任务:)
我的想法是:不要试图对所有东西都有一个抽象,因为很快你的程序员就会变得太复杂,无法扩展和维护。只要有一些基本的抽象可供使用,就可以在这些简单的抽象之上构建应用程序。
这是我成功使用过几次的模式:
拥有一个"事务管理器"对象,该对象在内部跟踪当前连接和事务。它可以是一个简单的静态,用于单线程应用程序,也可以使用线程本地存储甚至WCF操作上下文来做一些有趣的事情。其思想是,它为您提供了一个单独的位置来创建连接和事务,这些连接和事务与调用数据库的代码分离。
事务管理器公开一个名为BeginTransaction的公共方法,该方法返回实现IDisposable的事务对象。每次调用BeginTransaction时,都会得到一个新的事务范围实例。
事务范围对象还提供了获取数据库连接的方法,以及在处理之前必须调用的Commit方法。如果未调用Commit,则事务将在Dispose上回滚。
void M1()
{
using( var scope = TransactionManager.BeginTransaction() )
{
// Do stuff with the database.
M2(); // M2 and M3 each create their own scopes that share the transaction
M3(); // created by M1.
// An exception before the commit will cause the transaction to roll back.
scope.Commit();
}
}
重要的是,TransactionManager将允许您创建嵌套的作用域——"对数据库做一些事情"行可以调用一组其他方法,每个方法都创建自己的作用域,共享一个事务。必须提交所有作用域,否则一切都将回滚。
这一切看起来都与System.Transactions命名空间中的东西的工作方式非常相似,我建议您也看看。
然后你的实用程序函数来简化代码,如果你仍然想要它们,看起来像这样:
public static void Execute(Action<ITransactionScope> action)
{
using( var scope = TransactionManager.BeginTransaction() )
{
action(scope);
scope.Commit();
}
}
public static TResult Execute<TResult>(Func<ITransactionScope, TResult> func)
{
using( var scope = TransactionManager.BeginTransaction() )
{
var result = func(scope);
scope.Commit();
return result;
}
}