C# 使用子对象更新实体是否需要初始查询
我有一个相册实体:C# 使用子对象更新实体是否需要初始查询,c#,.net,entity-framework,entity-framework-6,C#,.net,Entity Framework,Entity Framework 6,我有一个相册实体: public class Album { public Album() { } [Key] [Column("AlbumId")] public int Id { get; set; } public string Title { get; set; } public int ReleaseYear { get; set; } public int Rating { get; set; }
public class Album
{
public Album() { }
[Key]
[Column("AlbumId")]
public int Id { get; set; }
public string Title { get; set; }
public int ReleaseYear { get; set; }
public int Rating { get; set; }
public int ComposerId { get; set; }
[ForeignKey("ComposerId")]
public Composer Composer { get; set; }
}
其中包含作为子对象的Composer:
public class Composer
{
[Key]
[Column("ComposerId")]
public int Id { get; set; }
public string Name { get; set; }
}
在我的相册更新方法中,我有以下正确工作的代码:
public void UpdateAlbum(Album album)
{
using (var context = new MusicCatelogContext())
{
try
{
Album albumEntity = context.Albums
.Where(a => a.Id.Equals(album.Id))
.Include(a => a.Composer)
.First();
Composer composerEntity = context.Composers
.Where(c => c.Id.Equals(album.Composer.Id))
.First();
context.Entry(albumEntity).CurrentValues.SetValues(album);
albumEntity.Composer = composerEntity;
context.SaveChanges();
}
上述代码虽然有效,但需要对数据库进行两次查询。我希望能够按照以下方式连接更新的相册实体:
public void UpdateAlbum(Album album)
{
using (var context = new MusicCatelogContext())
{
try
{
context.Entry(album).State = EntityState.Modified;
context.SaveChanges();
}
但是,当我尝试此代码时,当我尝试设置状态时会引发以下异常:
发生引用完整性约束冲突:关系一端的'Composer.Id'属性值与另一端的'Album.ComposerId'属性值不匹配。
我做了很多研究,但我仍然不确定为什么会这样。我应该注意到,在album
参数中传递给UpdateAlbum
的整个Composer对象是新的更新版本
因此,我的问题是:
谢谢。据我所知,这是EF的标准行为。我也相信这是正确的行为。当您点击DB时,可能发生了很多事情,另一个进程/用户删除了该对象或更改了该对象。您是开发人员,希望了解这一点。你也应该问问自己为什么要担心这个。只有当您进行大规模批量更新时,您才会受到性能损失,但此处不会。该错误也是标准错误,因为EF希望插入新对象,因此它不在其上下文中。上下文。条目(相册)。状态=EntityState.Modified;做两件事:将对象相册附加到上下文,并告诉EF此对象将按原样保存到数据库。但是,composer Id与与album相关的对象图中的composer Id不匹配(您刚刚将其设置为其他值)。将FK设置为“保存前一个”,不要公开FK属性(让EF处理它),或者像在第二个示例中那样将正确的编写器条目附加到上下文中。@Aldert EF不会插入新对象,因为.entry方法适用于ChangeTracker(没有导航属性,因此不考虑引用的条目)…另一方面,Set.Add Previous确实会尝试插入相关条目,并可能引发不同的错误。@Devil,据我所知,这只是上下文对象范围内的情况。通常您实例化上下文,运行业务逻辑并处理上下文。您是对的,在这个上下文中,我们需要一个ChangeTracker在上面的示例中,刚刚创建了上下文,因此changetracker为空。