开发者

Adding user to a role inserts a duplicate user into users table

开发者 https://www.devze.com 2023-03-01 14:45 出处:网络
I\'m using Entity Framework code first to manage a database backstore for my users.I have an \"add role to user\" operation that pulls a user from the db, adds that user to the role, and then saves ch

I'm using Entity Framework code first to manage a database backstore for my users. I have an "add role to user" operation that pulls a user from the db, adds that user to the role, and then saves changes. However, when I do this a new copy of the user is inserted into the database with a new/different ID (unique key) than the user I pulled from the db and I'm not sure why. Any thoughts on why this is happening?

 IEnumerable<long>开发者_如何学编程 usersIdsToGiveRole = from u in vm.UsersNotInSelectedRole where u.IsSelected select u.Id; // say, yields "5"
 IEnumerable<User> usersToGiveRole = _userRepository.InternalUsers.Where(u => usersIdsToGiveRole.Contains(u.ID)); // gets user with ID 5
 foreach (var user in usersToGiveRole)
 {
       selectedRole.UsersWithRole.Add(user);
 }


 _roleRepository.SaveChanges(); // creates new user with ID 6 cloning all other fields of user 5


Just a guess: You seem to have separate ObjectContexts for _userRepository and for _roleRepository. By loading usersToGiveRole from the _userRepository you attach to this context. selectedRole seems to be attached to the other context of _roleRepository. When you add the user to selectedRole.UsersWithRole you add it to this second context (user is now in added state in the context of _roleRepository). When you call SaveChanges of this context now a new User object is created in the database.

Solution: Make sure that you only use one single context in both repositories.

Edit

In short what I mean:

Don't do this:

class UserRepository
{
    private readonly MyContext _context;

    public UserRepository()
    {
        _context = new MyContext();
    }

    public void SaveChanges()
    {
        _context.SaveChanges();
    }
}

class RoleRepository
{
    private readonly MyContext _context;

    public RoleRepository()
    {
        _context = new MyContext();
    }

    public void SaveChanges()
    {
        _context.SaveChanges();
    }
}

...

var userRepository = new UserRepository();
var roleRepository = new RoleRepository();

// CRUD

userRepository.SaveChanges();

// perhaps other CRUD

roleRepository.SaveChanges();

Instead do this:

class UserRepository
{
    private readonly MyContext _context;

    public UserRepository(MyContext context)
    {
        _context = context;
    }
}

class RoleRepository
{
    private readonly MyContext _context;

    public RoleRepository(MyContext context)
    {
        _context = context;
    }
}

...

using (var context = new MyContext())
{
    var userRepository = new UserRepository(context);
    var roleRepository = new RoleRepository(context);

    // CRUD

    context.SaveChanges();
}

The context (or Unit of Work) is always a level above the repositories, should be created outside and injected into the repos.

0

精彩评论

暂无评论...
验证码 换一张
取 消