我正在使用Entity Framework 4.3 Code First,我在更新多对多关系方面遇到了问题。
我定义了以下类:
public abstract class Entity
{
[Column(Order = 0)]
[Key]
public int Id { get; set; }
[Timestamp]
[Column(Order = 1)]
public byte[] Version { get; set; }
}
public class Video : Entity
{
public string Title { get; set; }
public string Description { get; set; }
public TimeSpan Length { get; set; }
public virtual ICollection<Coworker> Coworkers { get; set; }
}
public class Coworker : Entity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<Video> Videos { get; set; }
}
创建数据库时,架构看起来正确: 还有一个视频,同事和VideoCoworkers表,没有
我在N层应用程序中使用存储库模式来访问数据库,我的Insert和Update方法如下所示:
public T Insert(T entity)
{
//Creates database context. When it disposes, it calls context.SaveChanges()
using (var session = new DatabaseSession())
{
session.Context.Set<T>().Add(entity);
}
}
public T Update(T entity)
{
//Creates database context. When it disposes, it calls context.SaveChanges()
using (var session = new DatabaseSession())
{
entity = session.Context.Set<T>().Attach(entity);
session.Context.Entry(entity).State = EntityState.Modified;
}
return entity;
}
当我更新实体时,我从DTO创建实体对象,这就是使用DbSet.Attach而不是选择它并逐个更新属性的原因。
初始化数据库时,我添加了一些测试数据:
当我从代码中列出视频时,我可以看到Video.Coworkers集合中充满了良好的值,当我在SQL Server Management Studio中查询链接表(VideoCoworkers)时,它看起来也很不错。
我的问题是 当我更新例如视频的标题时,它可以工作。但是当我尝试从Video2中删除现有的同事(B和C),并尝试添加同事A时,则关系不会更新。当我只尝试添加新的同事,或者只尝试删除一个时,它也不起作用。我创建了一个实体,它用作Update()方法的参数,方法是创建一个带有新的同事集合的新视频实体(使用Id的Find()方法从数据库中选择)。
更新多对多关系的正确方法是什么?
答案 0 :(得分:6)
但是当我尝试从Video2中删除现有的同事(B和C), 并尝试添加同事A,然后关系不会更新。
不使用通用存储库,正确的过程是:
using (var session = new DatabaseSession())
{
video2 = session.Context.Set<Video>().Include(v => v.Coworkers)
.Single(v => v.Id == video2Id);
coworkerA = new Coworker { Id = coworkerAId };
session.Context.Set<Coworker>().Attach(coworkerA);
video2.Coworkers.Clear();
video2.Coworkers.Add(coworkerA)
session.Context.SaveChanges();
}
关键部分是您必须以实际状态加载或附加实体,更改实体,即删除和添加子项,然后保存更改。 EF的更改检测将为链接表条目创建必要的INSERT和DELETE语句。在通用Modified
方法中将状态设置为Update
的简单过程仅适用于更新标量属性(如更改视频标题),但不适用于更新实体之间的关系。
答案 1 :(得分:2)
解决这个问题:
所以你的更新代码应该是这样的:
public Video Update(Video entity)
{
//Creates database context. When it disposes, it calls context.SaveChanges()
using (var session = new DatabaseSession())
{
entity = session.Context.Set<Video>().Attach(entity);
session.Context.Entry(entity).Collection(p => p.Coworkers).Load();
session.Context.Entry(entity).State = EntityState.Modified;
}
return entity;
}
答案 2 :(得分:-1)
请参阅here,了解如何首先在数据库中保存asp.net mvc中的主要详细信息。希望它能首先为您提供有关代码的想法。您还可以查看knokout.js示例