zoukankan      html  css  js  c++  java
  • 【AaronYang风格】第一篇 CodeFirst 初恋

    image         原著: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的细节

    image

    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特点的内容的时候,会讲的更深点。

    image通过这幅图,发现Code First,DbContext是建立在EF4前提上的

    开始写 Code First

    Code First名字取的很巧妙哈,先写代码,再写其他的。我们先不考虑一些你可能需要用到的场景,我们先大致看下基本功能。这本书剩下的内容都会一直讲这个。

             AaronYang 说明

             在第一章里面,我们不需要示例代码。接下来写的一些代码只是简单的例子,不是贯穿全文的示例。从第二章开始,你将会实战练习。你可以用visual Studio 跟着写练习,你也可以尝试不看代码,自己写一下。

    当然了,第一件事情,我们需要写一些类去描述我们的 商业领域(domain)。这个例子比较小,就是个 Patient 和 看兽医的Visit 访问记录

    我们新建一个控制台程序吧

    imageimage

    添加一个类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,就可以很方便的查询数据了。image

    使用NuGet添加对 EntityFramework.dll的引用

    imageimage

    或者通过这种方式添加对EntityFramework.dll的引用

    image

    输入 Install-Package EntityFramework    然后 回车(下面一节续篇  我们稍微讲下这个控制台的使用)

    image

    代码如下

    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语法把这条狗的病情和记录存到数据库中去

    运行项目!!

    image


     

    数据库生成的位置

    imageimage

    只要你的电脑装了 VS2012(不在乎你的电脑是否装了vs2010),默认CodeFirst配置生成数据库位置都会在localdb

    imageimage

    VS2012还有种方式查看数据库SQL Server对象资源管理器

    imageimage

    如果你的电脑只装了VS2010,如果你装了SQLExpress默认在 SQLExpress上

    image

    EF CodeFirst会根据你使用VS2010开发还是VS2012开发

    会生成稍微不同的配置文件

    我现在的电脑上装的是VS2010和2012都有,生成的App.config如下

    image

    上面基本一样的

    注意下面的entityFramework那个节点

    这里默认的是LocalDbConnectionFactory.EntityFramework,所以这个项目默认生成的数据库在LocalDb上

    如果想生成在最常见的那种SQLServer上,你可以entityFramework节点下的内容改下

    方式一:

    imageimage

    亲,你现在还陌生吗?同样的不想使用sqlexpress,你自己换成其他的数据库连接字符串方式就行了

    方式二:

    加一个ConnectionStrings的节点

    image

    关于packages.config配置文件,我画红圈的地方不一样,看你使用的.netframework,vs2012应该是net45

    image

    如果需要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们变成数据库的,如图

    image

    这个就好比   用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那张表中,可以为空,我们不希望为空,怎么做?

    image

    我们只要在TypeName属性上加一个Required

    imageimage

    此时再次 运行项目,

    会发生这个错误。因为模型改变了,建议我使用Code First Migrations去更新数据库。这里讲到了Migrations(迁移)

    image

    我们先解决这个问题

    我们打开  包资源管理器控制台,输入enable-Migrations   大小写无所谓

    image

    运行后会生成一个文件夹,后面的20130829020525什么的是时间戳,让每次的Migration都不会出现重复的文件名

    image

    如果 你还遇到一个这样的问题(我是遇到了):

    比如我尝试重新安装EntityFramework,因为我一开项目在家里的电脑的vs,然后用的公司电脑的vs,两个vs的NuGet版本

    不一样,所以会报如下的错误,你只要重新安装最新版本的NuGet,就是保证两个前一次使用的NuGet版本和现在的要一样就行了

    image

    接下来,我们执行  add-migration AddRequiredOnAnimalType_TypeName(包管理控制台中执行)

    添加一次迁移

    image

    然后我们执行update-database

    image

    刷新数据库,TypeName变成not null了,说白了每次的update-database命令都是转换成sql去执行、在后面 update-database –verbose  就可以查看这次迁移的sql语句了。

    加了Required后就像ASP.NET MVC3中那样,Model中的属性就具有验证的功能了,如果为空,EF就会抛出异常的

    由于客户机器上没有vs,所以你可以把这段sql拷过去,作为本次版本数据库的改变了

    image

    我们再在 AnimalType上加上Table注解,里面就是最新的表名称

    image

    我再做一次迁移  复习一下过程

    1.    add-migration UpdateAnimalTypeTableNameToSpecies

    2.    update-database –verbose

    image

    image

    ======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模式,下面有张图判断

    image

    这里不做具体讨论了





     

    最后留言

    关于这本书,重点是在讲使用Code First构建和配置模型(Model).是 Programming Entity Framework (second edition)这本书的拓展。还有一本书叫Programming Entity Framework: DbContext,主要重点在DbContext, DbSet, Validation API,还有些EntityFramework NuGet  包的一些功能的使用讲解

    代码下载: 下载

    注意,可能我们的NuGet的包不太一样,所以运行时候可能有错误,所以代码仅供参考.如果有疑问,亲留言….

     

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

  • 相关阅读:
    PAT Advanced 1067 Sort with Swap(0, i) (25分)
    PAT Advanced 1048 Find Coins (25分)
    PAT Advanced 1060 Are They Equal (25分)
    PAT Advanced 1088 Rational Arithmetic (20分)
    PAT Advanced 1032 Sharing (25分)
    Linux的at命令
    Sublime Text3使用指南
    IntelliJ IDEA创建第一个Groovy工程
    Sublime Text3 安装ftp插件
    Sublime Text3配置Groovy运行环境
  • 原文地址:https://www.cnblogs.com/AaronYang/p/3271657.html
Copyright © 2011-2022 走看看