CTP5 EF Code Первый вопрос - PullRequest
6 голосов
/ 06 марта 2011

Вы можете найти исходный код, демонстрирующий эту проблему @ http://code.google.com/p/contactsctp5/

У меня есть три объекта модели.Контакт, ContactInfo, ContactInfoType.Если у контакта много контактных данных, и каждая контактная информация является контактным инфотипом.Довольно простой, я думаю.Проблема, с которой я сталкиваюсь, заключается в том, что когда я иду редактировать контактный объект.Я вытащил его из своего хранилища контактов.Затем я запускаю «UpdateModel (контакт);»и он обновляет объект со всеми значениями из моей формы.(мониторинг с отладкой) Однако, когда я сохраняю изменения, я получаю следующую ошибку:

Операция не выполнена: отношение не может быть изменено, поскольку одно или несколько свойств внешнего ключа не являютсяобнуляемый.Когда в отношение вносится изменение, для соответствующего свойства внешнего ключа устанавливается нулевое значение.Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, свойству внешнего ключа должно быть присвоено другое ненулевое значение или несвязанный объект должен быть удален.

ItКажется, после того, как я вызываю update model, он обнуляет мои ссылки, и это, кажется, ломает всеЛюбые мысли о том, как исправить, будет принята с благодарностью.Спасибо.

Вот мои модели:

public partial class Contact {
    public Contact() {
      this.ContactInformation = new HashSet<ContactInformation>();
    }

    public int ContactId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public virtual ICollection<ContactInformation> ContactInformation { get; set; }
 }

 public partial class ContactInformation {
    public int ContactInformationId { get; set; }
    public int ContactId { get; set; }
    public int ContactInfoTypeId { get; set; }
    public string Information { get; set; }

    public virtual Contact Contact { get; set; }
    public virtual ContactInfoType ContactInfoType { get; set; }
  }

  public partial class ContactInfoType {
    public ContactInfoType() {
      this.ContactInformation = new HashSet<ContactInformation>();
    }

    public int ContactInfoTypeId { get; set; }
    public string Type { get; set; }

    public virtual ICollection<ContactInformation> ContactInformation { get; set; }
  }

Действие моего контроллера:

[AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Contact person) {
      if (this.ModelState.IsValid) {
        var contact = this.contactRepository.GetById(person.ContactId);
        UpdateModel(contact);
        this.contactRepository.Save();
        TempData["message"] = "Contact Saved.";
        return PartialView("Details", contact);
      } else {
        return PartialView(person);
      }
    }

Код контекста:

protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder) {
      modelBuilder.Entity<Contact>()
        .HasMany(c => c.ContactInformation)
        .WithRequired()
        .HasForeignKey(c => c.ContactId);

      modelBuilder.Entity<ContactInfoType>()
        .HasMany(c => c.ContactInformation)
        .WithRequired()
        .HasForeignKey(c => c.ContactInfoTypeId);
    }

Ответы [ 2 ]

3 голосов
/ 06 марта 2011

Здесь происходит несколько вещей.

1 Если вы настроены на отложенную загрузку, дочерние объекты загружаются, только если вы указываете их на загрузку. Это можно сделать с помощью следующего в вашем запросе.

..

context.Contacts.Include(c => c.ContactInfos).Include(c => c.ContactInfos.ContactInfoType)

см. в этой статье для получения полной информации о том, что объекты загружаются так, как вы хотите.

2 Если вы не хотите сохранять contactinfo и contactinfotype (потому что они не загружены или вы просто не хотите), вам нужно будет указать контексту не сохранять дочерние объекты, которые не должен обновляться Это можно сделать с помощью:

..

context.StateManager.ChangeObjectState(entity.ContactInfos.ContactInfoType, EntityState.Unchanged);

Я считаю, что мне нужно это сделать при изменении / использовании объекта страны для пользовательских данных. Я определенно никогда не хочу, чтобы это обновлялось пользователем.

В середине написания небольшого руководства ко всему этому, но могут пройти недели, пока это не будет сделано в моем блоге

3 MVC не будет хранить / отправлять обратно то, что вы не указали в форме. Если вы отправите объектную иерархию в форму, а значения не будут представлены в скрытых входах, они вернутся пустыми в вашей модели. По этой причине я обычно делаю модели представления, которые являются редактируемыми только версиями сущностей с ToEntity и методом ToModel на них. Это также покрывает меня в целях безопасности, так как я не хочу, чтобы все виды пользовательских идентификаторов были скрытыми, просто так мои сущности отображаются прямо в MVC (см. эту статью о превышении ).

Я бы подумал, что тот факт, что ваши свойства contactinfo установлены на виртуальные, UpdateModel не будет возражать, если бы они не существовали при возврате, но я вполне могу ошибаться, поскольку не пробовал.

1 голос
/ 14 марта 2011

Я разобрался с этим вопросом благодаря Мортезе Манави на веб-сайте Entity Framework.Моя проблема была вызвана моими свойствами модели ContactInformation, так как 'contactid' & 'contacttypeid' не обнулялись.Как только я это исправил, все с помощью UpdateModel () работало правильно.Большое спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...