2017-07-07 37 views
1

我有一個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

呀創建一個父類,在那裏將您的代碼。 –

+0

你是什麼意思?你可以提供一些更多的細節,目前這個wcf服務從接口繼承到基類然後到頂級類你是什麼意思添加父類?這些功能是由外部客戶端通過json – Dizzle

+0

調用您的問題不是很清楚 - 「使用」如何導致代碼重複? – PaulF

回答

2

你可以寫一個輔助方法,處理該事務邏輯在調用實際代碼爲拉姆達。

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>作爲參數類型)。因人而異。

對於示例:

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; 
    } 
+0

確定這看起來像什麼我在想,我可以給它一個測試,謝謝你的答案。 – Dizzle

+0

是的,我已經在所有響應繼承的接口中有響應,所以這看起來更好 – Dizzle

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-原子事務在執行不期望結果的操作時很有用。