我使用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(来自参与者表格的FK)InterestId(FK兴趣表)
我添加了公共虚拟ICollection参与者{get;组;在兴趣模型和
公共虚拟ICollection兴趣{get;组;在参与者模型中形成多对多关联。 我的数据上下文类如下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语句已终止。
理想情况下,根据我的想法,它应该在参与者表中插入参与者信息,并在参与者兴趣表中插入参与者兴趣。但它试图在Interests表中插入记录,这不应该发生。请帮我解决这个问题。我可能通过创建多对多关联做错了。
由于
注意:我可以理解这个问题,因为Interests集合没有添加/附加到上下文,但我无法找到如何将Interest集合添加到具有存储库模式和工作单元的相同上下文中。
请提供解决方案。提前致谢
答案 0 :(得分: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自动设置,因为您是将其添加到参与者的Interests属性中。