I am trying to perform a very simple task which is "Add the user with role in the database". The roles are already populated in the database and I am simply adding the role to the User roles collection but it keeps throwing the following exception:
The EntityKey property can only be set when the current value of the property is null.
Here is the code in User.cs:
public void AddRole(Role role)
{
if (!Exists(role))
{
role.User = this;
Roles.Add(role);
}
}
And here is the test that fails:
[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);
}
The Repository Code:
public bool Save(User user)
{
bool isSaved = false;
using (var db = new EStudyDevDatabaseEntities())
{
db.AddToUsers(user);
isSaved = db.SaveChanges() > 0;
}
return isSaved;
}
Here is the AddRole Method:
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);
}
}
And here is the whole exception:
------ 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.LightweightEntityWrapper1.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:
Here is my UserRepository and RoleRepository and they both uses separate contexts:
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()));
}
}
As, you can see the user and the role are using different context which you have already pointed out. The problem with using single datacontext is that I cannot layer the application properly.