数据库表之间有一对一 一对多 多对多关系。那同样,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