实体框架在实体更新时不更新外键

时间:2015-09-22 22:24:29

标签: c# entity-framework asp.net-web-api2

我正在使用带有Web API的实体框架2.我有一个具有名称,价格等属性的船实体。这些简单属性在由Put发送到web api控制器时更新。船实体还与名为BoatType的实体有多对一的关系。船型是" Yacht"," Motor Yacht"等

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

以下是发送到网址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);
}

我查看了Entity Framework Code First Update Does Not Update Foreign KeyEntity Framework does not update Foreign Key objectUpdate foreign key using Entity Framework等类似问题,但似乎没有相同的情况(或者答案对我没有帮助)了解我的问题。)

这里是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; }
}

1 个答案:

答案 0 :(得分:1)

好的,我弄清楚问题是什么。使用SQL Server Profiler来查看SQL Update语句,我发现Boat.BoatType的外键甚至不在那里 - 所以我认为我的模型必须搞砸到某个地方。当我在设计师中创建模型时,我错误地将Boat和BoatType之间的关系设置为一对一。我后来意识到这个错误,并将关联更改为一个(BoatType)到多个(Boats),但这一定是在我生成数据库之后。 d&#39;哦!关于EF处理关联的方式意味着简单地更改图中的关联类型还不够 - 我当时应该删除/重新创建数据库约束。

由于我在数据库中只有测试数据,对我来说有用的是使用&#34;从模型中生成数据库来重新创建数据库...&#34;设计师中的选项。

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