views:

100

answers:

1

I am using EF 4 Feature CTP 4.

I have the following database schema:

[Users] 1-M [UserRoles] M-1 [Roles]

I have a User and Role class (both POCOs).

When I try to associate an existing role to a user, a new record is getting inserted in the Roles table, instead of only inserting a new record in UserRoles.

So say I have User 1 and want to Associate with Role 2. When I try to save, I end up with a new record in Roles named "Role 2" with a record in UserRoles to the newly created Role. From the code below I was expecting only a new record in UserRoles with the mapping between User and Role.

Here is my POCO classes, mapping and test.

POCO Classes:

public class User {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public byte[] DataVersion { get; set; }

        private List<Role> roles = new List<Role>();
        public virtual IList<Role> Roles {
            get {
                return roles;
            }
        }   
    }

public class Role {
        public int Id { get; set; }
        public string Name { get; set; }

        public List<User> Users { get; set; }
    }

Mapping:

public class UserConfiguration : EntityConfiguration<Domain.User> {
        public UserConfiguration() {
            this.MapSingleType(user => new {
                UserId = user.Id,
                FirstName = user.FirstName,
                LastName = user.LastName,
                DataVersion = user.DataVersion
            });

            this.Property(u => u.DataVersion).IsConcurrencyToken().HasStoreType("timestamp").StoreGeneratedPattern = StoreGeneratedPattern.Computed;

            //Users <--> Roles
            this.HasMany(u => u.Roles).WithMany(r => r.Users)
                .Map("UserRoles", (u, r) => new {
                    UserId = u.Id,
                    RoleId = r.Id
                });  
        }
   }

public class RoleConfiguration : EntityConfiguration<Domain.Role> {
        public RoleConfiguration() {
            this.MapSingleType(role => new {
                RoleId = role.Id,
                RoleName = role.Name
            });

        }
    }

Test:

public void AssignRoleTest() {
            var userId = 1;
            User user;

            var userRepo = new UsersRepository();
            user = userRepo.GetUser(userId);

            var roleRepo = new RolesRepository();

            var roleId = 2;
            var role = roleRepo.GetRole(roleId);

            user.Roles.Add(role);

            userRepo.SaveUser(user);

     }

Code for Repository Save:

public void SaveUser(User user) {
        if (user.Id > 0) {
            dbContext.Users.Attach(user);
            dbContext.MarkAsModified(user);
        }
        else {
            dbContext.Users.Add(user);
        }
A: 

Try to use context.DetectChanges() in your SaveUser method. It should work because you are using same context for both loading and saving entity graph.

Ladislav Mrnka
That didn't work, even after I exposed DetectChanges (not in dbContext)
B Z