原文地址:http://www.cnblogs.com/nianming/archive/2012/11/12/2767089.html
实体间的关系,简单来说无非就是一对一、一对多、多对多,根据方向性来说又分为双向和单向。Code First在实体关系上有以下约定:
1. 两个实体,如果一个实体包含一个引用属性,另一个实体包含一个集合属性,Code First默认约定它们为一对多关系。
2. 两个实体,如果只有一个实体包含一个导航属性或一个集合属性,Code First也默认约定它们是一对多关系。
3. 两个实体分别包含一个集合属性,Code First默认约定它们为多对多关系。
4. 两个实体分别包含一个引用属性,Code First默认约定它们为一对一关系。
5. 在一对一关系情况下,需要提供给Code First额外的信息,以确定它们的主从关系。
6. 在实体中定义一个外键属性,Code First使用属性是否为空来确定关系是必须还是可选。
一、一对一
在Code First中,一对一关系总是需要配置,因为两个实体都包含有一个引用属性,无法确定它们的主从关系。
配置一对一关系常用的方法:
HasRequired ,HasOptional ,WithOptional ,WithRequiredPrincipal,WithRequiredDependent
下面是用到的类:
1: public class Person
2: {
3: public int PersonId { get; set; }
4: public int SocialSecurityNumber { get; set; }
5: public string FirstName { get; set; }
6: public string LastName { get; set; }
7: public byte[] RowVersion { get; set; }
8: public PersonPhoto Photo { get; set; }
9: }
10:
11: public class PersonPhoto
12: {
13: public int PersonId { get; set; }
14: public byte[] Photo { get; set; }
15: public string Caption { get; set; }
16: public Person PhotoOf { get; set; }
17: }
因为Photo是具体人的,所以PersonPhoto使用PersonId作为主键。
下面是一对一关系配置的几种情况:
1.PersonPhoto必须属于一个Person,但是Person不一定有PersonPhoto,这种关系是1:0..1,此种情况下Person是一定存在的,所以它是主从关系主的一方。
1: HasRequired(t => t.PhotoOf).WithOptional(t => t.Photo);
或
1: HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf);
2.PersonPhoto必须属于一个Person,Person也必须有PersonPhoto,这种关系式1:1,此种情况下,两个都一定存在,要确定主从关系,需要使用WithRequiredPrincipal或WithRequiredDependent。
1: HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo);
或
1: HasRequired(t => t.Photo).WithRequiredPrincipal(t => t.PhotoOf);
上述两种情况都是真实存在的,不真实存在的就不说了。
下面配置一对一关系贴出Demo:
class Person
2: {
int PersonId { get; set; }
int SocialSecurityNumber { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
byte[] RowVersion { get; set; }
public PersonPhoto Photo { get; set; }
9: }
10:
class PersonPhoto
12: {
int PersonId { get; set; }
byte[] Photo { get; set; }
string Caption { get; set; }
public Person PhotoOf { get; set; }
17: }
18:
//配置Person
class PersonConfiguration : EntityTypeConfiguration<Person>
21: {
public PersonConfiguration()
23: {
//主键
25: HasKey(t => t.PersonId);
//并发检查
27: Property(t => t.SocialSecurityNumber).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None).IsConcurrencyToken();
//长度50 不为空
29: Property(t => t.FirstName).IsRequired().HasMaxLength(50);
//长度50 不为空
31: Property(t => t.LastName).IsRequired().HasMaxLength(50);
//并发检查
33: Property(t => t.RowVersion).IsRowVersion();
//HasRequired(t => t.Photo).WithRequiredPrincipal(t => t.PhotoOf);
//HasOptional(t => t.Photo).WithRequired(t => t.PhotoOf);
36: }
37: }
38:
//配置PersonPhoto
class PersonPhotoConfiguration : EntityTypeConfiguration<PersonPhoto>
41: {
public PersonPhotoConfiguration()
43: {
//主键
45: HasKey(t => t.PersonId);
//长度50
47: Property(t => t.Caption).HasMaxLength(50);
//必须从属于Person
49: HasRequired(t => t.PhotoOf).WithRequiredDependent(t => t.Photo);
50: }
51: }
52:
class BreakAwayContext : DbContext
54: {
public DbSet<Person> People { get; set; }
public DbSet<PersonPhoto> Photos { get; set; }
57:
void OnModelCreating(DbModelBuilder modelBuilder)
59: {
new PersonConfiguration());
new PersonPhotoConfiguration());
base.OnModelCreating(modelBuilder);
63: }
64: }
65:
class Initializer : DropCreateDatabaseAlways<BreakAwayContext>
67: {
public Initializer()
69: {
70: }
71:
//创建数据库时 Seed数据
void Seed(BreakAwayContext context)
74: {
new Person()
76: {
,
,
79: SocialSecurityNumber = 123456,
new PersonPhoto()
81: {
,
byte[] { }
84: }
85: });
86: context.SaveChanges();
87: }
88: }