0

我想我已经阅读了有关此问题的所有文章和堆栈溢出问题,但无法找到解决方案。让我从我的模型开始

public class Entry
{
    public Entry ()
    {
        DateEntered = DateTime.Now;
    }

    public int Id { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [Required]
    public string Email { get; set; }
    public string Number { get; set; }
    public string FbId { get; set; }
    [ReadOnly(true)]
    public DateTime DateEntered { get; set; }
    public string AccessToken { get; set; }

    //Relationsips
    public Backgrounds Background { get; set; }
    public Cars Car { get; set; }
}

public class Backgrounds
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Filename { get; set; }
}

public class Cars
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string FileName { get; set; }
}

现在在我的控制器中,我正在更新条目。如下

    // PUT /api/entries/5
    public HttpResponseMessage Put(Entry entry)
    {
        if(ModelState.IsValid)
        {

            _db.Entries.Attach(entry);
            _db.Entry(entry).State = EntityState.Modified;
            _db.SaveChanges();

            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }

        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

我的 Entry 模型得到正确更新,但如果 entry.Background.Name 发生更改,则不会将其保存到数据库中。我的控制器正在接受整个入口模型,包括它的关系 => 背景和汽车。但是,更改为关系的任何值都不会更新或反映。无需查询数据库然后更新的任何优雅的解决方案?我不想在更新之前进行任何额外的查询或查找。

谢谢

泰隆

4

1 回答 1

0

您必须手动告知 EF 对对象图所做的所有更改。您只告诉 EF 对条目实例的更改,但您没有告诉它对相关实体或关系本身的任何更改。没有优雅的方法可以解决这个问题。您通常有两种选择:

  • 您将使用一些 DTO 代替您的实体,并且这些 DTO 将具有一些标志,例如IsDirty- 当您将对象图接收回控制器时,您将从 DTO 重建实体并基于IsDirty. 此解决方案需要进一步扩展,例如,如果您的客户也可以删除关系。
  • 您将从数据库中查询对象图,并将传入的更改合并到从数据库中检索到的实体。

有一些部分解决方案,例如通过将所有相关对象的状态设置为已修改和标识新对象来强制保存对所有相关对象的更改,Id == 0但同样这些解决方案仅适用于特定场景。

关于这个问题的更复杂的讨论。

于 2012-05-16T09:08:40.463 回答