C# ASP.net MVC EF Codefirst重复条目

C# ASP.net MVC EF Codefirst重复条目,c#,asp.net,entity-framework,ef-code-first,duplicates,C#,Asp.net,Entity Framework,Ef Code First,Duplicates,使用Asp.NETMVC4和EF5.0 问题: public class ViewModel { public IQueryable<DinnerEvent> events { get; set; } public IQueryable<User> users { get; set; } } 每当我在dropdownlist中选择一个用户并将帖子提交给Action时。 发生了两件事: 用户被添加到DinnerEvent,其作用是: 选择的用户是重复的,因

使用Asp.NETMVC4和EF5.0

问题:

public class ViewModel
{
    public IQueryable<DinnerEvent> events { get; set; }
    public IQueryable<User> users { get; set; }
}
每当我在dropdownlist中选择一个用户并将帖子提交给Action时。 发生了两件事:

  • 用户被添加到DinnerEvent,其作用是:

  • 选择的用户是重复的,因此我现在在数据库的用户表中有两个该用户的实例。这是不好的(




  • 这是设置

    我创建了两个实体: 晚餐事件和用户

    [HttpPost]
    public ActionResult AddAttendantToEvent(int users  , int EventID )
    {
        if (ModelState.IsValid)
        {
            var user = userRepository.Find(users);
            dinnereventRepository.Find(EventID).Attendants.Add(user); //Add the User to the Event.
            dinnereventRepository.Save();
            return RedirectToAction("Index");
        }
        else
        {
            return View();
        }
    }
    
    DinnerEvent类具有指向参与者(用户)集合的导航属性

    视图-迭代所有事件,并添加一个包含每个事件的所有用户的下拉列表。

    我做错了什么

    请求的存储库代码:

    public ViewResult Index()
    {
        ViewModel viewdata = new ViewModel();
        viewdata.events = dinnereventRepository.AllIncluding(m => m.Attendants);
        viewdata.users = userRepository.All;
        return View(viewdata);
    }
    
    缩小到只包含Save()方法

    注意,这都是脚手架自动生成的代码

    public class DinnerEventRepository : IDinnerEventRepository
    {
        MadklubContext context = new MadklubContext();
    
        public void Save()
        {
            context.SaveChanges();
        }        
    }
    
    public class MadklubContext : DbContext
     {     
    
       public DbSet<Madklub.Models.User> Users { get; set; }
    
       public DbSet<Madklub.Models.MadklubEvent> MadklubEvents { get; set; }
    
     }
    
    public class dinnerenterepository:IDinerEventRepository
    {
    MadklubContext=new MadklubContext();
    公共作废保存()
    {
    SaveChanges();
    }        
    }
    公共类MadklubContext:DbContext
    {     
    公共数据库集用户{get;set;}
    公共DbSet MadklubEvents{get;set;}
    }
    
    工作单元模式:(顺便说一句,使您的回购/uow IDisposable,以便您可以清理DbContext实例)

    用法:

    [HttpPost]
    public ActionResult AddAttendantToEvent(int users  , int EventID )
    {
        if (ModelState.IsValid)
        {
            // this should be a using statement once you implement IDisposable
            // e.g. using( var uow = new RsvpUnitOfWork() ) { ... }
            var uow = new RsvpUnitOfWork();
            // you need to validate that user != null
            var user = uow.UserRepo.Find(users);
            // possible null reference exception if dinner event not found for EventID
            uow.DinnerEventRepo.Find(EventID).Attendants.Add(user); //Add the User to the Event.
            uow.Save();
            return RedirectToAction("Index");
        }
        else
        {
            return View();
        }
    }
    

    您可以发布存储库的代码吗?我已经添加了存储库代码,注意:这都是自动生成的代码。@KristianGrønborgNissen,复制的原因是,您正在添加一个分离的实体(因此EF不知道它存在)我认为Johan是对的,您必须添加一个分离的对象。Find方法是否分离该对象?使用工作单元模式;创建一个类,该类具有每个存储库的实例,并将单个DbContext实例传递给每个存储库,以便它们共享相同的DbContext。这就解决了d问题。非常感谢。所以问题是,存储库没有使用同一个DbContext实例?!是的-您将
    UserRepository
    的上下文中的
    User
    对象引入到
    dinneretropository
    的上下文中,这使它看起来是新的,因此是一个添加/插入操作。
    public class DinnerEventRepository : IDinnerEventRepository
    {
        MadklubContext context = new MadklubContext();
    
        public void Save()
        {
            context.SaveChanges();
        }        
    }
    
    public class MadklubContext : DbContext
     {     
    
       public DbSet<Madklub.Models.User> Users { get; set; }
    
       public DbSet<Madklub.Models.MadklubEvent> MadklubEvents { get; set; }
    
     }
    
    public class DinnerEventRepository : IDinnerEventRepository
    {
        MadklubContext _context = new MadklubContext();
    
        public void Save()
        {
            _context.SaveChanges();
        }  
    
        public DinnerEventRepository( MadklubContext context = null )
        {
            _context = context ?? new MadklubContext();
        }      
    }
    
    public class UserRepository //: IUserRepository
    {
        MadklubContext _context = new MadklubContext();
    
        public void Save()
        {
            _context.SaveChanges();
        }  
    
        public UserRepository( MadklubContext context = null )
        {
            _context = context ?? new MadklubContext();
        }      
    }
    
    public class RsvpUnitOfWork // come up with a better name
    {
        MadklubContext _context = new MadklubContext();
    
        public DinnerEventRepository DinnerEventRepo { get; private set; }
        public UserRepository UserRepo { get; private set; }
    
        public RsvpUnitOfWork()
        {
            DinnerEventRepo = new DinnerEventRepository( _context );
            UserRepo = new UserRepository( _context );
        }
    
        public void Save()
        {
            _context.SaveChanges();
        }
    }
    
    [HttpPost]
    public ActionResult AddAttendantToEvent(int users  , int EventID )
    {
        if (ModelState.IsValid)
        {
            // this should be a using statement once you implement IDisposable
            // e.g. using( var uow = new RsvpUnitOfWork() ) { ... }
            var uow = new RsvpUnitOfWork();
            // you need to validate that user != null
            var user = uow.UserRepo.Find(users);
            // possible null reference exception if dinner event not found for EventID
            uow.DinnerEventRepo.Find(EventID).Attendants.Add(user); //Add the User to the Event.
            uow.Save();
            return RedirectToAction("Index");
        }
        else
        {
            return View();
        }
    }