- Conventions 都定义在 System.Data.Entity.ModelConfiguration.Conventions 命名空间下,就是一系列的规则(约束)的集合
- 通俗的讲就是定义数据库里面字段
- 一般我们在约束字段时可以使用Data Annotations 或者 Fluent API 或者Conventions,荐的配置顺序如下:优先使用 Data Annotations ,然后是 Fluent API ,最后才是 Conventions.
1. 类型发现 约束
通俗的说就是让DbConntext 知道我们定义的数据实体,一般做法是自定义一个Context继承与DbConntext,同时定义DbSet属性
public class SwartzUserUserContext : DbContext { public SwartzUserUserContext() : base("UserContext") { } 类型发现 约束 public DbSetUserInfo { get; set; } ..... }
Code First 能够发现并钻取所有的引用类型,如上代码中的MUserInfo 实体如果用引用类型的属性,该属性也会自动包含在模型中,如果不想让某个实体包含进去,可以使用NotMappdeAttribute或者DbModelBuilder.Ignore(fluent API)实现
[NotMapped]public class Department
protected override void OnModelCreating(DbModelBuilder modelBuilder){ modelBuilder.Ignore();}
2. 主键约束
如果实体中的属性名称为ID(不区分大小写)或类名+ID,Code First 会默认其为主键,如果主键属性的类型为int或GUID 则会默认为标识列
3. 关系(外键)约束
- 一对多关系
public class MUserInfo{ [Key] public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } public MOrgInfo OrgInfo { get; set; }}public class MOrgInfo{ [Key] public int ID { get; set; } public string Name { get; set; } public int Address { get; set; } public ListUsers { get; set; }}
如上代码,MUserInfo中有一个MOrgInfo对象,MOrgInfo有一个MUserInfo中有一个MOrgInfo对象集合对象,所以MOrgInfo和MUserInfo是一对多关系,所以CodeFirst在生成数据库时会自动为MUserInfo添加外键(MOrgInfoID)
其实只要一个类中存在引用属性(MOrgInfo OrgInfo),或存在导航属性(List Users),CodeFirst 都会自动生成外键(OrgInfo_ID、MOrgInfoID )
指定外键:
只要外键名命名规范的话,CodeFirst 也会将该属性设置为外键,如下
public class MUserInfo{ [Key] public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } //会自动设置为外键 也可以是MOrgInfoID、MOrgInfoMOrgInfoID public int OrgInfoMOrgInfoID { get; set; } public MOrgInfo OrgInfo { get; set; }}规范的命名指:[目标类型的键名],[目标类型名称]+[目标类型键名称],[导航属性名称]+[目标类型键名称]即MOrgInfoID、OrgInfoMOrgInfoID、MOrgInfoMOrgInfoID
如果命名不规范的话,可以显示的指定外键[ForeignKey("OrgInfo")]public int OrgID { get; set; }public MOrgInfo OrgInfo { get; set; }或
public int OrgID { get; set; }[ForeignKey("OrgID")]public MOrgInfo OrgInfo { get; set; }当然也可以使用Fluent Api 指定外键
modelBuilder.Entity().HasRequired(u => u.OrgInfo).WithMany(o => o.Users).HasForeignKey(u => u.OrgID); 对同一个实体的多个引用
http://www.cnblogs.com/Gyoung/archive/2013/01/22/2869782.html public class MOrgInfo{ [Key] public int ID { get; set; } public string Name { get; set; } public int Address { get; set; } public ListGoodUser { get;set; } public List BadUser { get; set; }}public class MUserInfo{ [Key] public int ID { get; set; } public string Name { get; set; } public int Age { get; set; } public int OrgInfoID { get; set; } public MOrgInfo OrgInfoGood { get; set; } public MOrgInfo OrgInfoBad { get; set; }} 这样的话MUserInfo会生成4个外键,因为有两套类型的导航属性和引用属性,codefirst 无法确定他们之间的关系,就为每个属性都创建,为了让codefirst知道对应关系,可以使用InverseProperty
[InverseProperty("GoodUser")]public MOrgInfo OrgInfoGood { get; set; }[InverseProperty("BadUser")]public MOrgInfo OrgInfoBad { get; set; }这样的话就只有两个外键咯
- 多对多关系 两个实体中都有对方的导航属性,这时会自动生成一张中间表,存两个实体的主键
- 一对一关系 两个实体中都有对方的引用属性,这时必须显示的指定依赖关系
public class Person{ public int PersonId { get; set; } public PersonPhoto Photo { get; set; }}public class PersonPhoto{ [Key, ForeignKey("PhotoOf")] public int PersonId { get; set; } public byte[] Photo { get; set; } public Person PhotoOf { get; set; }}这时 PersonPhoto表中的PersonId既是外键也必须是主键
4.复杂类型约束
如果 Code First 无法从类定义中推断出主键,也没有通过 Data Annotations 或 Fluent API 注册的主键,则此类型自动注册为复杂类型。 此外还要求类型中不能含有对其它实体类型的引用,并且其它类型中也不能含有对本类型引用的属性集合
public partial class OnsiteCourse : Course{ public OnsiteCourse() { Details = new Details(); } public Details Details { get; set; }}public class Details{ public System.DateTime Time { get; set; } public string Location { get; set; } public string Days { get; set; }}Details 就是一个复杂类型
5.移除约定
可以移除任何定义于命名空间 System.Data.Entity.ModelConfiguration.Conventions 中的约定
modelBuilder.Conventions.Remove(); 参考资料: