我为此使用了 Entity Framework Core 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; }
}
在我的数据库上下文中,我已将它们定义为这样
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<FavouriteColour>()
.HasKey(c => new { c.PersonId, c.ColourId });
modelBuilder.Entity<FavouriteColour>()
.HasOne(fc => fc.Person)
.WithMany(p => p.FavouriteColours)
.HasForeignKey(p => p.PersonId);
modelBuilder.Entity<FavouriteColour>()
.HasOne(fc => fc.Colour)
.WithMany(c => c.FavouriteColours)
.HasForeignKey(c => c.ColourId);
}
现在在应用程序中,用户可以添加或删除喜欢的颜色,以便在调用存储库更新的控制器中接收新的用户对象
public async Task<IActionResult> PutPerson(int id, Person person)
{
peopleRepository.Update(person);
}
然后存储库进行更新
public void Update(Person person)
{
_context.Update(person);
}
执行 await _context.SaveChangesAsync();
后,颜色没有任何变化。我认为所有这些模型的目的都是为了颜色会自动改变?
我设置了一个 FavouriteColourRepository
来进行这样的更新
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);
实际上更改了 favouriteColours 参数并将最后一个状态强制到其中创建重复的主键并且插入失败。
那么为什么新的最喜欢的颜色永远不会被插入,为什么当我试图清除用户已有的所有颜色时我的 favouriteColours
参数被编辑?
答案 0 :(得分:1)
为什么永远不会插入新的最喜欢的颜色
调用 _context.Update(person);
将 Person
实体和所有相关的 FavouriteColour
实体置于 Modified
状态。因此,在下一次 SaveChanges
调用中,EF 应该向数据库提交更新命令。
如果您修改 Person
实体的任何属性,您会发现此人已正确更新。 FavouriteColour
实体的问题在于它只包含主键属性,并且 EF 不修改键属性(或作为复合主键一部分的任何属性)。您可以使用以下代码进行测试 -
var fc = dbCtx.FavouriteColours
.FirstOrDefault(p => p.PersonId == 1 && p.ColourId == 4);
fc.ColourId = 6; // CoulourId is part of primary key
dbCtx.SaveChanges();
你会遇到一个例外 -
<块引用>属性 'FavouriteColour.ColourId' 是键的一部分,因此不能 被修改或标记为已修改。 ...
因此,EF 甚至不会为 FavouriteColours
生成任何更新命令,即使它们都被标记为 Modified
。
要更新 Person
及其所有 FavouriteColour
,您需要执行类似 -
// fetch the exising person with all its FavouriteColours
var existingPerson = dbCtx.Persons
.Include(p => p.FavouriteColours)
.FirstOrDefault(p => p.Id == id);
// modify any properties of Person if you need
// replace the existing FavouriteColours list
existingPerson.FavouriteColours = person.FavouriteColours;
// save the changes
dbCtx.SaveChanges();
这将 -
FavouriteColour
FavouriteColour
。在您的存储库就位后,您如何实现这一点取决于您。
<块引用>为什么我的 favouriteColours 参数在我尝试时被编辑 清除用户已有的所有颜色
在此操作之前,您调用了 _context.Update(person);
。因此,Person
现在作为现有实体在 Modified
状态下被跟踪。然后当你打电话 -
_context.FavouriteColours.RemoveRange(_context.FavouriteColours.Where(fc => fc.PersonId == personId));
_context.FavouriteColours.Where(fc => fc.PersonId == personId)
部分,从数据库中获取该 FavouriteColours
的现有 Person
。因此,这些提取的 FavouriteColours
会添加到此人的 FavouriteColours
列表中(因为它正在被跟踪)。
例如,假设在您的控制器中,您收到了一个 Person
实体,其中包含 4 个 FavouriteColour
,而数据库中有 3 个 FavouriteColour
用于此人。调用 _context.Update(person);
后,将使用 4 FavouriteColour
的列表跟踪此人。然后,当您从数据库中获取此人现有的 FavouriteColours
时,正在跟踪此人,其中包含总共 7 个 FavouriteColour
的列表。
我希望能遮蔽任何光线。