CodeFirst 初恋
CodeFirst 初恋
原著:Prorgamming Entity Framework Entitywork Code First
大家好!
我是AaronYang,这本书我也挺喜欢的,看了一半了,今晚也没事情,就分享一下一点东西吧
这本书总共8章,192页,整体内容看起来也不算吃力的。但是自己认真学的,感觉内容也不多。初学者完全不用害怕自己会不会学会,放心吧,会学会的。
虽然本书还是基于vs2010 开发的,但是我相信学会这个vs2012那个也会很简单,再说2010现在也还是主流(但也会对比vs2012的)。当然EF会采用版本EF5的
内容:Code First介绍,几种EF编程方式的对比,基本DEMO,Code First生成的数据库在哪,NuGet在EF中的使用,Migration的问题,其他错误处理,Code First 的简单Convention,配置示例等等,包学会的,亲!!!
读者约定:
Code First单词太长了,我简称 CF ,以后 我一直都会这样说哈,不是 腾讯的那个哈。
微软的ADO.NET EntityFramework,简称就是大家所说的EF,一个ORM框架。我对ORM的理解就是,按它的语法简化数据库的操作,平时都是写SQL什么的,ORM还有很多,例如NHibernate,Subsonic其他的等等,这里我不想讨论这个
在Code First出现之前的Model
EF第一次是在VS2008 .NET3.5中 被引进来的。当时工程师们可以用它反向地将数据库变成一个EDMX后缀名的一个实际上是一个XML的文件。它是可视化的,你可以再次调整你的model去作为你的Domain(三层的朋友的大多都是DAL,其实有的架构模式,其中的Domain类似于三层中的DAL层)。Visual Studio 2010 和 .NET4 又引进来了 EF的第二个版本,你们说的EF4(跟.NET版本一样,都是4,同样地,
.NET5,现在已经有EF5了,那么是不是应该学新的呢,我不清楚,如果有技术洁癖的朋友,自己调整一下),在动态创建模型(modeling)的 那一边,一个新的叫Model First的编程方式被添加进来了。从那以后,你就可以通过可视化界面(edmx文件双击后在vs2010里面会有界面,就是那个),你可以在那里面设计(字段,关系等等),然后可以基于你设计的model重新生成数据库(database)
Model First让开发者,首先设计模型,在进程中创建数据库,也就是动态创建数据库啦。这样子,你项目运行的时候,使用者,没有数据库也能动态创建。
不管你是否通过database-first还是model-first的方式设计了EDMX,这接下来的一步就是让你的domain层 里面,通过这些model中的实体和关系自动地创建类,生成代码,到这里开始,开发者就有强类型的类去表现他们的domain中的对象了。有了他们,你就可以很轻松的去操作数据库了。
还好在.NET4 中,EF有了另一个转变。以前在NET 3.5中,EF管理内存中的对象,它必须要让类继承Entity Framework的EntityObject对象。EntityObject把对象(谁继承EntityObject的类)的变化传递给Entity Framework,从而也就是变成了 跟踪这些 对象的变化,最后将这些变化持久化到数据库中去。在.NET4中,除了这个以外,还有个POCO(Plain Old CLR Object)支持,它可以让EntityFramework跟踪些简单的类,而不需要使用EntityObject。这样可以让开发者们使用他们自己的类,而不依赖于EntityFramework的了。因为EF 运行时候在内存中会用另一个自己的方式去跟踪和维护 对象的状态。
Code First 到来
在EF4的基础上,微软再一次地提供了一种方式去建模(modeling),而且现在已经有很多开发者在使用了----Code First.
Code First允许你 不再使用基于XML的EDMX文件去定义你的domain model
即使Model First和Database First可以让一些开发者使用他们(技术工具)生成的代码去解决处理问题,但是许多开发者既不想简单地使用设计器去处理问题,也不想使用它们生成的类去处理问题,那些人就是想去写代码去解决问题。哎~~
所以Code First可以满足那些人
在Code First中,你可以通过使用POCO类开始定义你的domain model,这些类都不依赖于Entity Framework的。Code First可以完全根据你定义的类的结构去推算出一些信息。你也可以进一步地提供一些额外的配置去描述你的model或者重写CF推断的依据的东西。这些配置也是通过code(写代码)配置的,不是XML文件或者设计器。
AaronYang 提醒
当你在使用designer(以前的EF有EDMX文件,双击是一个设计器,designer)的时候,EF4已经支持POCO类了。EF团队提供了 可以帮你生成POCO风格类代码的 POCO模版。这些类在你在设计器里面操作,做改变的时候,这些生成的类也会自动更新。你可能使用自己POCO类而不是使用工具帮你生成的类。但是如果你这样做的话,你必须保持类与EDMX同步。这就意味着,设计器改了,你的类你就要手动去改。Code First有个好处,你的类就是Model了,不需要设计器了,这就意味着,你要做改变什么的,你只要改一处,就是改你的 POCO类。
Code First,Database First和Model First都只是生成一些 符合Entity Framework去操作数据 特定规范的类的技术实现方式。一旦有了符合EF的
Model,EF不管你采用什么方式,哪一种技术,运行的时候表现的都是一样的。所以不管选择哪一种都是取决于你自己。下面一张图1-1,简单地说明了一些EntityFramework的细节
Code First在.NET4的时候,没有立刻发布,但是也没有在.NET5的时候带给开发者,在2011年4月,微软在发行EntityFramework4.1的时候,顺带把Code First一部分带给开发者了,当时还没有把Code First的核心部分发布。接下来,2011年10月 EntityFramework4.2发布了,替代了EF4.1,才真正包含了Code First。这时候,Entity Framework API的核心,System.Data.Entity.dll,已经作为.NET Framework中的一部分。这个dll在EF4.1和4.2是一样,没有变化。
Entity Framework4.1也包括了另一个很重要的特征(feature),叫做 DbContext API
DbContext是这个API的核心,当然核心还包括了其他的类。DbContext是Entity Framework中ObjectContext的轻量级版本。换句话说,ObjectContext是DbContext的超集,它包括了微软觉得开发者在使用EF时候经常使用的一些特征
DbContext可以让你用更简洁的方式,而不需要使用复杂的ObjectContext的编码语法,写更少的代码去实现很多通用的相同的功能。当使用Code First的时候,这一切更容易发现,通过这个系列的博客,你会慢慢体会到的。
还有本书叫 Programming Entity Framework: DbContext 在讲解DbContext,DbSet,验证API,还有一些其他的DbContext特点的内容的时候,会讲的更深点。
通过这幅图,发现Code First,DbContext是建立在EF4前提上的
开始写 Code First
Code First名字取的很巧妙哈,先写代码,再写其他的。我们先不考虑一些你可能需要用到的场景,我们先大致看下基本功能。这本书剩下的内容都会一直讲这个。
AaronYang 说明
在第一章里面,我们不需要示例代码。接下来写的一些代码只是简单的例子,不是贯穿全文的示例。从第二章开始,你将会实战练习。你可以用visual Studio 跟着写练习,你也可以尝试不看代码,自己写一下。
当然了,第一件事情,我们需要写一些类去描述我们的 商业领域(domain)。这个例子比较小,就是个 Patient 和 看兽医的Visit 访问记录
我们新建一个控制台程序吧
添加一个类Patient.cs,代码如下
using System;
using System.Collections.Generic;
namespace ChapterOneProject
{
public class Patient
{
public Patient()
{
Visits = new List<Visit>();
}
public int Id { get; set; }
public string Name { get; set; }
public DateTime BirthDate { get; set; }
public AnimalType AnimalType { get; set; }
public DateTime FirstVisit { get; set; }
public List<Visit> Visits { get; set; }
}
public class Visit
{
public int Id { get; set; }
public DateTime Date { get; set; }
public String ReasonForVisit { get; set; }
public String Outcome { get; set; }
public Decimal Weight { get; set; }
public int PatientId { get; set; }
}
public class AnimalType
{
public int Id { get; set; }
public string TypeName { get; set; }
}
}
Code First核心原则----定义一个 让Code First基于你的类去生成模型的规则。比如说,EF要求一个类要有一个key属性(主键)。CF就会用一个规则,比如说属性名是否叫 Id,或者组合起来的Id(比如说 PatientId),像这类属性的名字都会自动地被CF理解为Key。如果按照规则找不到这样的属性,它会在运行的时候抛出一个异常,说没有key。其他一些的转换规则(convention),决定了string类型的默认长度,或者当你的类继承了其他的类,也就是子类没有东西,CF会按照约定给予默认的表结构,CF根据EF可以预测出来的。
如果CF仅仅依赖这点规则去处理你的类,肯定是有限制的。但是CF没有强加要求去怎么设计去满足它的处理规则。反过来想想,这些规则已经可以处理一批常见的场合问题了。如果你的类整合遵循这些规则,CF就不需要你再提供其他的配置了。EF将会直接处理你的类。如果你的类没有遵循约定,你就需要提供其他的配置来保证CF可以正确的理解你的设计。
在这3个类中,Id根据约定,都会是主键(key).我们先不添加其他配置,让CF处理这些类。
用DbContext管理Object
上面的这3个类对Entity Framework来说没有用,它不认识他们.
但是使用CF就可以了.你就可以使用你自己的类了.如果你使用其他项目的domain层的类,也就是自己的类了,CF将会非常有用了.
为了使用CF,你必须先定义一个类,它是要继承DbContext的.这个是这些类的角色之一,它会作为一个context(上下文),有了它,CF就知道怎样去构造你的model了。同样地,EF也是会理解的,从而跟踪它们的状态。这些完成都是靠一个新的类 DbSet。DbSet跟DbContext出生意义差不多。DbContext被包括在ObjectContext中,轻量级的。同样的,DbSet被包括在EF4的ObjectSet中,轻量级的,使用DbSet可以写更少的代码完成一样的任务。
下面的代码展示了context的大致样子。里面有DbSet泛型的Patients和Visits,但是没有AnimalTypes。CF足够的智能,它知道Patient会使用到AnimalType类,因此,它也是被包括在这个model中的。通过定义了DbSet,就可以很方便的查询数据了。
使用NuGet添加对 EntityFramework.dll的引用
或者通过这种方式添加对EntityFramework.dll的引用
输入 Install-Package EntityFramework 然后 回车(下面一节续篇 我们稍微讲下这个控制台的使用)
代码如下
using System.Data.Entity;
namespace ChapterOneProject
{
public class VetContext : DbContext
{
public DbSet<Patient> Patients { get; set; }
public DbSet<Visit> Visits { get; set; }
}
}
接下来,我们完全可以利用CF代码去操作了,它现在已经可以作为我们的数据访问层了,是不是有点吃惊。这里没有数据库连接字符串,甚至不存在数据库。但是数据访问层已经准备好了,你已经可以使用了。
打开Program.cs我们添加如下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ChapterOneProject
{
class Program
{
static void Main(string[] args)
{
var dog = new AnimalType { TypeName = "Dog" };
var patient = new Patient
{
Name = "Sampson",
BirthDate = new DateTime(2008, 1, 28),
AnimalType = dog,
FirstVisit = new DateTime(2008, 1, 28),
Visits = new List<Visit>
{
new Visit
{
Date = new DateTime(2011, 9, 1)
}
}
};
using (var context = new VetContext())
{
context.Patients.Add(patient);
context.SaveChanges();
}
Console.WriteLine("录入成功!");
Console.ReadKey();
}
}
}
创建一个动物类型,狗
然后创建一个病的狗,来看兽医是在2011年9月1日,就一次记录,还有其他关于狗的信息
接下来我们是CF语法把这条狗的病情和记录存到数据库中去
运行项目!!
数据库生成的位置
只要你的电脑装了 VS2012(不在乎你的电脑是否装了vs2010),默认CodeFirst配置生成数据库位置都会在localdb
VS2012还有种方式查看数据库SQL Server对象资源管理器
如果你的电脑只装了VS2010,如果你装了SQLExpress默认在 SQLExpress上
EF CodeFirst会根据你使用VS2010开发还是VS2012开发
会生成稍微不同的配置文件
我现在的电脑上装的是VS2010和2012都有,生成的App.config如下
上面基本一样的
注意下面的entityFramework那个节点
这里默认的是LocalDbConnectionFactory.EntityFramework,所以这个项目默认生成的数据库在LocalDb上
如果想生成在最常见的那种SQLServer上,你可以entityFramework节点下的内容改下
方式一:
亲,你现在还陌生吗?同样的不想使用sqlexpress,你自己换成其他的数据库连接字符串方式就行了
方式二:
加一个ConnectionStrings的节点
关于packages.config配置文件,我画红圈的地方不一样,看你使用的.netframework,vs2012应该是net45
如果需要SQLExpress 2008 R2的伙伴,可以到这里官网 下载
AaronYang 提醒
Code First中 Convention这个单词
Convention 这个单词我个人理解是 规定,约定。 写CodeFirst的人,如果你的类符合Convention,CodeFirst就能认识,然后它就能够按照已经定义好的Convention去处理你的类,生成你想要的数据库结构,然后你就可以利用EntityFramework操作数据库了。比如说Visit类中的PatientId符合Convention,这里自动处理成外键了。int类型,是其他类的名字+Id
再比如说,VetContext中没有声明DbSet<AnimalType>但是CodeFirst也会帮我们生成,它好像什么都知道的样子原因是你写的Code符合它的Convention了。还有很多其他的Convention,我们后面几章讲解到的。
后面的内容,我会经常说到Convention,到时候,我可不解释咯。如果想要具体添加或者修改Convention,我们可以通过配置完成,当然这里肯定不是DatabaseFirst或者ModelFirst中的 designer可视化操实际上XML文件的EDMX文件。具体的后面说吧
各种方式是如何把Class们变成数据库的,如图
这个就好比 用VC++,VB,C#等.net语言,不管前面怎么弄,最终会变成中间代码(IL)才能被机器识别
也就是说DataBase First, Model Fitst,Code First 最终都是变成内存中的对象,EntityFramework能够识别的(例如EntityType,AssociatonType),然后就可以跟踪,持久化数据操作等等。
简单的配置了解
Code First主要有两种,第一种是Data Annotations, 第二种是Fluent API
第二种的方式的配置更强大点,也就是说,DataAnnotations的功能是Fluent API功能的子集,但是DataAnnotations使用起来更简洁
======Data Annotations小例子====
我们应该发现AnimalTypes那张表中,可以为空,我们不希望为空,怎么做?
我们只要在TypeName属性上加一个Required
此时再次 运行项目,
会发生这个错误。因为模型改变了,建议我使用Code First Migrations去更新数据库。这里讲到了Migrations(迁移)
我们先解决这个问题
我们打开 包资源管理器控制台,输入enable-Mirgrations 大小写无所谓
运行后会生成一个文件夹,后面的20130829020525什么的是时间戳,让每次的Migration都不会出现重复的文件名
如果 你还遇到一个这样的问题(我是遇到了):
比如我尝试重新安装EntityFramework,因为我一开项目在家里的电脑的vs,然后用的公司电脑的vs,两个vs的NuGet版本
不一样,所以会报如下的错误,你只要重新安装最新版本的NuGet,就是保证两个前一次使用的NuGet版本和现在的要一样就行了
接下来,我们执行 add-migration AddRequiredOnAnimalType_TypeName(包管理控制台中执行)
添加一次迁移
然后我们执行update-database
刷新数据库,TypeName变成not null了,说白了每次的update-database命令都是转换成sql去执行、在后面 update-database –verbose 就可以查看这次迁移的sql语句了。
加了Required后就像ASP.NET MVC3中那样,Model中的属性就具有验证的功能了,如果为空,EF就会抛出异常的
由于客户机器上没有vs,所以你可以把这段sql拷过去,作为本次版本数据库的改变了
我们再在 AnimalType上加上Table注解,里面就是最新的表名称
我再做一次迁移 复习一下过程
1. add-migration UpdateAnimalTypeTableNameToSpecies
2. update-database –verbose
======Fluent API小例子====
同样的过程,我们使用Fluent API操作下
打开VetContext类,重写OnModelCreating方法,添加一些代码,估计一看就能看懂了,这里不细说了
using System.Data.Entity;namespace ChapterOneProject{public class VetContext : DbContext{public DbSet<Patient> Patients { get; set; }public DbSet<Visit> Visits { get; set; }protected override void OnModelCreating (DbModelBuilder modelBuilder){modelBuilder.Entity<AnimalType>().ToTable("Species");modelBuilder.Entity<AnimalType>().Property(p => p.TypeName).IsRequired();}}}
判断开发者使用了那种EF模式,下面有张图判断
这里不做具体讨论了
最后留言
关于这本书,重点是在讲使用Code First构建和配置模型(Model).是 Programming Entity Framework (second edition)这本书的拓展。还有一本书叫Programming Entity Framework: DbContext,主要重点在DbContext, DbSet, Validation API,还有些EntityFramework NuGet 包的一些功能的使用讲解
代码下载: 下载
注意,可能我们的NuGet的包不太一样,所以运行时候可能有错误,所以代码仅供参考.如果有疑问,亲留言….
CodeFirst 初恋的更多相关文章
- 【AaronYang风格】第一篇 CodeFirst 初恋
原著:Prorgamming Entity Framework Entitywork Code First 大家好! 我是AaronYang,这本书我也挺喜欢的,看了一半了,今晚也没 ...
- MVC5+EF6+MYSQl,使用codeFirst的数据迁移
之前本人在用MVC4+EF5+MYSQL搭建自己的博客.地址:www.seesharply.com;遇到一个问题,就是采用ef的codefirst模式来编写程序,我们一般会在程序开发初期直接在glob ...
- MVC CodeFirst简单的创建数据库(非常详细的步骤)
最近在学习MVC的开发,相信有过开发经验的人初学一个新的框架时候的想法跟我一样最关心的就是这个框架如何架构,每个架构如何分工,以及最最关键的就是如何与数据库通信,再下来才是学习基础的页面设计啊等 ...
- ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存
ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 part 1:给我点时间,允许我感慨一下2016年 正好有时间,总结一下最近使用的一些技术,也算是为2016年画上一个完 ...
- 使用EF CodeFirst 创建数据库
EntityFramework 在VS2015添加新建项时,选择数据->ADO.NET 实体数据模型,有一下选项 来自数据库的EF设计器,这个就是我们最常用的EntityFramework设计模 ...
- 1.【使用EF Code-First方式和Fluent API来探讨EF中的关系】
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/relationship-in-entity-framework-using-code-firs ...
- 2.EF中 Code-First 方式的数据库迁移
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...
- 3.EF 6.0 Code-First实现增删查改
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-entity-framework-5-0-code- ...
- ASP.NET MVC——CodeFirst开发模式
Entity Framework框架提供了几种开发模式,比如Database First,Model First,Code First.Database First是最老也是应用得最广泛的一种设计方式 ...
随机推荐
- 64bit Centos6.4编hadoop-2.5.1
64bit Centos6.4编hadoop-2.5.1 1.说明 a) 因为从apache下载下来的tar.gz包是用32 bit编译的,全部假设用Linux 64作为hadoop的 ...
- 每日算法37:Rotate Image (图像旋转)
You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). ...
- MapReduce 编程模型
一.简单介绍 1.MapReduce 应用广泛的原因之中的一个在于它的易用性.它提供了一个因高度抽象化而变得异常简单的编程模型. 2.从MapReduce 自身的命名特点能够看出,MapReduce ...
- centos7看电影
sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm sudo rpm ...
- Scala Sublime text 3 Build 编译
使用Sublime text 3编译Scala 在sublime工具栏中[tools]->[Build System]->[new Build System]添加如下文本 { " ...
- Keil中使用Astyel进行C语言的格式化
Astyel !E --style=linux --delete-empty-lines --indent=spaces=2 --break-blocks 这可以做到, 使用Linux风格的代码 ) ...
- HBuilder js 自定义代码块
=begin 本文档是HBuilder预置的js代码块的文件.注意不要把其他语言的设置放到js里来. 如果用户修改此文档,HBuilder升级后会覆盖用户的修改,建议进入菜单 工具→扩展代码块 扩展相 ...
- C# FileSystemWatcher 监视磁盘文件
C# FileSystemWatcher 监视磁盘文件变更 简化需求:有一个简化了的需求是这样的:有一个拍照程序在运行,一旦抓拍之后则将图片文件存储至某目录,然后图片要上传至远程服务器并update数 ...
- 如何使用OPENQUERY访问另一个SQL Server
原文:如何使用OPENQUERY访问另一个SQL Server 在项目中,经常会遇到一个数据库访问另一个数据库,[CNVFERPDB]为服务器名,[CE3]为库名 SELECT Dtl.* FROM ...
- App.config
App.config的学习笔记 昨天基本弄清config的使用之后,再看WP的API,晕了.结果WP不支持system.configuration命名空间,这意味着想在WP上用App.config ...