我遇到了Entity Framework 6.1.3 CodeFirst多对多关系的问题。我的模型基本上是这样的:
class Schedule
{
int Id { get; set; }
}
class Contest
{
int Id { get; set; }
ICollection<Schedule> GameSchedules { get; set; }
}
我的上下文供参考:
class MyContext
{
MyContext() : base("name=DefaultConnection")
{
// no lazy loading for us
this.Configuration.LazyLoadingEnabled = false;
// do not auto detect changes for me
this.Configuration.AutoDetectChangesEnabled = false;
// we don't want our stuff to be wrapped in proxies
this.Configuration.ProxyCreationEnabled = false;
}
}
实体Farmework CodeFirst configuraiton:
class ContestConfiguration : EntityTypeConfiguration<Contest>
{
ContestConfiguration()
{
// setup many-to-many table between game schedules and contests
this.HasMany(contest => contest.GameSchedules)
.WithMany(schedule => schedule.Contests)
.Map(
contestSchedule =>
{
contestSchedule.MapLeftKey("ContestId");
contestSchedule.MapRightKey("ScheduleId");
contestSchedule.ToTable("ContestSchedule", "something");
});
}
}
在创建与现有计划的比赛后,我执行以下操作,并且我看到两个sql语句进入,一个创建比赛,一个创建MTM表的记录。
Contest Add(Contest entity)
{
// setup schedules
entity.GameSchedules.ToList().ForEach(schedule => this.Context.Entry(schedule).State = EntityState.Unchanged);
// call base add method
return base.Add(entity);
}
然而,当我尝试更新时,它是一个非常不同的故事。我尝试了很多方法,并且无法让CodeFirst更新MTM表中的关系。它或者尝试删除计划以及MTM记录,或者它什么都不做。关于如何实现这一令人兴奋的壮举的任何想法?
答案 0 :(得分:0)
好的,想通了。首先,删除ManyToManyCascadeDeleteConvention或者从MTM表中删除每个DELETE,它也会尝试删除计划或竞赛。这是因为默认情况下,EntityFramework将级联删除设置为true。
// remove many-to-many cascade auto delete
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
现在这里是更新的代码 1.确保已将新计划复制到新集合 2.使用新数据修改现有实体(这可以在更新MTM表之前或之后完成) 3.为简单起见,我刚刚从MTM表中删除了与此链接的所有当前行,并为了简洁起见添加了新行。 4.保存更改以确保删除计划 5.现在添加新的 6.再次保存更改以确保添加新计划
public void Update(Contest entity)
{
// (1) generate new collection so that the reference doesn't get overwritten
var schedulesToAdd = entity.GameSchedules.ToList();
// (2) get entry
var entry = this.context.Entry(entity);
// set entry to modified
entry.State = EntityState.Modified;
// save the current state
this.Context.SaveChanges();
// get the existing context from the db
var existingContest = this.Set.Where(contest => contest.Id == entity.Id).Include(contest => contest.GameSchedules).SingleOrDefault();
// get the object context
var context = ((IObjectContextAdapter)this.Context).ObjectContext;
// iterate over existing relationships and eliminate
foreach (var existingSchedule in existingContest.GameSchedules.ToList())
{
var schedule = this.Context.Schedules.Find(existingSchedule.Id);
// (3) mark relationship as deleted
context.ObjectStateManager.ChangeRelationshipState(existingContest, schedule, contest => contest.GameSchedules, EntityState.Deleted);
}
// (4) save the current state
result = this.SaveChanges();
// iterate over new entity relationships and add them
foreach (var newSchedule in schedulesToAdd)
{
// find the schedule
var schedule = this.Context.Schedules.Find(newSchedule.Id);
// (5) mark relationship as added
context.ObjectStateManager.ChangeRelationshipState(existingContest, schedule, contest => contest.GameSchedules, EntityState.Added);
}
// (6) save the current state
this.SaveChanges();
}
请记住,您需要提出一些更复杂的行为来删除eixsting关系并添加新的关系。这只是一个例子。