Entity Framework模型类具有条件一对一的关系

时间:2014-08-10 14:46:13

标签: c# asp.net-mvc entity-framework-6 foreign-key-relationship

我需要一些帮助。基于我对项目的想法,我在创建模型时遇到了重大问题。为简化起见,我有一个Parent表,一个Student表和一个Address表。因此,每个父记录,可以有多个学生,只有一个地址。每个学生记录,可以有多个父母,只有一个地址。从逻辑上讲,我真的不能认为学生的地址与父母的地址相同,因为可能有一个学生的父母住在不同的地方。所以,我希望能够为学生提供一个地址以及每个家长的地址。所以,我基本上设想这个数据库布局下到一个地址表,包括AddressID,street,city,state,zip ..然后是一个学生表,带有StudentID,name,addressID。然后是具有ParentID,name,addressID的Parent表。然后是Parent_Student引用表,带有StudentID和ParentID。

那么,关于如何实现这一点的任何想法?我只用地址信息和ID创建了我的地址模型。我使用ID,名称,虚拟地址和虚拟ICollection Parent创建了我的学生模型。然后使用ID,名称,虚拟地址和虚拟ICollection创建我的父模型。当我尝试通过New-> Scaffolded Item创建我的学生控制器时,我收到一个关于VS的错误,无法确定父类和地址类型之间关联的主要结束。

我认为这与地址记录对父母或学生都有外键的事实有关,但不是两者都有。我对这整个代码优先的方法很陌生,所以任何洞察都会非常感激。提前谢谢!


编辑:添加更新的代码

PERSON模特:

public enum PersonType
{
    Student, Parent, Teacher
}

public abstract class Person
{

    [Key]
    public int PersonId { get; set; }

    [Required]
    [StringLength(50,ErrorMessage = "First Name cannot be longer than 50 characters.")]
    [Display(Name= "First Name")]
    public string FirstName { get; set; }

    [StringLength(50, ErrorMessage = "Middle Name cannot be longer than 50 characters.")]
    [Display(Name = "Middle Name")]
    public string MiddleName { get; set; }

    [Required]
    [StringLength(50, ErrorMessage = "Last Name cannot be longer than 50 characters.")]
    [Display(Name = "Last Name")]
    public string LastName { get; set; }
    public PersonType personType {get; set;}

    public Address Address { get; set; }

    [Display(Name = "Full Name")]
    public string FullName
    { 
        get
        {
            return FirstName + " " + LastName;
        }
    }

    [Display(Name = "Full Name w Middle")]
    public string FullNameWMid
    { 
        get
        { 
            return FirstName + " " + MiddleName + " " + LastName;
        }
    }
}

学生模特:

public class Student : Person
{
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:mm-dd-yyyy}", ApplyFormatInEditMode = true)]
    [Display(Name = "Birthday")]
    public DateTime Birthday { get; set; }
    public ICollection<int> ParentList { get; set; }

    public virtual ICollection<Parent> Parents { get; set; }
    public virtual Teacher Teacher { get; set; }


}

父模型:

public class Parent : Person
{       
    public string EmailAddress { get; set; }
    public ICollection<int> StudentList { get; set;  }

    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }
    public virtual ICollection<Student> Students { get; set; }

}

地址模型:

public class Address
{
    public int AddressId { get; set; }
    public string StreetLine1 { get; set; }
    public string StreetLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }

    public Person Person { get; set; }

}

2 个答案:

答案 0 :(得分:1)

是的,你在这里会遇到很多问题。首先,实体框架在使用&#34;共享主键&#34;时仅支持1:1关系。这意味着地址ID和父或学生ID必须相同,并且地址必须是另一个的外键。

我知道为每个创建导航属性似乎很容易,你应该有1:1,但你必须考虑如何在数据库中创建它。它实际创造的是两个独立的1:多种关系。并且,由于没有什么可以阻止您将多个实体分配给多端,这导致EF不支持的情况。

这当然会让事情变得困难,因为你有几个表来链接地址。

我建议改为创建一个&#34; Person&#34; Student和Parent派生自的实体,然后使用TPH或TPC继承来创建Student和Parent唯一实体。

这允许您的家长和学生共享一个公共ID,然后您可以将其用作与您的地址实体的1:1共享密钥。

您可以在此处找到更多信息:

http://blog.bennymichielsen.be/2011/06/02/entity-framework-4-1-one-to-one-mapping/

答案 1 :(得分:0)

首先,我不认为命名是合适的。将父母与学生联系没有任何意义,我认为应该是父母和孩子。并且在每个属性中提供ID属性作为主键使得维护非常困难。但是,让我们尝试按照您的方式实施它。

将一个类作为具有共同属性的人,如ID,全名和名字和姓氏,门牌号码等其他一般信息。这样做会给出一个主键(ID)和一个外键(门牌号)。现在你与Address类有1:1的关系。

在上面给出的学生和家长课程模型中,我发现没有这样的属性可以将学生与其父母相关联,反之亦然。现在您创建类Parent和Student,例如: Parent类有一个ID(ParentOfStudentsList)的整数集合属性,同样,Student类有一个整数集合属性来保存父项的所有ID,与(StudentOfParentsList)相关联,这样做可以让你有一对多和多对一的关系家长和学生之间。

注意:在Parent和Student中派生Person类。我希望这个解决方案适合你。