简体   繁体   English

具有关系的实体框架6代码优先更新行

[英]Entity Framework 6 Code First Update Row with Relations

I'm currently building a RestAPI using EF 6 Code First, I got a couple of models which have some relations. 我目前正在使用EF 6 Code构建RestAPI,首先,我得到了几个有一定关系的模型。

I've managed to successfully add items and all that, but now I'm building a "Update"-function, which aren't going well. 我已经成功地添加了项目以及所有这些内容,但是现在我正在构建一个“更新”功能,但是运行得并不顺利。

I currently got this code, and it does infact update the row, but on the columns with relations it simply adds new rows instead of using the existing... 我目前有这段代码,它确实会更新行,但是在具有关系的列上,它只是添加新行,而不是使用现有行...

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 DatabaseItem-类

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 DatabaseSubject-类

public class DatabaseSubject
{
    public int Id { get; set; }

    public string Name { get; set; }

    public ICollection<DatabaseItem> Databases { get; set; }
}

DatabaseType - Class DatabaseType-类

public class DatabaseType
{
    public int Id { get; set; }

    public string Name { get; set; }

    public ICollection<DatabaseItem> Databases { get; set; }
}

Edit: 编辑:

SetValues never updates navigation properties. SetValues从不更新导航属性。 When you execute your code it only knows about changes in simple / complex properties of the entity passed to your Update method. 在执行代码时,它仅知道传递给Update方法的实体的简单/复杂属性中的更改。 EF even don't know about related entities of the entity passed to your Update method. EF甚至都不知道传递给您的Update方法的实体的相关实体。

You must manually tell EF about each change in your object graph 您必须手动将对象图中的每个更改告知EF

Quoted from https://stackoverflow.com/a/11710813/4834103 引用自https://stackoverflow.com/a/11710813/4834103

I left the original answer below as the above only tells why the update didn't work correctly and the answer might be helpful to rework your code 我在下面留下了原始答案,因为上述内容仅说明了更新为何无法正常进行,并且该答案可能有助于重新编写代码

Original answer: 原始答案:

I think you aren't supposed to set directly 我认为您不应该直接设置

   db.Subjects = ...
   db.Types =...

Those collections are created and managed by Entity Framework. 这些集合由实体框架创建和管理。

You should remove or add elements to those collections but not overwrite them with another collection. 您应该删除元素或元素添加到这些集合中,但不要用其他集合覆盖它们。 Since those are many-to-many relations here is an example about how to update many-to-many relations in entity framework 由于这些关系是多对多的,因此这里是一个有关如何在实体框架中更新多对多关系的示例

Basically you should note what should be deleted and remove those items through the collection's interface. 基本上,您应该注意应删除的内容,并通过集合的界面删除这些项目。 Note any new items that should be inserted and insert them. 注意应插入的所有新项目,然后将其插入。

Also this: 还有这个:

You have to load the collection (eagerly, explicitly or lazily) so that it can be tracked before setting the new values and calling save. 您必须(急切地,显式地或延迟地)加载集合,以便可以在设置新值和调用save之前对其进行跟踪。 Otherwise you will not be replacing the collection but, just be adding to it. 否则,您不会替换集合,而只是添加到集合中。

Check out this similar issue where I took the quote from. 看看我从中获取报价的类似问题

Since db.Subjects or db.Types are lazy loaded they should be accessed at least once to be initialized. 由于db.Subjectsdb.Types是延迟加载的,因此应至少对其进行一次访问以进行初始化。 The provided code doesn't access them before overwriting them so they are not loaded / tracked and changeds are added as new rows 提供的代码在覆盖它们之前不会访问它们,因此不会加载/跟踪它们并将更改添加为新行

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM