你的位置:首页 > ASP.net教程

[ASP.net教程]EF CodeFirst(四) 关系


数据库表之间有一对一  一对多 多对多关系。那同样,CodeFirst也要能分析这些类之间的这些关系。CodeFirst可以自动通过分析类之间的属性导航属性 从而得出类之间的关系,自动确定外键。

一对多
一对多是最为常见的一种关系,符合怎样的规范会被CodeFirst识别为一对多的关系呢?


  public class Blog  {    public string ID { get; set; }    public string BlogName { get; set; }    public string BlogAuthor { get; set; }    public virtual List <Post> Posts { get; set ; }   //导航属性         public virtual List <Article> Articles { get; set; } //导航属性    [ Timestamp]    public byte [] version { get; set; }  }  public class Post  {    public string ID { get; set; }    public string PostName { get; set; }    public string Content { get; set; }    public virtual Blog BelongBlog { get; set; }   //导航属性  }  public class Article  {    public string ID { get; set; }    public string ArticleName { get; set; }    public string Content { get; set; }  }

CodeFirst发现 Blog中有两个集合导航属性,Post中也有一个Blog类型的引用属性,分析出Blog和 Post以及Article之间都存在一对多的关系。

我们还可以发现 Article中并没有 Blog类型的导航属性,并且 Post和Article生成的主键名称不一样。
其实EF推断两个类之间存在一堆多的关系,只需要 两个类中的其中一个存在指向另一个类的导航属性即可。
并且 外键名称的生成规则是 首先是 导航属性名称+ 下划线_ +ID 如果导航属性不存在 那就是 另一个类的类名+ID
 
存在显示的符合规范的外键
有些时候就是手贱,喜欢手动写上外键,那么属性名称符合什么样的规范会被CodeFirst识别为外键,而不是一般属性呢?(当然前提是已经存在导航属性)
当属性符合 [目标类型的键名],[目标类型名称]+[目标类型键名称],或[导航属性名称]+[目标类型键名称]的形式的时候,会被判定为外键。
 
当两个类之间存在多个关系时会怎样呢?在Post类中,有可能需要跟踪谁创建了它,以及谁编辑了它。那么Post类就需要增加两个导航属性
  public Person CreatedBy { get; set; }    public Person UpdatedBy { get; set; }

那同样在我们的Person类之中,也需要加上两个属性,一个属性指向这个人创建的所有文章,另一个属性指向之个人更新的所有文章。
 public virtual List<Post> PostsWritten { get; set; }    public virtual List <Post> PostsUpdated { get; set ; }

会发现这时候生成了四个外键,这是因为当类之间存在多个关系的时候,EF是无法准确分辨的,需要我们手动的添加代码来帮助EF分析。要想解决这个问题 就要用另一个数据注释 : InverseProperty 代码赢改成如下
    [InverseProperty( "CreatedBy")]    public virtual List <Post> PostsWritten { get; set ; }    [ InverseProperty("UpdatedBy" )]    public virtual List <Post> PostsUpdated { get; set ; }

要注意 InverseProperty括号内的名称是要与另一个类的相关的导航属性名称相匹配的,否则会报错。
这个时候数据库外键就正确了




多对多
如果两个类之间,各自都有集合导航属性指向对方,那这两个类之间的关键会被识别为多对多关系。

 public class Student  {    public int StudentID { get; set; }    public string Name { get; set; }    public List <Course> Courses { get; set ; }  }  public class Course  {    public int CourseID { get; set; }    public string CourseName { get; set; }    public List <Student> Students { get; set ; }  }

学生可以选择多门课程,每门课也有很多学生,这样的多对对关系,codefirst会自动生成第三张表,表里存放另外两张表的主键作为外键存放。




一对一
在一对一和一对多的关系之后,我们回头再来讲一对一的关系。

如果需要将两个类之间的关系配置为一对一的关系,那么需要两个类互相有指向对方的引用属性

 public class Book  {    public int BookID { get; set; }    public string Name { get; set; }    public BookCover Cover { get; set; }  }  public class BookCover  {    [ Key , ForeignKey ("Coverof" )]    public int BookID { get; set; }    public byte [] Photo { get; set; }    public Book Coverof { get; set; }  }

并且两个类的主键要是一样的,而且为了确认其中一个为关系中的依赖主体,必须用ForeignKey指明,也就是上面的BookCover表的BookID既是外键也必须是主键。否则会报错。
 
关系就讲到这里,如果喜欢就 推荐一下吧~ O(∩_∩)O