CTP5 EF代码第一个问题

时间:2011-03-06 04:19:17

标签: c# .net asp.net asp.net-mvc entity-framework

您可以找到演示此问题的源代码@ http://code.google.com/p/contactsctp5/

我有三个模型对象。联系,的ContactInfo,ContactInfoType。如果联系人有许多contactinfo,并且每个contactinfo都是contactinfotype。我觉得相当简单。我遇到的问题是当我去编辑联系对象时。我从我的联系人存储库中取出它。然后我运行“UpdateModel(contact);”并使用我的表单中的所有值更新对象。 (使用debug进行监视)当我保存更改时,出现以下错误:

  

操作失败:关系   无法更改,因为一个或   更多的外键属性是   非空的。当进行更改时   关系,相关   foreign-key属性设置为null   值。如果外键没有   支持null值,一个新的   关系必须定义,   必须分配外键属性   另一个非空值,或者   必须删除不相关的对象。

似乎在我调用更新模型之后它将我的引用归零,这似乎打破了一切?任何有关如何补救的想法将不胜感激。感谢。

以下是我的模特:

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 个答案:

答案 0 :(得分:3)

这里有一些事情发生。

1 如果设置为延迟加载,则只有在您指示加载时才加载子对象。这可以通过查询中的以下内容完成。

...

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

有关确保根据需要加载对象的详细信息,请参阅this article

2 如果你不想保存contactinfo和contactinfotype(因为它们没有加载或你只是不想),你需要告诉上下文不要保存子对象不应该更新。这可以使用:

完成

...

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

我发现在将国家/地区对象更改/使用用户数据时,我需要这样做。我绝对不希望用户更新。

在编写所有这些指南的过程中,可能需要几周才能完成blog

3 MVC不会存储/发送您未放入表单的任何内容。如果将对象层次发送到表单并且值未在隐藏输入中表示,则它们将在模型上返回空白。出于这个原因,我通常只生成只能使用ToEntity和ToModel方法的实体版本的视图模型。这也包含了我的安全性,因为我不希望隐藏输入中存在各种用户ID,因此我的实体直接映射到MVC(请参阅this article on overposting)。

我认为你将你的contactinfo属性设置为虚拟的事实,UpdateModel不会介意它们在返回时是否存在,但我可能错了,因为我没有尝试过。< / p>

答案 1 :(得分:1)

感谢Morteza Manavi在实体框架网站上提出这个问题。我的问题是由我的ContactInformation模型属性'contactid'和&amp; 'contacttypeid'不可为空。一旦我修复了这一切,UpdateModel()工作正常。非常感谢你!