我有一个wcf api,希望将所有请求包装在一个事务
中目前我的代码在每个端点中都是这样的
public MyCompleteList ReadOrganisations()
{
MyCompleteList resp = new MyCompleteList ();
try
{
using (TransactionScope scope = new TransactionScope())
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
DC_Base browser_request = new DC_Base(PROJECT);
browser_request.cmd_user_id = coreDb.GetUserIDFromLoginName(PROJECT,
HttpContext.Current.User.Identity.Name);
resp =
new MyCompleteList (coreSc.User_Read_All_Organisations(browser_request, utils,
validation, coreSc, coreDb));
scope.Complete();
}
else
{
resp.SetResponseNotLoggedIn();
}
}
}
catch (TransactionAbortedException ex)
{
resp.SetResponseServerError();
}
catch (ApplicationException ex)
{
resp.SetResponseServerError();
}
return resp;
}
你可以看到我是否要使用"使用"每个端点(大约300个)的事务范围部分将成为大量重复的代码。
无论如何都要减少重复量?
答案 0 :(得分:2)
您可以编写一个辅助方法,在将您的实际代码作为lambda调用时处理事务逻辑。
public static T Execute<T>(Func<T> func, TransactionExecutionOptions options = null)
{
options = options ?? TransactionExecutionOptions.Default;
T res;
using (var tx = new TransactionScope(options))
{
res = func();
tx.Complete();
}
return res;
}
根据您的需要,您可以为Func
参数提供其他参数;例如,Execute
方法也可以打开数据库连接并将其传递给func(然后将Func<IDbConnection, T>
作为参数类型)。 YMMV。
对于你的例子:
public MyCompleteList ReadOrganisations()
{
MyCompleteList resp = new MyCompleteList ();
try
{
resp = Execute(() => {
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
DC_Base browser_request = new DC_Base(PROJECT);
browser_request.cmd_user_id = coreDb.GetUserIDFromLoginName(PROJECT,
HttpContext.Current.User.Identity.Name);
resp =
new MyCompleteList (coreSc.User_Read_All_Organisations(browser_request, utils,
validation, coreSc, coreDb));
scope.Complete();
}
else
{
resp.SetResponseNotLoggedIn();
}
});
}
catch (TransactionAbortedException ex)
{
resp.SetResponseServerError();
}
catch (ApplicationException ex)
{
resp.SetResponseServerError();
}
return resp;
}
如果可能,您还可以将SetResponse*()
方法分解为基类或接口(比如IMyResponse),从而可以在Execute
方法中处理此方面。
public static T Execute<T>(Func<T> func, TransactionExecutionOptions options = null) where T : IMyResponse
{
options = options ?? TransactionExecutionOptions.Default;
T res;
try
{
using (var tx = new TransactionScope(options))
{
res = func();
tx.Complete();
}
}
catch (TransactionAbortedException ex)
{
res.SetResponseServerError();
}
catch (ApplicationException ex)
{
res.SetResponseServerError();
}
return res;
}
答案 1 :(得分:1)
1-按如下所示创建ServiceBase类
public class ServiceBase
{
protected void ExecuteOperation(Action codetoExecute)
{
try
{
using (TransactionScope scope = new TransactionScope())
{
codetoExecute.Invoke();
scope.Complete();
}
}
catch (TransactionAbortedException ex)
{
// handle exception
}
catch (ApplicationException ex)
{
// handle exception
}
}
}
2-每个新服务必须从ServiceBase继承并调用ExecuteOperation。代码如下:
ExecuteOperation(() =>
{
// Custom code here
});
3-执行不希望返回结果的操作时,原子事务非常有用。