2015-09-22 6 views
0

Я использую Entity Framework с веб-интерфейсом API 2. У меня есть объект лодки с такими свойствами, как имя, цена и т. Д. Эти простые свойства обновляются отлично при отправке с помощью Put to web api controller , Судно судна также имеет много отношений с сущностью под названием BoatType. Типы лодок - «Яхта», «Моторная яхта» и т. Д.Entity Framework не обновляет внешний ключ при обновлении сущностей

Когда объект лодки обновляется в контроллере, внешний ключ для типа лодки в базе данных не обновляется. Должен ли я как-то вручную обновлять значение дочернего объекта или есть способ получить EF для этого автоматически?

Вот запрос пример PUT отправлен веб-API:

{ 
    "$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 
} 

Вот функция обновления в веб-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 Key, Entity Framework does not update Foreign Key object и Update foreign key using Entity Framework но ни один из них не имеет такого же сценария (или ответы не помогли мне понять мою проблему).

Вот классы моделей Boat and 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; } 
} 
+0

«... обновляется в контроллере, внешний ключ для типа лодки в базе данных не обновляется». Ну, вы передаете действительный идентификатор типа лодки в объекте лодки? Не относится к вашему вопросу: почему вы передаете идентификатор в дополнение к объекту лодки, который содержит идентификатор? Кажется странным. – Sam

+0

Определяете ли вы FK на своих моделях, т. Е. Лодка содержит свойство BoatTypeID, а также свойство BoatType? – Sam

+0

Да, идентификатор BoatType 1 в приведенном выше PUT действителен. – Danzig

ответ

1

Хорошо, я понял, в чем проблема. Используя SQL Server Profiler для просмотра инструкции SQL Update, я увидел, что внешний ключ для Boat.BoatType не был даже там, поэтому я решил, что моя модель должна быть где-то прикручена. Когда я создал модель в дизайнере, я ошибочно установил отношения между Boat и BoatType как один к одному. Позже я осознал ошибку и изменил связь с одним (BoatType) ко многим (Лодки), но это, должно быть, ПОСЛЕ того, как я сгенерировал базу данных. D'о! Что-то о том, как EF обрабатывает ассоциации, означало, что простого изменения типа ассоциации на диаграмме было недостаточно - я должен был удалить/воссоздать ограничение базы данных в это время.

Поскольку у меня были только тестовые данные в базе данных, то работала для меня, чтобы воссоздать базу данных, используя опцию «Создать базу данных из модели ...» в дизайнере.

После того, как я правильно выполнил PUT, я должен был решить другую проблему (которая на самом деле не является предметом этого вопроса, но обсуждалась выше, поэтому на случай, если это кому-то полезно) было то, что веб-API дал ошибку " Нарушение ограничения ссылочной целостности произошло: значения (-ы) свойства «Boat.BoatTypeId» на одном конце отношения не соответствуют значениям свойств «Boat.BoatType.Id» на другом конце. ». Список выбора, который позволяет пользователю изменять тип лодки, привязан к клиенту, используя AngularJS для Boat.BoatType. Таким образом, в данных PUT, Boat.BoatType был обновлен до новых значений, но Boat.BoatTypeId не изменился - следовательно, ошибка ссылочной целостности. Поэтому я просто вручную задал значение Boat.BoatTypeId для Boat.BoatType.Id перед отправкой PUT, и все работает как ожидается.

 Смежные вопросы

  • Нет связанных вопросов^_^