代码改变世界

EF CodeFirst(四) 关系

2016-01-04 09:07  FelixShen  阅读(749)  评论(0编辑  收藏  举报
数据库表之间有一对一  一对多 多对多关系。那同样,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