如何避免重复"使用"码

时间:2017-07-07 10:50:06

标签: c# sql sql-server wcf transactions

我有一个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个)的事务范围部分将成为大量重复的代码。

无论如何都要减少重复量?

2 个答案:

答案 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-执行不希望返回结果的操作时,原子事务非常有用。