我目前正在使用EF 6 Code First构建RestAPI,我得到了几个有一些关系的模型。
我设法成功添加了所有项目,但现在我正在建立一个更新"功能,但这些功能并不顺利。
我目前有这个代码,它确实更新了行,但是在有关系的列上它只是添加新行而不是使用现有的...
DatabaseController
public void UpdateDatabase(int id, DatabaseItem db)
{
using (var databasesCtx = new DatabaseContext())
{
DatabaseItem existing = databasesCtx.Databases.Include(a => a.Subjects).Include(a => a.Types).FirstOrDefault(d => d.Id == id);
if(existing != null)
{
List<DatabaseSubject> subjects = GetAllSubjects();
List<DatabaseType> types = GetAllTypes();
db.Subjects = subjects.Where(s => db.Subjects.Select(b => b.Id).ToList().Contains(s.Id)).ToList();
db.Types = types.Where(t => db.Types.Select(b => b.Id).ToList().Contains(t.Id)).ToList();
databasesCtx.Entry(existing).CurrentValues.SetValues(db);
databasesCtx.SaveChanges();
}
}
}
DatabaseItem - Class
public class DatabaseItem
{
public int Id { get; set; }
public virtual ICollection<DatabaseSubject> Subjects { get; set; }
public byte[] Icon { get; set; }
public virtual ICollection<DatabaseType> Types { get; set; }
public string Description { get; set; }
[Required]
public Boolean Public { get; set; }
}
DatabaseSubject - Class
public class DatabaseSubject
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<DatabaseItem> Databases { get; set; }
}
DatabaseType - Class
public class DatabaseType
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<DatabaseItem> Databases { get; set; }
}
答案 0 :(得分:1)
SetValues永远不会更新导航属性。执行代码时,它只知道传递给Update方法的实体的简单/复杂属性的更改。 EF甚至不知道传递给Update方法的实体的相关实体。
您必须手动告知EF有关对象图中的每项更改
引自https://stackoverflow.com/a/11710813/4834103
我在下面留下了原来的答案,因为上面只说明为什么更新无法正常工作,答案可能有助于重做代码
我认为你不应该直接设置
db.Subjects = ...
db.Types =...
这些集合由Entity Framework创建和管理。
您应该删除或添加元素到这些集合,但不会用其他集合覆盖。 由于这些是多对多关系,因此an example关于如何更新实体框架中的多对多关系
基本上你应该记下应删除的内容并通过集合的界面删除这些项目。请注意应插入的所有新项目并插入它们。
还有:
您必须加载集合(热切,明确或懒惰),以便在设置新值和调用save之前对其进行跟踪。否则你不会更换集合,只是添加它。
查看我从中获取引用的similar issue。
由于db.Subjects
或db.Types
是延迟加载的,因此应至少访问一次以进行初始化。提供的代码在覆盖它们之前不会访问它们,因此不会加载/跟踪它们并将更改添加为新行