原著: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 ,以后 我一直都会这样说哈,不是 腾讯的那个哈。

第一章 欢迎 Code First
 

微软的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-Migrations   大小写无所谓

运行后会生成一个文件夹,后面的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的包不太一样,所以运行时候可能有错误,所以代码仅供参考.如果有疑问,亲留言….

 

本文章是 Http://AaronYang.cnblogs.com  AaronYang(杨洋)辛苦写的,转载时候,请标明出处

【AaronYang风格】第一篇 CodeFirst 初恋的更多相关文章

  1. [转载] Android Metro风格的Launcher开发系列第一篇

    前言:从毕业到现在已经三年多了,回忆一下这三年基本上没有写过博客,总是觉得忙,没时间写,也觉得写博客没什么大用.但是看到很多大牛们都在写博客,分享自己的东西,所以嘛本着向大牛看齐,分享第一,记录第二的 ...

  2. Android Metro风格的Launcher开发系列第一篇

    前言:从毕业到现在已经三年多了,回忆一下这三年基本上没有写过博客,总是觉得忙,没时间写,也觉得写博客没什么大用.但是看到很多大牛们都在写博客,分享自己的东西,所以嘛本着向大牛看齐,分享第一,记录第二的 ...

  3. CodeFirst 初恋

    CodeFirst 初恋 原著:Prorgamming Entity Framework Entitywork Code First 大家好! 我是AaronYang,这本书我也挺喜欢的,看了一半了, ...

  4. 深入学习jQuery选择器系列第一篇——基础选择器和层级选择器

    × 目录 [1]id选择器 [2]元素选择器 [3]类选择器[4]通配选择器[5]群组选择器[6]后代选择器[7]兄弟选择器 前面的话 选择器是jQuery的根基,在jQuery中,对事件处理.遍历D ...

  5. 【第一篇】ASP.NET MVC快速入门之数据库操作(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  6. 如何起草你的第一篇科研论文——应该做&避免做

    如何起草你的第一篇科研论文——应该做&避免做 导语:1.本文是由Angel Borja博士所写.本文的原文链接在这里.感谢励德爱思唯尔科技的转载,和刘成林老师的转发.2.由于我第二次翻译,囿于 ...

  7. Android开源项目第一篇——个性化控件(View)篇

    本文为那些不错的Android开源项目第一篇——个性化控件(View)篇,主要介绍Android上那些不错个性化的View,包括ListView.ActionBar.Menu.ViewPager.Ga ...

  8. Android开发UI之开源项目第一篇——个性化控件(View)篇

    原文:http://blog.csdn.net/java886o/article/details/24355907 本文为那些不错的Android开源项目第一篇——个性化控件(View)篇,主要介绍A ...

  9. 微信小程序教程(第一篇)

    目录 第一篇小程序概述 第二篇如何注册接入小程序及搭建开发环境 第三篇小程序的架构及实现机制,信道服务及会话管理 第四篇小程序开发基本框架及其限制与优化 第五篇小程序开发项目实例,测试及发布 .... ...

随机推荐

  1. OpenGL ES 3.0 图元组合和光栅化(三)

    图元是能够被OpenGL ES 绘制的几何物体,如三角形.线条或者精灵.在图元组合过程 中,对每个图元必须判断是否位于投影 截体内,如果图元不完全在平截体内部,将被视图平截体剪贴,如果完全在平截体外, ...

  2. Springmvc 上传文件MultipartFile 转File

    转自:http://blog.csdn.net/boneix/article/details/51303207 业务场景:ssm框架 上传文件到应用服务器过程中要传到专有的文件服务器并返回url进行其 ...

  3. iOS编程(双语版)-视图-Autolayout代码初步

    一谈到Autolayout,初学者肯定想到的是IB中使用拖拽啊,pin啊各种鼠标操作来进行添加各种约束. 今天我们要聊得是如何利用代码来添加视图间的约束. 我们来看一个例子: (Objective-C ...

  4. 查看java进程启动的详细参数和过程

    jsp 查看java进程: 6448 main 然后,使用jinfo pid 查看: jinfo 6448 有一行VM Flages:表示启动参数 VM Flags: -Dproc_main -*** ...

  5. Java 生成ZIP文件

    public static byte[] fileToZip(){ ZipOutputStream append = null; ByteArrayOutputStream bos = new Byt ...

  6. Linux内核配置:Kconfig

    Linux内核源码中,差不多有300个内核子目录都包含了名为Kconfig的文件.这个文件用于配置其所在目录的源码的特性.Kconfig中的每个配置参数都有附带的帮助文本,配置子系统会解析Kconfi ...

  7. JAVA开发总结

    1.Float取整 long warning; float fwarning = 0f; fwarning = total*0.34/100; warning = new Float(fwarning ...

  8. Git如何获得两个版本间所有变更的文件列表

    https://segmentfault.com/q/1010000000133613 git diff --name-status HEAD~2 HEAD~3

  9. 【leetcode】solution in java——Easy1

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6409067.html 1:Hamming distance The Hamming distance betw ...

  10. Jackson序列化日期类型的属性

    @JsonProperty("BankSettlementDate") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = ...