首页 文章

实体框架 - 关系混乱

提问于
浏览
0

我在理解Entity Framework Code Firsts关系创建方面遇到了问题,因为我更习惯于传统方式 .

one-to-many 关系对我来说似乎很清楚:孩子们只需要一个foreignKey ID属性来指示他们属于哪个Parent .

public class Parent
{
   public int Id { get; set; }
   public virtual ICollection<Child> Childs { get; set; }
}

public class Child
{
   public int Id { get; set; }

   public int ParentId { get; set; } 
   public virtual Parent Parent { get; set; }
}

现在,我不太确定如何正确创建 many-to-many 关系 . 可能还需要一个额外的表 ParentChild ,所以不需要(外键)ID属性吗?

public class Parent
{
   public int Id { get; set; }
   public virtual ICollection<Child> Childs { get; set; }
}

public class Child
{
   public int Id { get; set; }
   public virtual ICollection<Parent> Parents { get; set; }
}

现在,对于 one-to-one 关系,我不知道 . public class Parent {public int Id {get;组; }

public int ChildID { get; set; }
   public virtual Child child { get; set; }
}

public class Child
{
   public int Id { get; set; }

   public int ParentId { get; set; } 
   public virtual Parent Parent { get; set; }
}

是否需要外部ID属性,或者我可以在 Parent 类中使用 Child 属性,在 Child 类中使用 Parent -type属性?当我省略外键ID属性时,是否允许使用 virtual 关键字?

2 回答

  • 0

    我建议你看看实体框架流畅的api . 使用流畅的api可以轻松实现一对一的关系 . Explanation source . 如需快速参考:

    public class Student
        {
            public Student() { }
    
            public int StudentId { get; set; }
            [Required]
            public string StudentName { get; set; }
    
            [Required]
            public virtual StudentAddress StudentAddress { get; set; }
    
        }
    
    
        public class StudentAddress 
        {
            [Key, ForeignKey("Student")]
            public int StudentId { get; set; }
    
            public string Address1 { get; set; }
            public string Address2 { get; set; }
            public string City { get; set; }
            public int Zipcode { get; set; }
            public string State { get; set; }
            public string Country { get; set; }
    
            public virtual Student Student { get; set; }
        }
    

    您可以在datacontext类中重写OnModelCreating .

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<StudentAddress>()
                .HasKey(e => e.StudentId);
            modelBuilder.Entity<StudentAddress>()
                        .Property(e => e.StudentId)
                        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
            modelBuilder.Entity<StudentAddress>()
                        .HasRequired(e => e.Student)
                        .WithRequiredDependent(s => s.StudentAddress);
    
            base.OnModelCreating(modelBuilder);
        }
    
  • 0

    使用Entity Framework,您甚至不必指定外键关系,因为它会从模型中推导出它并相应地创建表 . 您实际需要做的唯一关系类型是0..1或1到0..1或1 .

    不要忘记对象模型比数据库模型更宽松 . 您可以将属性存储在对象中但不在表中 .

    您必须以不同的方式思考,因为EF将在数据库级别为您完成工作,您将可以访问对象模型中定义的所有属性,甚至是集合属性 .

    我一直用来完成它的规则如下:

    如果关系的基数为0..1或1,则使用对另一个实体对象的引用作为您的属性 . 如果基数很多,请使用集合 .

    以下是一些用例:

    1到多(每个父母很多孩子):

    public class Parent
    {
        public int Id { get; set; }
        // Navigation property
        public virtual ICollection<Child> Childs { get; set; }
    }
    
    public class Child
    {
        public int Id { get; set; }
        // Navigation property
        public virtual Parent Parent { get; set; }
    }
    

    数据库中的结果将是具有单个属性(Id)的表父和具有两个属性的表Child,自动生成的Id和外键属性名为Parent_Id(表名然后是下划线,然后是相关类的键属性) ) .

    多对多:

    public class ClassA
    {
        public int Id { get; set; }
        // Navigation property
        public virtual ICollection<ClassB> ClassBs { get; set; }
    }
    
    public class ClassB
    {
        public int Id { get; set; }
        // Navigation property
        public virtual ICollection<ClassA> ClassAs { get; set; }
    }
    

    数据库中的结果将是具有单个属性(Id)的Table ClassA,具有单个属性(Id)的表ClassB和具有两个属性的第三个表(多对多关系的关系表)(this两个表的Ids) .

    EF将推断它为了完成工作所需要的东西,所以你不必具体那么具体 .

    现在,对于唯一有问题的,1比1:

    public class ClassA
    {
        public int Id { get; set; }
        // Navigation property
        public virtual ClassB ClassB { get; set; }
    }
    
    public class ClassB
    {
        public int Id { get; set; }
        // Navigation property
        public virtual ClassA ClassA { get; set; }
    }
    

    遵循我在开始时给出的规则,这就是我们要做的 . 但在这种情况下,EF无法知道关系的方向......一对一的方向是两个方向 . 我们必须让它知道使用注释的方向(对我而言,与Fluent API相比最简单的方法) .

    public class ClassA
    {
        public int Id { get; set; }
        // Navigation property
        public virtual ClassB ClassB { get; set; }
    }
    
    public class ClassB
    {
        [ForeignKey("ClassA")]
        public int Id { get; set; }
        // Navigation property
        public virtual ClassA ClassA { get; set; }
    }
    

    ClassB中的注释[ForeignKey(“ClassA”)]告诉EF使用ClassB中的Id列作为ClassA中的外键 .

    数据库中的结果将是具有2个属性(Id和ClassB_Id)的Table ClassA和具有单个属性(Id)的表ClassB .

    您不必自己创建外部键属性,因为EF会为您执行此操作 .

相关问题