2009-11-11 52 views
0

在開發&使用Entity Framework進行學習時,我對模型中的一個實體運行測試時遇到了插入問題。具體來說,問題是一起運行一些測試。我會解釋一下自己:實體框架:使用標識列插入失敗「有時」使用OptimisticConcurrencyException

我的模型中有一個名爲「DtoCategoria」的實體,它有兩個成員:id:Int32和name:string,映射到一個表,其中id是一個標識列。這很好,很簡單。

我對這個DTO一個數據訪問層,稱爲CadCategoria,在那裏我已經創建了一個製備方法插入,如:

public class CadCategoria 
{ 
    protected readonly CUENTASEntities bd = Singletons.bd; 

    public bool add(EntityObject entity) 
    { 
     try 
     { 
      bd.AddObject(EntitySet, entity); 
      return bd.SaveChanges() > 0; 
     } 
     catch (Exception e) 
     { 
      bd.Detach(entity); 
      return false; 
     } 
    } 

    // and some other methods... update, delete, etc. 
} 

和其他一些通用的方法,以及用於更新和刪除。我使用單例模式在應用程序中分享上下文,如下所示:

public class Singletons 
{ 
    public static CUENTASEntities bd; 

    static Singletons() 
    { 
     bd = new CUENTASEntities(); 
    } 
} 

從現在開始看起來很好。但是,我創建了一些單元測試,看看每一件事情是還好吧,看起來像:

[TestClass] 
public class CadCategoriaTest 
{ 
    private CadCategoria bd = new CadCategoria();  

    [TestMethod] 
    public void addTest() 
    { 
     var catAdd = new DtoCategoria { name= "cat 1" }; 
     Assert.IsTrue(bd.add(catAdd)); 

     bd.delete(catAdd); 
    } 

    [TestMethod] 
    public void deleteTest() 
    { 
     var catDel = new DtoCategoria { name= "cat 2" }; 
     bd.add(catDel); 

     Assert.IsTrue(bd.delete(catDel)); 
     Assert.IsFalse(bd.delete(new DtoCategoria { name= "not exists", id = -1 })); 
    } 

    [TestMethod] 
    public void updateTest() 
    { 
     var a = new DtoCategoria { name= "cat 3" }; 
     bd.add(a); 
     a.nombre = "name modified"; 
     Assert.IsTrue(bd.update(a)); 

     var b = bd.get(-1); 
     Assert.IsFalse(bd.update(b)); 

     bd.delete(a); 
    } 
} 

和現在正值交流中心的事情:

  • 當單獨運行更新測試:測試通過
  • 當運行更新&添加測試:測試通過
  • 當運行更新&刪除測試:更新測試失敗並刪除通過!

錯誤在測試的第二行:bd.add(a);在上下文的SaveChanges方法中引發一個OptimisticConcurrencyException。

任何想法,爲什麼我有一個帶有標識列的插入的併發異常?只有當與刪除測試方法結合??這與添加測試結合時不會發生,它也會執行「添加」操作?

恐怕如果在測試中失敗了,它也可能在真實應用程序中失敗。它不會發生另一個沒有身份列ID作爲PK的DTO。

任何想法?非常感謝!!!

塞爾吉

+1

使ObjectContext成爲單例幾乎肯定會導致問題。我不確定它是否會導致* this *,但我不會在這個問題解決之前解決這個問題,因爲當你這樣做的時候問題可能會消失。此外,吃例外幾乎總是錯誤的,並可能掩蓋實際問題。 –

+0

我繼續測試,我發現測試運行的順序很重要:刪除和更新,失敗,但更新和刪除,通過...... 任何想法? – Sergi

+0

我忘了說我正在開發一個Windows應用程序,它是單線程的,可能測試運行時是多線程的?如果是這樣,這可能是問題,因爲,對於MSDN:「ObjectContext類不是線程安全的。在多線程場景中無法確保ObjectContext中數據對象的完整性。」 可能是這個原因嗎? – Sergi

回答

0

嗯,我想我找到了問題的最後一次。它與Singleton模式無關。事實是,我刪除測試試圖刪除並且不存在對象,只是爲了檢查,如果該方法返回false:

Assert.IsFalse(bd.delete(new DtoCategoria { name= "not exists", id = -1 })); 

但在bd.delete方法,我忘了dettach從該unexisting對象上下文,所以下一次我試圖做context.SaveChanges(),它是triyng再次刪除錯誤的對象,所以它再次引發了OptimisticException,因爲沒有行被刪除。

這是我的BD。刪除方法:

public bool delete(EntityObject entity) 
    { 
     try 
     { 
      if (entity.EntityKey == null) 
       entity.EntityKey = bd.CreateEntityKey(EntitySet, entity); 
      if (entity.EntityState == EntityState.Detached) 
       bd.AttachTo(EntitySet, entity); 
      bd.DeleteObject(entity); 
      return bd.SaveChanges() > 0; 
     } 
     catch (Exception e) 
     { 
      bd.Detach(entity); 
      return false; 
     } 
    } 

的解決辦法是在閉鎖段的bd.Detach(entity);命令,告訴上下文這個模擬實體忘記。快速查看SQL分析器給了我答案。

這就是爲什麼順序很重要:刪除然後更新導致更新崩潰。離開刪除作爲最後一個,工作得很好,因爲沒有更多的SaveChanges()到上下文。

感謝您的patiente @Craig,並對由此造成的不便深表歉意。

Sergi。

相關問題