实体框架6代码第一次更新行与关系
本文关键字:关系 更新 第一次 框架 代码 实体 | 更新日期: 2023-09-27 17:52:41
我目前正在使用EF 6代码构建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; }
}
databasessubject - 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; }
}
SetValues从不更新导航属性。当您执行代码时,它只知道传递给Update方法的实体的简单/复杂属性的变化。EF甚至不知道传递给Update方法的实体的相关实体。
你必须手动告诉EF你的对象图中的每一个变化
引自https://stackoverflow.com/a/11710813/4834103
我把原来的答案留在下面,因为上面只告诉了为什么更新不能正常工作,答案可能有助于重做你的代码
原始答:
我认为你不应该直接设置
db.Subjects = ...
db.Types =...
这些集合由实体框架创建和管理。
应该删除或添加元素到这些集合中,但不能用另一个集合覆盖元素。由于这些是多对多关系,这里有一个关于如何在实体框架
中更新多对多关系的示例基本上,您应该注意应该删除什么,并通过集合的接口删除这些项。注意任何应该插入的新项并插入它们。
还:
您必须加载集合(急切地、显式地或惰性地),以便在设置新值和调用save之前可以跟踪它。否则,您将不会替换集合,而只是添加它。
查看我引用的这个类似的问题。
由于db.Subjects
或db.Types
是惰性加载的,它们应该至少被访问一次才能初始化。所提供的代码在覆盖它们之前不会访问它们,因此它们不会被加载/跟踪,并且更改将作为新行添加