Entity framework core 实体框架核心导航未更新

Entity framework core 实体框架核心导航未更新,entity-framework-core,Entity Framework Core,为此,我使用EntityFramework核心v5.0.3 我正在为用户制作一个简单的信息应用程序,每个用户都可以拥有自己喜欢的颜色 人物模型 public class Person { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int PersonId { get; set; } [MaxLength(50)] public string FirstName {

为此,我使用EntityFramework核心v5.0.3

我正在为用户制作一个简单的信息应用程序,每个用户都可以拥有自己喜欢的颜色

人物模型

public class Person 
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int PersonId { get; set; }
    [MaxLength(50)]
    public string FirstName { get; set; }
    [MaxLength(50)]
    public string LastName { get; set; }
    public bool IsAuthorised { get; set; }
    public bool IsValid { get; set; }
    public bool IsEnabled { get; set; }
    public virtual ICollection<FavouriteColour> FavouriteColours { get; set; }
}
彩色模型

public class FavouriteColour
{
    [Key]
    public int PersonId { get; set; }
    public virtual Person Person { get; set; }
    [Key]
    public int ColourId { get; set; }
    public virtual Colour Colour { get; set; }
}
public class Colour
{
    [Key]
    public int ColourId { get; set; }
    public string Name { get; set; }
    public bool IsEnabled { get; set; }
    public virtual IList<FavouriteColour> FavouriteColours { get; set; }
}
执行
wait后_context.SaveChangesAsync()所有颜色都不会改变。我以为所有这些型号的目的都是为了让颜色自动改变

我设置了一个
FavoriteColowerRepository
,而不是像这样进行更新

public async Task<bool> Update(int personId, ICollection<FavouriteColour> favouriteColours) 
{
    // empty their favourite colours
    _context.FavouriteColours.RemoveRange(_context.FavouriteColours.Where(fc => fc.PersonId == personId);

    // add new favourite colours
    _context.FavouriteColours.AddRange(favouriteColours);

    return true;
}
实际上更改了FavoriteColors参数,并强制进入最后一个状态,从而创建重复的主键,插入失败

那么,为什么新的最喜欢的颜色从未被插入,为什么在我试图清除用户已经拥有的所有颜色时,我的
favoriteColors
参数被编辑

为什么最受欢迎的新颜色从未被插入

调用
\u context.Update(person)
个人
实体和所有相关的
收藏夹颜色
实体置于
修改
状态。因此,在下一个
SaveChanges
调用中,EF应该向数据库提交更新命令

如果修改
个人
实体的任何属性,您将发现该个人已正确更新。
favoriteColour
实体的问题在于它只包含主键属性,而EF不修改键属性(或作为复合主键一部分的任何属性)。您可以使用以下代码对此进行测试-

var fc=dbCtx.favoriteColor
.FirstOrDefault(p=>p.PersonId==1和&p.colorID==4);
fc.colorId=6;//CoulourId是主键的一部分
dbCtx.SaveChanges();
你会遇到一个例外-

属性“FavoriteColour.colorId”是键的一部分,因此不能 被修改或标记为已修改

因此,EF甚至不会为
收藏夹颜色
生成任何更新命令,即使所有颜色都标记为
已修改

要更新
人物
及其所有
收藏夹颜色
,您需要执行以下操作-

//获取现有人员及其所有喜爱的颜色
var existingPerson=dbCtx.Persons
.包括(p=>p.FavoriteColor)
.FirstOrDefault(p=>p.Id==Id);
//如果需要,请修改Person的任何属性
//替换现有的收藏夹颜色列表
existingPerson.FavoriteColors=person.FavoriteColors;
//保存更改
dbCtx.SaveChanges();
这将-

  • 删除现有列表中但不在新列表中的任何
    FavoriteColour
  • 插入新列表中但不在现有列表中的任何
    FavoriteColour
  • 有了存储库,如何实现这一点就取决于您了

    为什么在尝试编辑时会编辑我的FavoriteColors参数 清除用户已有的所有颜色

    在此操作之前,您调用了
    \u context.Update(person)。因此,
    Person
    现在作为现有实体在
    Modified
    状态下被跟踪。那么当你打电话的时候-

    \u context.favoriteColors.RemoveRange(\u context.favoriteColors.Where(fc=>fc.PersonId==PersonId));
    
    \u context.favoriteColors.Where(fc=>fc.PersonId==PersonId)
    部分从数据库中获取该
    人物的现有
    FavoriteColors
    。因此,这些获取的
    favoriteColors
    被添加到此人的
    favoriteColors
    列表中(因为它正在被跟踪)

    例如,假设您在控制器中收到一个带有4个FavoriteColour的
    Person
    实体,数据库中有3个
    FavoriteColour
    。调用
    \u context.Update(person)后,将使用4个
    收藏夹颜色的列表跟踪此人。然后,当您从数据库中获取此人现有的
    FavoriteColors
    时,将使用总共7个
    FavoriteColour
    的列表跟踪此人

    我希望这能遮住任何光线

    public async Task<IActionResult> PutPerson(int id, Person person) 
    {
        peopleRepository.Update(person);
    }
    
    public void Update(Person person) 
    {
        _context.Update(person);
    }
    
    public async Task<bool> Update(int personId, ICollection<FavouriteColour> favouriteColours) 
    {
        // empty their favourite colours
        _context.FavouriteColours.RemoveRange(_context.FavouriteColours.Where(fc => fc.PersonId == personId);
    
        // add new favourite colours
        _context.FavouriteColours.AddRange(favouriteColours);
    
        return true;
    }
    
    public async Task<IActionResult> PutPerson(int id, Person person)
    {
        peopleRepository.Update(person);
        bool valid = await favouriteColourRepository.Update(id, person.FavouriteColours);
    }
    
    _context.FavouriteColours.RemoveRange(_context.FavouriteColours.Where(fc => fc.PersonId == personId);