简体   繁体   中英

Trouble getting Unit of Work and Repository Pattern Working in MVC app

I have a View that is bound to a NewUserViewModel which is posted to this method of the controller.

    [HttpPost]
    public ActionResult NewUser(NewUserViewModel newUser)
    {
        var user = new User();
        user.Id = newUser.Id;
        user.Email = newUser.Email;
        //more mapping hidden for brevity

        //here is where the trouble starts
        _userService.AddNewUser(user);

        return RedirectToAction("Users");
    }

The _userService is in a private field that is instantiated in the controllers constructor like this

    private IUserService _userService;

    public ControllerName()
    {
        _userService = new UserService();
    }

The AddNewUser method on the _userService looks like this.

        public void AddNewUser(User newUser)
        {
        using (var uow = new UnitOfWorkUser(new Context()))
        {
            using (var _userRepo = new UserRepository(uow))
            {
                _userRepo.InsertOrUpdate(newUser);
                uow.Save();
            }
        }
    }

The constructor of the UserRepository looks like this.

    private Context _context;

    public UserRepository(UnitOfWorkUser unitOfWork)
    {
        _context = unitOfWork.Context;
    }

and the unitOfWorkLooks like this.

    public class UnitOfWorkUser :IDisposable, IUnitOfWork
{
    private readonly Context _context;

    public UnitOfWorkUser(Context context = null)
    {
       _context = context ?? new Context();
    }

    public int Save()
    {
        return _context.SaveChanges();
    }

    internal Context Context
    {
        get { return _context; }
    }

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

And the InsertOrUpdate Method on the _userRepo looks like this.

 public virtual void InsertOrUpdate(User user)
    {
        if (user.Id == default(int))
        {
            _context.Users.Add(user);
        }
        else
        {
            _context.Entry(user).State = System.Data.EntityState.Modified;
        }
    }

When I get to the _context.Users.Add(user); in the method above I get this error

An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

I thought by passing in the Context with the UnitOfWork Object in the constructor of the UserRepository I was going to be avoiding these errors.

What am I doing wrong?

在asp.net mvc中有一种更好的方法来使用UOW,您不必在上下文中考虑实体生存时间的许多方面,因此我建议阅读本文

This looks very wrong to me. The purpose of unit work pattern is to consolidate all your "work" in one object. There is several issue with the following code:

  1. Looks like you are disposing the DBContext Twice

  2. Since you only need dbcontext, you shouldn't only pass dbcontext to the repository instead of UOW object

  3. You might want to have a internal reference to the UserRepository. It should be used to group your Repositories and ensure they all share the same EF context instance. A sample will look like UnitOfWorkUser.UserRepo.Save(newUser)

      using (var uow = new UnitOfWorkUser(new Context())) { using (var _userRepo = new UserRepository(uow)) { _userRepo.InsertOrUpdate(newUser); uow.Save(); } } 

Here is an example on how you use UOW,

http://www.mattdurrant.com/ef-code-first-with-the-repository-and-unit-of-work-patterns/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM