实体框架6代码优先更新行与关系

时间:2016-06-28 18:59:06

标签: c# entity-framework entity-framework-6 asp.net-web-api2

我目前正在使用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; }
}

1 个答案:

答案 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.Subjectsdb.Types是延迟加载的,因此应至少访问一次以进行初始化。提供的代码在覆盖它们之前不会访问它们,因此不会加载/跟踪它们并将更改添加为新行