GGG*_*GGG 5 asp.net-mvc many-to-many entity-framework code-first
我正在使用具有以下配置的EF Code First
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<UserProfile>()
.HasMany(x => x.TeamLeaders)
.WithMany()
.Map(m => m.MapLeftKey("UserId")
.MapRightKey("TeamLeaderId")
.ToTable("UserTeamLeaders"));
}
Run Code Online (Sandbox Code Playgroud)
TeamLeaders是一个用户的ICollection,即它是一个自我引用很多关系.
用简单的英语,用户可以拥有多个团队领导.这种配置似乎是正确的,因为它创建了我期望的决斗FK/PK链接表.
我有一个MVC4应用程序,允许编辑,添加和删除集合中的团队领导.
在我的控制器中,我最初有以下内容:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
context.Entry(original).CurrentValues.SetValues(model);
Run Code Online (Sandbox Code Playgroud)
但是,最后一行未能将TeamLeaders集合标记为已更新,并且当我调用SaveChanges()时,未记录任何更改.
相反,我在我的User类上编写了一个简单的CopyProperties方法,该方法使用反射手动复制属性,所以在我的控制器中我现在有:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
//context.Entry(original).CurrentValues.SetValues(model);
original.CopyProperties(model);
Run Code Online (Sandbox Code Playgroud)
但是,这太过分了,SaveChanges尝试将新用户添加到与所选团队负责人的配置文件匹配的系统中.
任何人都可以建议我做错了哪一部分?我不确定是否需要更新映射,或者更改将属性从视图模型复制到模型的方式
您必须根据您的更改修改用户TeamLeaders中加载的集合,以便更改检测可以识别哪些领导者已被删除以及哪些已被添加。original当您调用时SaveChanges,EF 将根据检测到的更改为连接表编写适当的 DELETE 和 INSERT 语句。最简单的方法如下所示:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
original.TeamLeaders.Clear();
foreach (var teamLeader in model.TeamLeaders)
{
var user = context.UserProfiles.Find(teamLeader.UserId);
if (user != null)
original.TeamLeaders.Add(user)
}
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
Find如果团队领导者已经加载,将从上下文中获取团队领导者。如果未加载,它将查询数据库。
如果您想避免额外的查询,您可以手动将团队负责人附加到上下文:
var original = context.UserProfiles
.Include("TeamLeaders")
.Single(x => x.UserId == model.UserId);
original.TeamLeaders.Clear();
foreach (var teamLeader in model.TeamLeaders)
{
var user = context.UserProfiles.Local
.SingleOrDefault(o => o.UserId == teamLeader.UserId);
if (user == null)
{
user = new User { UserId = teamLeader.UserId };
context.UserProfiles.Attach(user);
}
original.TeamLeaders.Add(user)
}
context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
除了加载的第一个查询之外,original这里不涉及进一步的数据库查询。
顺便说一句:您应该能够将强类型Include版本与 EF Code First 一起使用:
Include(u => u.TeamLeaders)
Run Code Online (Sandbox Code Playgroud)
您只需要using System.Data.Entity;在代码文件中即可访问此版本。
| 归档时间: |
|
| 查看次数: |
2006 次 |
| 最近记录: |