Entity Framework 查漏补缺 (三)
code first的数据库映射
有两种方式来实现数据库映射:
- 数据属性:data annotation
- 映射配置: fluent api
有继承关系的实体如何映射?
- code first在生成数据库表时,默认使用tph方式
就是把父类和子类生成同一张表,额外增加了一列discriminator字段,区分是父类或子类的数据类型
比如:
父类book对象
public class book { [key] [databasegenerated(databasegeneratedoption.identity)] public int bookid { get; set; } public string bookname { get; set; } public int pages { get; set; } }
子类historybooks对象,继承book
public class historybooks:book { public int chapter { get; set; } }
数据库生成一张表
- 另一种方式(data annotation实现):tpt
不管父类子类,各自生成一张表,以及在子类中增加两者联系的外键;
定义tpt方式 父类和子类定义 [table("xxx")]
如:
父类
[table("book")] public class book { [key] [databasegenerated(databasegeneratedoption.identity)] public int bookid { get; set; } public string bookname { get; set; } public int pages { get; set; } }
子类
[table("historybooks")] public class historybooks:book {public int chapter { get; set; } }
映射数据生成的两张表
book:
historybooks:
映射方式一:data annotation
给实体对象的属性加上注解特性,实现与数据库之间建立映射关系并进行控制
如:
booid映射到表中字段为自增的主键
dataannotations 包含的常用特性:
keyattribute:对应数据库中表的主键的设置
requiredattribute:对应数据库中字段的数据不可null
maxlengthattribute:对应数据库中字符串类型字段的最大长度
concurrencycheckattribute:指定用于开放式并发检查的列的数据类型
timestampattribute:将列的数据类型指定为行版本
databasegeneratedattribute:标记指定实体属性是由数据库生成的,并指定生成策略(none数据库不生成值,identity当插入行时,数据库生成值,computed当插入或更新行时,数据库生成值)
tableattribute:指定实体类对应的数据表名
columnattribute:指定实体属性在数据库中的列名
foreignkeyattribute :指定导航属性的外键字段
notmappeattribute:不映射对应字段
映射方式二:fluent api
fluent api的配置方式可以将实体类与映射配置进行解耦合
有两种方式来实现fluent api的映射配置
- 第一种:重写dbcontext的中onmodelcreating方法
如下面的book类,不再有data annotation特性
public class book { public int bookid { get; set; } public string bookname { get; set; } public int pages { get; set; } }
重写dbcontext中的onmodelcreating方法实现book类映射的配置:
protected override void onmodelcreating(dbmodelbuilder modelbuilder) { modelbuilder.entity<book>().haskey(t => t.bookid); base.onmodelcreating(modelbuilder); }
现实项目中,实体对象可能是非常多的,在onmodelcreating方法中逐一进行映射配置,可想而知会造成dbcontext的代码庞大。
- 第二种:新建bookmap类,并继承entitytypeconfiguration<entitytype>
1、在新建的bookmap类实现映射配置
public class bookmap : entitytypeconfiguration<book> { public bookmap() { this.totable("book", "dbo"); this.haskey(p => p.bookid); //this.haskey(p => new { p.bookid, p.bookpreid });//关联主键 this.property(p => p.bookid).hasdatabasegeneratedoption(databasegeneratedoption.identity);//自动生成 this.property(p => p.bookname).isrequired().hasmaxlength(20).hascolumnname("bookname").isunicode(false);//非空,最大长度20,自定义列名,列类型为varchar而非nvarchar this.ignore(p => p.bookdescription);//忽略改属性的映射 } }
2、依旧重写dbcontext中的onmodelcreating方法,将bookmap 类的实例添加到modelbuilder的configurations。
protected override void onmodelcreating(dbmodelbuilder modelbuilder) { modelbuilder.configurations.add(new bookmap()); }
这样能大大减少onmodelcreating的代码量,依然存在一个问题,就是实体对象一多,还是要逐条将map类的实例添加到modelbuilder的configurations
3、利用反射将程序集中所有的entitytypeconfiguration添加到modelbuilder.configurations中,可以说完全解耦了
protected override void onmodelcreating(dbmodelbuilder modelbuilder) { var typestoregister = assembly.getexecutingassembly().gettypes() .where(type => !string.isnullorempty(type.namespace)) .where(type => type.basetype != null && type.basetype.isgenerictype && type.basetype.getgenerictypedefinition() == typeof(entitytypeconfiguration<>)); foreach (var type in typestoregister) { dynamic configurationinstance = activator.createinstance(type); modelbuilder.configurations.add(configurationinstance); } }
注:此段代码源自网友文章,摘自nopcommerce项目的代码
上一篇: PS制作沙漠中的海市蜃楼流程介绍
推荐阅读
-
【查漏补缺】File的path、absolutePath和canonicalPath的区别
-
一定要面试才刷面试题?Spring160道面试题+Spring书籍助你学Spring,查漏补缺!
-
ASP.NET CORE系列【三】使用Entity Framework Core进行增删改查
-
ASP.NET CORE系列【二】使用Entity Framework Core进行增删改查
-
使用多选框的时的查漏补缺
-
【工作查漏补缺】jQuery ajax - serializeArray()
-
系统查漏补缺:安卓开发月薪20K与40K,相差这几样热门前沿知识(进阶中的程序员必看)
-
工作查漏补缺
-
html查漏补缺之meta标签
-
Entity Framework 查漏补缺 (三)