2011-07-20 62 views
0

我想知道什麼是執行下面的最好辦法或做法:EF業務C#的MySQL連接器

我有一個名爲EditUser方法,該方法具有以下定義:

public void EditUser(user user, Roles role) 
    { 
     using (TestEntities entities = new TestEntities()) 
     { 
      entities.Connection.Open(); 
      using (DbTransaction trans = entities.Connection.BeginTransaction()) 
      { 
       try 
       { 
        var tmpUser = entities.users.Where(fields => fields.UserId == user.UserId).FirstOrDefault(); 

        RoleManagement rm = new RoleManagement(); 
        string oldRole = tmpUser.roles.FirstOrDefault().Name; 
        string newRole = rm.GetRoleName(role); 

        if (oldRole == newRole) 
        { 
         entities.users.ApplyCurrentValues(user); 
        } 
        else 
        { 
         rm.UnbindRoles(tmpUser.UserId, entities.Connection); 
         this.DeleteUser(tmpUser.UserId, entities.Connection); 
         this.Register(user, role, entities.Connection); 
        } 

        entities.SaveChanges(); 
        trans.Commit(); 
       } 
       catch (Exception ex) 
       { 
        trans.Rollback(); 
        throw ex; 
       } 
      } 
     } 
    } 

正如你可能會注意到我調用了幾種方法:UnbindRoles,DeleteUser和RegisterUser,它們都需要在同一事務下運行(EditUser運行的同一事務),以防萬一發生故障時我需要回滾。

現在我的問題主要在這裏...方法RegisterUser也啓動一個新的事務,因爲它添加一個用戶併爲新用戶分配一個角色。

任何人都可以描述如何實現這個最好的方法嗎?我試圖用一個TransactionScope塊,但因爲我在運行中等信任環境

編輯

這個應用程序確認MySQL的.NET連接器供應商,因爲我在中等信任使用的TransactionScope時有一個bug失敗剛剛使用MS SQL Server數據庫測試過相同的場景,並且其工作沒有任何問題

+0

另一個話題: 糟糕!前投! 除非你真的想失去你的堆棧,否則你應該拋出。 – BennyM

+0

拋出被調用者捕獲並再次拋出,以便Application_Error事件中的Global.asax將執行錯誤的通用處理 – Ryan

+0

只要確保知道throw之間的區別;並扔掉ex; – BennyM

回答

1

如果我的理解正確,您遇到的問題是您對DeleteUser和RegisterUser的調用正在啓動新的事務並需要登錄當前的事務。

幾種方法來解決這個問題:

A)當你創建一個TransactionScope你可以說,他們只需要創建一個,如果沒有一個已經可用。 B)不是採用第一種方法,而是引入私有方法,讓我們說InnerEdit和InnerRegister包含邏輯,但不打開或關閉代碼保留在公共可用編輯和註冊方法中的任何事務。這些「內部」方法可以重用,而公共方法則包含基礎設施。如果你打算在第二個方法爲谷歌面向方面的編程,可以解決這些「橫切關注點」

public void EditUser(user user, Roles role) 
{ 
    using (TestEntities entities = new TestEntities()) 
    { 
     entities.Connection.Open(); 
     using (DbTransaction trans = entities.Connection.BeginTransaction()) 
     { 
      InnerEditUser(entities, trans); 
      InnerThat(entities, trans); 
      InnerThis(entities,trans); 
      entities.SaveChanges(); 
      trans.Commit(); 
     } 
    } 
} 

TransactionScope options MSDN link

+0

我不確定你在哪裏得到了userFromDb EntityObject下的ChangeRole方法,請你解釋一下嗎? – Ryan

+0

或者你創建的那些用戶和角色類?然後,我會添加功能,以適應手頭的問題。 – BennyM

+0

但問題是,在每個方法我保存更改(調用entities.SaveChanges()),因爲有時我需要手動調用ChangeRole或AddUser方法(沒有被EditUser或RegisterUser調用),這就是爲什麼我需要有一個事務,以便我可以提交或回滾取決於發生了什麼 – Ryan

0

您可以註冊檢查現有事務並只創建一個(如果不存在)?這就是嵌套的TransactionScopes在類似情況下所能做到的。

+0

是的,這是一個選項,但我一開始就認爲這個選項是某種「補丁工作」 – Ryan

+0

這實際上是TransactionScope所做的 - 它在環境事務中使用,如果有的話,否則創建一個新事務。你只是自己做這件事,因爲你不能使用TransactionScope。如果你用一種方法很好地包裝它,這對我來說似乎是合法的。 – jlew