0

我正在使用 EF 代码优先方法和流利的 api。我的申请中有一个注册表单,在其中注册候选人可以从下拉列表中选择多个选项(对注册表单上的下拉列表感兴趣),其中包含一组预定义的选项(将来可能会增加,但机会非常少)。当用户提交表单时,我想将此记录保存到数据库中。所以我创建了以下实体。

将保存注册候选人信息的参与者班级

public class Participant
    {
        public Participant()
        {
            Interests = new Collection<Interest>();
        }
        [Key, ForeignKey("User")]
        public int Id { get; set; }
        [DisplayName("First Name")]
        [StringLength(50, ErrorMessage = "First name cannot be more than 50 characters")]
        [Required(ErrorMessage = "You must fill in first name")]
        public string FirstName { get; set; }

        [DisplayName("Last Name")]
        [StringLength(50, ErrorMessage = "Last name cannot be more than 50 characters")]
        [Required(ErrorMessage = "You must fill in last name")]
        public string LastName { get; set; }

        [Required(ErrorMessage = "You must indicate your full birthday")]
        [DisplayName("Birthday")]
        [DataType(DataType.DateTime)]
        public DateTime BirthDate { get; set; }

        [DisplayName("Gender")]
        [Required(ErrorMessage = "You must select gender")]
        public int Gender { get; set; }

        public string Address { get; set; }

        public int CountryId { get; set; }
        public Country Country { get; set; }

        [DisplayName("Zip code")]
        [StringLength(10, ErrorMessage = "Zip code cannot be more than 10 characters")]
        public string ZipCode { get; set; }

        public string Mobile { get; set; }

        public string PhotoUrl { get; set; }

        public virtual User User { get; set; }

        public virtual ICollection<Interest> Interests { get; set; }

        public string MedicalConditions { get; set; }
}

注册表格上的“感兴趣”下拉列表中的兴趣类用户可以从“感兴趣”下拉列表中选择多个选项

兴趣班

 public class Interest
    {
        public Interest()
        {
            Participants = new Collection<Participant>();
        }
        public int Id { get; set; }
        public string InterestName { get; set; }
        public virtual ICollection<Participant> Participants { get; private set; }
    }

为了保持每个参与者的兴趣,我在 DB 中使用以下模式创建了一个 ParticipantInterests 表。ParticipantInterests Id (PK) ParticipantId(来自 Participants 表的 FK) InterestId(FK Interests 表)

我添加了 public virtual ICollection Participants { get; 放; } 在兴趣模型和

公共虚拟 ICollection 兴趣 { 获取;放; } 在 Participant 模型中形成多对多关联。 我的数据上下文类如下

public class STNDataContext : DbContext
    {
        public DbSet<Participant> Participants { get; set; }
        public DbSet<User> Users { get; set; }
        public DbSet<Country> Countries { get; set; }
        public DbSet<Interest> Interests { get; set; }
        public DbSet<Role> Roles { get; set; }
        public DbSet<SecurityQuestion> SecurityQuestions { get; set; }

        public DbSet<Tour> Tours { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Participant>()
                .HasKey(p => p.Id);

            modelBuilder.Entity<User>()
                .HasOptional(u => u.Participant)
                .WithRequired();

            modelBuilder.Entity<Participant>()
            .HasMany(p => p.Interests)
            .WithMany(i => i.Participants)
            .Map(m =>
            {
                m.ToTable("ParticipantInterests");
                m.MapLeftKey("ParticipantId");
                m.MapRightKey("InterestId");
            });

            modelBuilder.Entity<User>().HasRequired(u => u.Role);
            modelBuilder.Entity<Participant>().HasRequired(p => p.Country);
            modelBuilder.Entity<User>().HasOptional(u => u.SecurityQuestion);
        }


        public virtual void Commit()
        {
            base.SaveChanges();
        }

控制器动作代码

public virtual ActionResult Register(StudentRegisterViewModel studentRegisterViewModel)
        {
            if (ModelState.IsValid)
            {
                if (_userService.IsUserExists(studentRegisterViewModel.Participant.User) == false)
                {
                    studentRegisterViewModel.Participant.User.Username = studentRegisterViewModel.Username;
                    studentRegisterViewModel.Participant.User.Email = studentRegisterViewModel.Email;
                    studentRegisterViewModel.Participant.User.DateCreated = DateTime.Now;
                    studentRegisterViewModel.Participant.User.Id = 3;
                    studentRegisterViewModel.Participant.User.IsApproved = false;
                    studentRegisterViewModel.Participant.User.RoleId = 2;
                    studentRegisterViewModel.Participant.CountryId = 1;
                    var interests = new List<Interest>();
                    foreach (var interestItem in studentRegisterViewModel.SelectedInterests)
                    {
                        var interest = new Interest { Id = interestItem };
                        interest.Participants.Add(studentRegisterViewModel.Participant);
                        interests.Add(interest);
                        studentRegisterViewModel.Participant.Interests.Add(interest);
                    }
                    studentRegisterViewModel.Participant.Interests = interests;
                    _participantService.CreatParticipant(studentRegisterViewModel.Participant);
                    var user = _userService.GetUser(studentRegisterViewModel.Participant.User.Username);
                }
            }
            studentRegisterViewModel.Gender =
                Enum.GetNames(typeof(Gender)).Select(
                    x => new KeyValuePair<string, string>(x, x.ToString(CultureInfo.InvariantCulture)));
            studentRegisterViewModel.Interests = _interestService.GetAllInterests();
            return View(studentRegisterViewModel);
        }

参与者存储库 (DAL)

 public class ParticipantRepository : Repository<Participant>, IParticipantRepository 
    {
        public ParticipantRepository(IDatabaseFactory databaseFactory)
            : base(databaseFactory)
        {
        }
    }

参与者服务 (BLL)

public class ParticipantService : IParticipantService
    {
        private readonly IParticipantRepository _participantRepository;
        private readonly IUnitOfWork _unitOfWork;

        public ParticipantService(IParticipantRepository participantRepository, IUnitOfWork unitOfWork)
        {
            this._participantRepository = participantRepository;
            this._unitOfWork = unitOfWork;
        }

        public void CreatParticipant(Participant participant)
        {
            _participantRepository.Add(participant);
            _unitOfWork.Commit();
        }
}

数据库工厂

public class DatabaseFactory : Disposable, IDatabaseFactory
    {
        private STNDataContext _stnDataContext;
        public DatabaseFactory()
        {
            Database.SetInitializer<STNDataContext>(null);
        }
        public STNDataContext Get()
        {
            return _stnDataContext ?? (_stnDataContext = new STNDataContext());
        }
        protected override void DisposeCore()
        {
            if (_stnDataContext != null)
                _stnDataContext.Dispose();
        }
    }

工作单位

public class UniOfWork : IUnitOfWork
{
    private readonly IDatabaseFactory _databaseFactory;
    private STNDataContext _stnDataContext;

    public UniOfWork(IDatabaseFactory databaseFactory)
    {
        this._databaseFactory = databaseFactory;
    }

    public STNDataContext StnDataContext
    {
        get { return _stnDataContext ?? (_stnDataContext = _databaseFactory.Get()); }
    }

    public void Commit()
    {
        StnDataContext.Commit();
    }

}

当我尝试创建参与者时,出现以下错误。

无法将值 NULL 插入到列“InterestName”、表“StudyTourNetworkDB.dbo.Interests”中;列不允许空值。INSERT 失败。\r\n语句已终止。

理想情况下,根据我的想法,它应该在 Participants 表和 ParticipantsInterests 表中插入参与者信息。但它也试图在兴趣表中插入记录,这也不应该发生。请帮我解决这个问题。通过创建多对多关联,我可能做错了。

谢谢

注意:我可以理解这个问题,因为兴趣集合没有被添加/附加到上下文,但我无法找到如何将兴趣集合添加到具有存储库模式和工作单元的相同上下文中。

请给我解决方案。提前致谢

4

1 回答 1

0

您是正确的,因为您的兴趣对象正在重新添加,因为您的模型中保存的副本没有被 EF 跟踪,因此它认为它们是新的。相反,您需要从存储库中查找版本,然后添加这些版本。

代替:

var interests = new List<Interest>();
foreach (var interestItem in studentRegisterViewModel.SelectedInterests)
{
    var interest = new Interest { Id = interestItem };
    interest.Participants.Add(studentRegisterViewModel.Participant);
    interests.Add(interest);
    studentRegisterViewModel.Participant.Interests.Add(interest);
}
studentRegisterViewModel.Participant.Interests = interests;

尝试类似:

// Look up the actual EF entities which match your selected items.  You'll  
// probably need to adapt this to make it work
var selectedInterestIds = studentRegisterViewModel.SelectedInterests.Select(i => i.Id);
var interests = _interestService.GetAllInterests().Where(i => selectedInterestIds.Contains(i.Id));    
studentRegisterViewModel.Participant.Interests = interests;

请注意,对于多对多关系,您不需要设置双方-在您的示例中,您填写了兴趣实体的参与者字段-这将由 EF 自动设置,因为您将其添加到参与者的权益财产。

于 2012-12-10T08:35:19.447 回答