关于Entity Framework 的code first 模式,相信大家都不陌生了.本文就来看看实体继承在 codefirst里的用法.

第一步  添加 code first 的环境

这里为了方便,选用的是 VS2013 +  SQL SERVER 2014 LocalDb, 查看数据用 SQL Server Management Studio 2014

工程我们选用最简单的控制台.

新建完成控制台项目(这里以 EF_CodeFirst_Test 命名)以后,添加 EF 的库,可以用NuGet 的界面添加,也可以用命令,这里用命令添加

在程序包管理器控制台(工具 –>  NuGet程序包管理器 –> 程序包管理器控制台) 输入

Install-Package EntityFramework EF_CodeFirst_Test#换上你自己的项目名

接下来,在app.config里加入连接字符串

<add name="CodeFirstModel" connectionString="data source=(LocalDb)\MSSQLLocalDb;initial catalog=TestDb;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework" providerName="System.Data.SqlClient" />
<!-- 同样的,换上你自己的数据库 -->

第二步 编写实体类

基类型

public class BaseClass
{
public long ID { get; set; } public string Name { get; set; } }

三个扩展类,这里为了合并一些表字段,加入了 注解,不然EF会把不同子类里的同名字段后面加上1  2  3 等的数字来区分.加入注解可以强制不同的子类在相同的类型下使用同一字段.

注解相关的命名空间如下

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

这里要说明一下,在.net 4.5中 Schema里的一些字段放到了自带的类库里,而在.net 4 及.net 3.5 里是没有的,如果你用一个版本建立了项目,又切换了.net 版本,记得重新安装EF,以保证不要出现同一个类在两个库中同时出现导致无法编译.

下面是几个扩展类

public class ExtendClass:BaseClass
{ public string DescriptionString { get; set; } [Required]
[Column("LongNum")]
public long LongNum { get; set; }
} public class ExtendClass2 : BaseClass
{ [Column("Version")]
public string Version { get; set; } [Required]
[Column("IntNum")]
public int IntNum { get; set; } } public class ExtendClass3 : BaseClass
{
[Column("Version")]
public string Version { get; set; } [Required]
[Column("IntNum")]
public int IntNum { get; set; } [Required]
[Column("LongNum")]
public long LongNum { get; set; } }

最后是数据库上下文

public partial class CodeFirstModel : DbContext
{
public CodeFirstModel()
: base("name=CodeFirstModel")
{
}
public virtual DbSet<ExtendClass> ExtendClass { get; set; }
public virtual DbSet<BaseClass> BaseClass { get; set; }
public virtual DbSet<ExtendClass2> ExtendClass2 { get; set; }
public virtual DbSet<ExtendClass3> ExtendClass3 { get; set; }
}

第三步 开始尝试—>建数据库

在Main函数里加入下面代码并执行

Database.SetInitializer(new DropCreateDatabaseIfModelChanges<CodeFirstModel>());
using (var context = new CodeFirstModel())
{
context.Database.Initialize(true);
}

然后我们可以在 SQL Server Management Studio  里看到数据库,并且还有两个表

从这张表上不难看出,在同一个基类下面继承出的不同实体, code first 会为我们创建同一张表来存储他们.第一个表是code first 的工作表,仅与模型的更新有关.第二个表者是真正的实体表.

让我们看看这个表的构成.

我们会发现,所有的子类的字段都在这里,因为我们用注解合并了一些数据字段,不然同名的字段会出现多个,并且后面补1,2,3 这些数字来区分.

子类中虽然我们在字段上标了[Required],但是表中的字段仍然是可空的.不能想到,因为在这个实体里是必须的,但是其它的子类里就不一定了,所以,只有其类的[Required]标注会让EF 创建一个not null的字段.

第四步  存一点数据看看吧

在Main 函数里插入点数据吧

using(CodeFirstModel db = new CodeFirstModel())
{ BaseClass bc = new BaseClass { Name = "" };
db.BaseClass.Add(bc); ExtendClass bc1= new ExtendClass() { Name = "王二", DescriptionString = "麻子" };
db.ExtendClass.Add(bc1); ExtendClass2 bc2 = new ExtendClass2 { Name = "Sqlserver", Version = "" };
db.ExtendClass2.Add(bc2); db.SaveChanges();
}

我们再来看看数据库里的数据

好的,都存进去了,让我们试试往基类的实体集里插入子类实体

修改Main 函数里添加的部分代码

using(CodeFirstModel db = new CodeFirstModel())
{ //BaseClass bc = new BaseClass { Name = "" }; //db.BaseClass.Add(bc); //ExtendClass bc1= new ExtendClass() { Name = "王二", DescriptionString = "麻子" };
//db.ExtendClass.Add(bc1); //ExtendClass2 bc2 = new ExtendClass2 { Name = "Sqlserver", Version = "2014" };
//db.ExtendClass2.Add(bc2); ExtendClass3 bc3 = new ExtendClass3 { Name = "C3", Version = "", IntNum = , LongNum = 0xFFFFFFFFFFL };
db.BaseClass.Add(bc3);
db.SaveChanges();
}

执行后查看数据库

然后我们发现,往基类的实体集里插子类实体,跟往子类的实体集中插入是一样的.

第五步 读点数据吧

修改Main 函数与实体操作相关部分

using(CodeFirstModel db = new CodeFirstModel())
{ //BaseClass bc = new BaseClass { Name = "" }; //db.BaseClass.Add(bc); //ExtendClass bc1= new ExtendClass() { Name = "王二", DescriptionString = "麻子" };
//db.ExtendClass.Add(bc1); //ExtendClass2 bc2 = new ExtendClass2 { Name = "Sqlserver", Version = "2014" };
//db.ExtendClass2.Add(bc2); //ExtendClass3 bc3 = new ExtendClass3 { Name = "C3", Version = "9981", IntNum = 3000, LongNum = 0xFFFFFFFFFFL };
//db.BaseClass.Add(bc3);
//db.SaveChanges(); foreach (var item in db.BaseClass)
{
var cbc3 = item as ExtendClass3;
if (cbc3 != null)
{
Console.Write(cbc3.ID);
Console.Write(":\t");
Console.WriteLine(cbc3.Name);
}
} }

我们可以看到执行的结果

看到了吧,从基类的实体集里读到的,实际上是子类实体.是可以向下转型到对应的子类的.当然,向上转型就不说了.

小结

Entity Framework 的 codefirst 模式让我们可以把数据库中的实体当成是本地的实体来用.无疑,这让我们的代码有了更大的灵活性.但是同时,也让数据库看起来不那么友好了,因为里面多了实体映射的字段.

ORM框架在一定程度上屏蔽了数据库的差异,但同时也屏蔽了一些数据库的优势.而codefirst 更是让一些复杂的数据切分及用存储过程加速处理变得不那么友好了.引用一句老话,不要为了做IT为做IT,当我们的ORM无法快速的达到我们预期的目的时,不妨把ORM 拿掉,用最原始的驱动加上手写的SQL和存储过程来做应用.

Code First 之类继承的更多相关文章

  1. Entity Framework Code First 映射继承关系

    转载 http://www.th7.cn/Program/net/201301/122153.shtml Code First如何处理类之间的继承关系.Entity Framework Code Fi ...

  2. 关于JavaScript继承的那些事

    在JavaScript中,对象的创建可以脱离类型(class free),通过字面量的方式可以很方便的创建出自定义对象. 另外,JavaScript中拥有原型这个强大的概念,当对象进行属性查找的时候, ...

  3. Template Method模式和Strategy模式[继承与委托]

    继承 program by difference. 通过继承,可以建立完整的软件结构分层.其中每一层都可以重用该层次以上的Code. 过度使用继承的代价是巨大的.应使用组合或者委托来替代继承. Tem ...

  4. Objective-C:继承的体现

    典型的继承例子:形状Shape为基类,继承它的类有:点类Point.圆类Circle.球体类Sphere.矩形类Rectangle.正方形类Square 点类Point也为基类,继承它的类有:圆类Ci ...

  5. 常用的JavaScript模式

    模式是解决或者避免一些问题的方案. 在JavaScript中,会用到一些常用的编码模式.下面就列出了一些常用的JavaScript编码模式,有的模式是为了解决特定的问题,有的则是帮助我们避免一些Jav ...

  6. Zero Requiem

    “最后是在游行.暴君鲁路修高居王座,两侧列着所有反对者的代表:黑色骑士团.黎星刻.原圆桌骑士名列第三的吉诺,以及一身女囚装的娜娜丽,他们都即将被公开处死.尤菲米娅在第一次“特别行政区•日本”成立仪式上 ...

  7. 新浪微博OAuth2.0的用法

    最近学习Android开发,照着视频开发新浪微博,但是视频里的介绍的是OAuth1.0的授权方式,试了半天发现用不了. 原来现在一般没审核的用户只能使用OAuth2.0了,视频教学里的方法已经过时了. ...

  8. (转)常用的js设计模式

    模式是解决或者避免一些问题的方案. 在JavaScript中,会用到一些常用的编码模式.下面就列出了一些常用的JavaScript编码模式,有的模式是为了解决特定的问题,有的则是帮助我们避免一些Jav ...

  9. 基于Node的PetShop,RESTful API以及认证

    前篇 - 基本认证,用户名密码 后篇 - OAuth2 认证 由于宠物店的业务发展需要,我们需要一种更加便捷的方式来管理日益增多的宠物和客户.最好的方法就是开发一个APP,我可以用这个APP来添加.更 ...

随机推荐

  1. w3m使用小记

    By francis_hao    Mar 8,2017   w3m是一个基于文本的web浏览器和分页器,运行在unix和windows系统上. 可显示包含链接的超文本标记语言(HTML),显示效果如 ...

  2. Python selenium chrome 环境配置

    Python selenium chrome 环境配置 一.参考文章: 1. 记录一下python easy_install和pip安装地址和方法 http://heipark.iteye.com/b ...

  3. C#访问加密的SQLite数据库

    前提:一个项目需要存储各种密码数据,使用的嵌入式的SQLite数据库.默认的SQLite数据库是没有加密的,这样相当不安全.找呀找呀找方法... 方法: 1.使用SQLite管理器加密. 部分SQLi ...

  4. GIST特征描述符使用(转)

    GIST特征描述符使用 一种场景特征描述 场景特征描述? 通常的特征描述符都是对图片的局部特征进行描述的,以这种思路进行场景描述是不可行的. 比如:对于“大街上有一些行人”这个场景,我们必须通过局部特 ...

  5. LG2831 愤怒的小鸟

    题意 分析 看n的范围只有18,考虑状压dp. 用\(f(s)\)表示过集合s中的点所需最小的抛物线数量. 然后枚举点对算抛物线,判断其他点是否在抛物线上来转移. 细节 判断能否构成抛物线只需要判断斜 ...

  6. Documentation/kobject.txt翻译--sysfs

    你从未想过的关于kobjects,ksets和ktypes的一切:作者:Greg Kroah-Hartman <gregkh@linuxfoundation.org>:上次更新时间:200 ...

  7. Ubuntu14.04下Sublime Text 3解决无法输入中文

    在Ubuntu 14.04中安装了SublimeText 3之后发现既然不支持输入中文,于是在网上搜罗一下,发现很多人遇到了同样的问题,但是解决办法大该就只有一个.下面根据自身的安装及解决办法总结如下 ...

  8. 02 - Unit04:笔记本加载功能

    @ExceptionHandler 在控制器中统一处理异常. 为了重用异常处理方法,可以将处理方法抽象到父类中,子类共享异常处理方法. 语法: @ExceptionHandler(Exception. ...

  9. Spring整合Hibernate,Druid(Maven)

    本文转载自:http://blog.csdn.net/lantazy/article/details/52495839 首先,说一下spring,spring有很好的整合能力,Web应用的各个层次都能 ...

  10. 汇编_指令_XCHG

    交换指令XCHG是两个寄存器,寄存器和内存变量之间内容的交换指令,两个操作数的数据类型要相同,可以是一个字节,也可以是一个字,也可以是双字 .其指令格式如下: XCHG Reg/Mem, Mem/Re ...