2009-12-14 124 views
2

我試圖執行一個非常簡單的任務,這是「與數據庫中的角色添加用戶」。角色已經填充到數據庫中,我只是將該角色添加到用戶角色集合中,但它一直拋出以下異常:實體框架附加一個持久對象的新對象

EntityKey屬性只能在屬性的當前值爲空時設置。

這裏是User.cs代碼:

public void AddRole(Role role) 
     { 
      if (!Exists(role)) 
      { 
       role.User = this; 
       Roles.Add(role);     
      } 
     } 

這裏是失敗的試驗:

[Test]   
     public void should_save_user_with_role_successfully() 
     { 
      var _role = _roleRepository.GetByName("Student");       

      _user.AddRole(_role); 

      _userRepository.Save(_user); 

      Assert.IsTrue(_user.UserId > 0);    
     } 

資源庫代碼:

public bool Save(User user) 
     { 
      bool isSaved = false; 

      using (var db = new EStudyDevDatabaseEntities()) 
      { 
       db.AddToUsers(user); 
       isSaved = db.SaveChanges() > 0; 
      } 

      return isSaved; 

     } 

這裏是AddRole方法:

public bool Exists(Role role) 
     { 
      var assignedRole = (from r in Roles 
           where r.RoleName.Equals(role.RoleName) 
           select r).SingleOrDefault(); 

      if (assignedRole != null) return true; 

      return false; 
     } 

     public void AddRole(Role role) 
     { 
      if (!Exists(role)) 
      { 
       role.User = this; 
       Roles.Add(role);     
      } 
     } 

這裏是整個異常:

------ Test started: Assembly: EStudy.Repositories.TestSuite.dll ------ 

TestCase 'EStudy.Repositories.TestSuite.Repositories.when_saving_new_user.should_save_user_with_role_successfully' 
failed: System.InvalidOperationException : The EntityKey property can only be set when the current value of the property is null. 
at System.Data.Objects.EntityEntry.GetAndValidateChangeMemberInfo(String entityMemberName, Object complexObject, String complexObjectMemberName, StateManagerTypeMetadata& typeMetadata, String& changingMemberName, Object& changingObject) 
at System.Data.Objects.EntityEntry.EntityMemberChanging(String entityMemberName, Object complexObject, String complexObjectMemberName) 
at System.Data.Objects.EntityEntry.EntityMemberChanging(String entityMemberName) 
at System.Data.Objects.ObjectStateEntry.System.Data.Objects.DataClasses.IEntityChangeTracker.EntityMemberChanging(String entityMemberName) 
at System.Data.Objects.DataClasses.EntityObject.set_EntityKey(EntityKey value) 
at System.Data.Objects.Internal.LightweightEntityWrapper`1.set_EntityKey(EntityKey value) 
at System.Data.Objects.ObjectStateManager.AddEntry(IEntityWrapper wrappedObject, EntityKey passedKey, EntitySet entitySet, String argumentName, Boolean isAdded) 
at System.Data.Objects.ObjectContext.AddSingleObject(EntitySet entitySet, IEntityWrapper wrappedEntity, String argumentName) 
at System.Data.Objects.DataClasses.RelatedEnd.AddEntityToObjectStateManager(IEntityWrapper wrappedEntity, Boolean doAttach) 
at System.Data.Objects.DataClasses.RelatedEnd.AddGraphToObjectStateManager(IEntityWrapper wrappedEntity, Boolean relationshipAlreadyExists, Boolean addRelationshipAsUnchanged, Boolean doAttach) 
at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach) 
at System.Data.Objects.DataClasses.EntityCollection`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach) 
at System.Data.Objects.DataClasses.RelationshipManager.AddRelatedEntitiesToObjectStateManager(Boolean doAttach) 
at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity) 
C:\Projects\EStudy\EStudySolution\EStudy.BusinessObjects\Entities\EStudyModel.Designer.cs(97,0): at EStudy.BusinessObjects.Entities.EStudyDevDatabaseEntities.AddToUsers(User user) 
C:\Projects\EStudy\EStudySolution\EStudy.BusinessObjects\Repositories\UserRepository.cs(17,0): at EStudy.BusinessObjects.Repositories.UserRepository.Save(User user) 
C:\Projects\EStudy\EStudySolution\EStudy.Repositories.TestSuite\Repositories\Test_UserRepository.cs(47,0): at EStudy.Repositories.TestSuite.Repositories.when_saving_new_user.should_save_user_with_role_successfully() 


0 passed, 1 failed, 0 skipped, took 6.07 seconds (NUnit 2.5). 

UPDATE:

這是我UserRepository和RoleRepository,他們都使用單獨的上下文:

public bool Save(User user) 
     { 
      bool isSaved = false; 

      using (var db = new EStudyDevDatabaseEntities()) 
      {    
       db.AddToUsers(user); 
       isSaved = db.SaveChanges() > 0; 
      } 

      return isSaved; 

     } 

public Role GetByName(string roleName) 
     { 
      using (var db = new EStudyDevDatabaseEntities()) 
      { 
       return db.Roles.SingleOrDefault(x => x.RoleName.ToLower().Equals(roleName.ToLower())); 
      }   
     } 

如,你可以看到用戶和角色正在使用您已經指出的不同上下文。使用單個數據上下文的問題是我無法正確分層應用程序。

+0

這些ASP.NET FormsAuth用戶和角色? – 2009-12-14 21:50:57

+0

不只是表用戶和角色(自定義表與認證無關)。 – azamsharp 2009-12-14 21:55:29

回答

4

再次更新基於更新的問題

我不同意你「無法正常層中的應用」當您共享存儲庫之間的上下文。這是一個需要解決的問題,但它絕對是可以解決的。另外,我想你會發現它容易得多比當您嘗試使用多個上下文您創建多少的問題解決。

在任何情況下,真的有隻有兩個,您的問題可能的解決方案:

  1. 手動跟蹤其上下文的具體實體連接到,並將其傳輸(含附加和分離),必要時。
  2. 在存儲庫實例之間共享上下文。

在我們的ASP.NET MVC應用程序中,邏輯工作單元是單個請求。因此,我們在請求開始時實例化一個ObjectContext,在請求結束時處理它,並在創建它們時將其注入到新的存儲庫中。版本庫實例永遠不會超過一個請求。基於新的問題

更新

是否角色庫和用戶庫中的每個有一個(單獨)方面?以下是堆棧跟蹤中發生了什麼:

  1. 您將用戶添加到上下文中。
  2. RelationshipManager通過用戶並確保任何相關實體也在上下文中。這涉及到,除其他外,設置他們的EntityKey屬性。
  3. 假設角色來自不同的上下文(這似乎是這種情況,否則上下文應該檢測到該角色已經在上下文中),您應該會看到一個錯誤,指出您不能添加附加到的實體一個上下文到另一個上下文出於某種原因,你在這裏沒有看到。但是,這不是一個有效的操作。
  4. 相反,您在分配角色的EntityKey時會出錯。

在我看來,一次只使用一個ObjectContext應該是使用EntityFramework的一般規則。只有當你絕對被迫時,你才應該使用多個上下文,根據我的經驗,這幾乎從不是。同時使用多個ObjectContexts同時使用顯着比一次只使用一個ObjectContext更難。

OK,我不知道你映射的細節,但我希望AddRole是沿着線的東西更多:

public void AddRole(Role role) 
{ 
    this.Roles.Add(role); 
} 

...如果用戶 - >角色是..或:

public void AddRole(Role role) 
{ 
    this.Role = role; 
} 

如果用戶 - >角色是* .. 1。

如果這沒有幫助,請發佈異常的堆棧跟蹤。

+0

我更新了原帖!有用戶表,角色表和UserRoles。角色已預先填充。 UserRoles具有UserId和RoleId。 – azamsharp 2009-12-14 22:09:42

+0

查看最新的回覆。 – 2009-12-14 22:27:35

+0

謝謝!我已經更新了我的回覆! – azamsharp 2009-12-14 22:33:34