繁体   English   中英

实体更新时,实体框架不会更新外键

[英]Entity Framework not updating foreign key when entity updates

我正在将Entity Framework与Web API 2一起使用。我有一个Boat实体,其属性如名称,价格等。当由Put发送到Web api控制器时,这些简单的属性可以很好地更新。 船实体还与称为BoatType的实体具有多对一关系。 船只类型为“游艇”,“机动游艇”等。

在控制器中更新船实体时,数据库中船类型的外键不会更新。 我是否必须以某种方式手动更新子实体值,或者是否有办法让EF自动执行此操作?

这是发送到Web API的示例PUT请求:

{
  "$id":"1",
  "Images":[],
  "BoatType": {
    "$id":"3",
    "Boat":[],
    "Id":1,
    "DateCreated":"2015-09-15T13:14:39.077",
    "Name":"Yacht"
  },
  "Id":2,
  "Name":"Schooner",
  "Description":"A harmless schooner",
  "DateCreated":"2015-09-15T17:59:37.8",
  "Price":65000
}

这是Web API中的更新功能:

[ResponseType(typeof(void))]
public async Task<IHttpActionResult> Put(int id, Boat boat)
{
    if (id != boat.Id)
    {
        return BadRequest();
    }

    _db.Entry(boat).State = EntityState.Modified;

    try
    {
        await _db.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!BoatExists(id))
        {
            return NotFound();
        }
        else
        {
            throw;
        }
    }
    return StatusCode(HttpStatusCode.NoContent);
}

我看过类似的问题,例如实体框架代码“第一次更新不更新外键” ,“ 实体框架不更新外键对象”“使用实体框架更新外键”,但是似乎没有一个完全相同的场景(或者答案没有帮助我了解我的问题)。

这是Boat和BoatType模型类(由EF设计器自动生成)。

public partial class Boat
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Boat()
    {
        this.Images = new HashSet<Image>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public System.DateTime DateCreated { get; set; }
    public Nullable<double> Price { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Image> Images { get; set; }
    public virtual BoatType BoatType { get; set; }
} 

public partial class BoatType
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public BoatType()
    {
        this.Boat = new HashSet<Boat>();
    }

    public int Id { get; set; }
    public System.DateTime DateCreated { get; set; }
    public string Name { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Boat> Boat { get; set; }
}

好的,我找出了问题所在。 使用SQL Server Profiler查看SQL Update语句,我发现Boat.BoatType的外键甚至不在其中-因此,我认为我的模型必须在某个地方搞砸了。 在设计器中创建模型时,我错误地将Boat和BoatType之间的关系设置为一对一。 后来我意识到了这个错误,并将关联从一个(BoatType)更改为许多(Boats),但这一定是在生成数据库之后进行的。 天哪! 关于EF处理关联的方式,这意味着仅更改图中的关联类型是不够的-那时我应该删除/重新创建数据库约束。

由于我只有数据库中的测试数据,因此对我有用的是使用设计器中的“从模型生成数据库...”选项重新创建数据库。

一旦我让PUT正常工作,我就不得不解决另一件事(这个问题并不是真正的话题,但是上面已经讨论过,以防万一它对某人有用)是Web API给出了错误“参照完整性约束发生冲突:关系的一端“ Boat.BoatTypeId”的属性值与另一端“ Boat.BoatType.Id”的属性值不匹配。” 使用AngularJS在客户端上将允许用户更改船型的选择列表绑定到Boat.BoatType。 因此,在PUT数据中,Boat.BoatType已更新为新值,但Boat.BoatTypeId并未更改-因此出现“参照完整性”错误。 因此,我只是在发送PUT之前手动将Boat.BoatTypeId的值设置为Boat.BoatType.Id,并且所有工作现在都按预期进行。

暂无
暂无

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

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