EF 4.1代码优先。与包含所需对象的其他对象的关系

时间:2011-07-06 13:26:37

标签: entity-framework asp.net-mvc-3 code-first

我整个下午一直在困惑和寻找,但我找不到我需要的东西。请考虑以下代码:

public class Project 
{
    public int ID { get; set; }

    [Required(ErrorMessage="De naam van het project is verplicht")]
    public String Name { get; set; }

    [Required(ErrorMessage = "Het projecttype is verplicht")]
    public virtual ProjectType Type { get; set; }
    public virtual ProjectStatus Status { get; set; }

    [Required(ErrorMessage="De naam van het boek is verplicht")]
    public String BookName { get; set; }
    [Required(ErrorMessage = "Het aantal te vertalen woorden is verplicht")]
    public int NrOfWords { get; set; }
    [Required(ErrorMessage = "De afgesproken prijs per woord is verplicht")]
    public int MoniesPerWord { get; set; }
    public int Progress { get; set; }
    public DateTime StartDate  { get; set; }
    [Required(ErrorMessage = "De deadline van het project is verplicht")]
    public DateTime DueDate { get; set; }
    public ICollection<DateTime> StateChangedDates { get; set; }

    [Required(ErrorMessage = "Een opdrachtgever voor dit project is verplicht")]
    public int ContactPersonID { get; set; }
    [ForeignKey("ContactPersonID")]
    public virtual Person ContactPerson { get; set; }

    public virtual Company Company { get; set; }
}

public class ProjectType
{
    public int ID { get; set; }
    [Required(ErrorMessage="Naam van projecttype is verplicht")]
    public String OptionName { get; set; }
    public String Description { get; set; }
}

public class Person
{
    public int ID { get; set; }

    public String FirstName { get; set; }
    [Required(ErrorMessage = "Achternaam is verplicht")]
    public String LastName { get; set; }
    public String PhotoFileName { get; set; }
    public DateTime? DateOfBirth { get; set; }

    public int PersonTypeID { get; set; }
    [ForeignKey("PersonTypeID")]
    [Required(ErrorMessage = "Type persoon is verplicht")]
    public virtual PersonType Type { get; set; }

    public int BillingAddressID { get; set; }
    [ForeignKey("BillingAddressID")]
    [Required(ErrorMessage = "Factuuradres is verplicht")]
    public virtual Address BillingAddress { get; set; }

    public int PostalAddressID { get; set; }
    [ForeignKey("PostalAddressID")]
    [Required(ErrorMessage = "Postadres is verplicht")]
    public virtual Address PostalAddress { get; set; }

    public virtual Company Employer { get; set; }

    [Required(ErrorMessage = "Tenminste 1 emailadres is verplicht")]
    public String EmailAddress { get; set; }
    public String PhoneNumber { get; set; }
    public String WebSite { get; set; }
    public String Comments { get; set; }

    public bool IsUser { get; set; }
}

视图如下所示:

<div class="editor-container">
    <div class="editor-label">
        Projecttype
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.Project.Type.ID, Model.ProjectTypes, new { @class = "dropDownList" })
        @Html.ValidationMessageFor(model => model.Project.Type.ID, " ")
    </div>
    <div class="clear"></div>
</div>
<div class="editor-container">
    <div class="editor-label">
        Opdrachtgever
    </div>
    <div class="editor-field">
        @Html.DropDownListFor(model => model.Project.ContactPerson.ID, Model.Contacts, new { @class = "dropDownList" })
    @Html.ValidationMessageFor(model => model.Project.ContactPerson.ID, " ")
    </div>
    <div class="clear"></div>
</div>

用于此视图的ViewModel是:

public class ProjectViewModel
{
    public Project Project { get; set; }
    public List<SelectListItem> ProjectTypes { get; set; }
    public List<SelectListItem> ProjectStatusses { get; set; }
    public List<SelectListItem> Contacts { get; set; }

    public ProjectViewModel()
    {

        Project = new Project();
        SetLists();
    }

    public ProjectViewModel(int projectID)
    {
        ProjectRepository projectRepository = new ProjectRepository();

        Project = projectRepository.GetProjectByID(projectID);
        SetLists();
    }

    private void SetLists()
    {
        ProjectTypeRepository projectTypeRepository = new ProjectTypeRepository();
        ProjectStatusRepository projectStatusRepository = new ProjectStatusRepository();
        PersonRepository personRepository = new PersonRepository();

        ProjectTypes = new List<SelectListItem>();
        ProjectStatusses = new List<SelectListItem>();
        Contacts = new List<SelectListItem>();

        foreach (var projectType in projectTypeRepository.GetProjectTypes())
            ProjectTypes.Add(new SelectListItem() { Text = projectType.OptionName, Value = projectType.ID.ToString() });

        foreach (var projectStatus in projectStatusRepository.GetProjectStatusses())
            ProjectStatusses.Add(new SelectListItem() { Text = projectStatus.OptionName, Value = projectStatus.ID.ToString() });

        foreach (var person in personRepository.GetPeopleByIsUser(false))
            Contacts.Add(new SelectListItem() { Text = String.Format("{0} {1}", person.FirstName, person.LastName), Value = person.ID.ToString() });
    }

问题在于:在我看来,我有一个下拉列表,其中包含可用于项目的人员姓名。选择联系人后,将设置ID。然而,ModelState无效,因为person对象因为需要它的属性而抛出多个错误。

有没有办法做到这一点,或者我只需要解决只有人的ID和类型作为参考的项目?

提前完成

1 个答案:

答案 0 :(得分:0)

我发现你的设计存在一些问题

您的视图模型过于复杂

您将数据绑定到3或4级嵌套属性。视图模型用于简化表示逻辑。 您的下拉列表项也包含在模型中。我建议您使用ViewDataViewBag将它们从控制器传递到视图。

将DropDownLists绑定到导航属性

例如:如果将model => model.Project.Type.ID绑定到下拉列表,MVC模型将必须创建ProjectType的新实例来绑定属性。因为EF会将ProjectType视为新实体并尝试添加它。我怀疑您在添加新ProjectType时添加新的Project

我建议你添加一个标量属性TypeID并装饰它Required属性

public class Project 
{
    public int ID { get; set; }

    [Required(ErrorMessage="De naam van het project is verplicht")]
    public String Name { get; set; }

    public virtual ProjectType Type { get; set; }

    [Required(ErrorMessage = "Het projecttype is verplicht")]
    public String TypeID{ get; set; }
}

然后绑定它

@Html.DropDownListFor(model => model.Project.TypeID, Model.ProjectTypes, new { @class = "dropDownList" })