初试Code First(附Demo)

来源:互联网 发布:未来软件园 mac 迅雷 编辑:程序博客网 时间:2024/05/22 10:36


http://www.cnblogs.com/xishuai/p/3632304.html

http://blog.csdn.net/kisscatforever/article/details/51442449


写在前面

  1. 新建项目
  2. 安装EntityFramework程序包
  3. 创建模型
  4. 创建上下文DbContext
  5. 创建数据库、读/写数据
  6. 配置连接字符串
  7. Code First 迁移
  8. 示例Demo下载
  9. 后记

  以前逛园子的时候,很多大牛写的一些东西,什么AOP、DDD之类的,看过之后一头雾水,远望大牛,回过头看看自己,原来程序员的差距还可以这么大。每个程序员都有个大牛梦想,当然小菜我也是,只是还在开始的路上。

  因为前几天研究easyui,准备写个mvc+ef+easyui的简单示例,当然这对很多人来说很简单,有段时间也研究过别人写的,但这是小菜我第一次自己写,勿喷。而且这周安排给自己的任务:设计模式第五篇-控制反转(ioc),前段时间做些其他方面的事,设计模式也好久没写了,所以这周必须把它完成,想研究完ioc之后,试着再写上面的简单示例,把ioc融入到mvc中,想想应该有搞头。

  关于Code First,昨晚无意间看到一位园友翻译的相关教程:http://www.cnblogs.com/qouoww/archive/2011/12/31/2309066.html,这边小弟先谢过,前面几篇还可以看下去,但是后面几篇就有点不知所云了,学习是一方面,实践是另一方面,做的过程中才能学到更多的东西,这边也试着写个关于Code First的小示例。

  自己动手,丰衣足食。

新建项目

  我使用的是vs2012,如果使用vs2010需要安装NuGet。

Nuget是一个.NET平台下的开源的项目,它是Visual Studio的扩展。在使用Visual Studio开发基于.NET Framework的应用时,Nuget能把在项目中添加、移除和更新引用的工作变得更加快捷方便。

  新建-项目-Visual C#-windows-控制台应用程序,命名为:CodeFirstDemo。

  这边需要注意的是:选择.net framework的时候要4.0以上版本,要不然下面NuGet安装EntityFramework扩展的时候会报创建项目版本底无法完成安装的错误,.net framework改成4.0就可以了,但是换了一台电脑3.5版本测试安装又是好的,不知是个什么情况,反正.net framework版本最好选择4.0以上。

安装EntityFramework程序包

  新建好CodeFirstDemo项目后,我们先来安装EntityFramework,项目-管理NuGet程序包-联机-搜索“EntityFramework”,下载安装。

  安装完成后会在项目下自动添加EntityFramework引用:

  在Program.cs代码文件中添加下面命名空间:

1 using System.Data.Entity;

创建模型

  Code First顾名思义就是代码先行的意思,除了Code First,还有Model First、DatabaseFirst,关于他们几个的区别:http://blog.bossma.cn/csharp/when-is-code-first-not-code-first/。

  下面我们在Program.cs中创建几个模型,平常我们可以分离出来。

复制代码
 1     public class New 2     { 3         public int NewId { get; set; } 4         public string Title { get; set; } 5  6         public int NewTypeId { get; set; } 7         public virtual NewType NewType { get; set; } 8     } 9 10     public class NewType11     {12         public int NewTypeId { get; set; }13         public string Name { get; set; }14 15         public int BlogId { get; set; }16         public virtual List<New> New { get; set; }17     }
复制代码

  NewId和NewTypeId在创建的时候会做为表的主键,因为包含有ID关键字,如果不包含的话,需要我们指定主键,要不然创建就会报未找到主键的错误,添加命名空间:

1 using System.ComponentModel.DataAnnotations;

  并在属性前添加[Key]标注,指示此字段作为主键,例如:

1         [Key]2         public string UserName { get; set; }

  当然除了Key,System.ComponentModel.DataAnnotations命名空间下还有其他的Attribute,这边就不多说,可以查看msdn有关教程:http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx。

  需要注意的另外一点,上面定义模型属性的时候有virtual关键字,表示延迟加载,我的理解是这样:当我访问主实体的时候,启动延迟加载,而不会查询数据库的子体,只有要访问它的时候才会去数据库查询加载,泛型List表示此实体是一对多的关系。

  EF默认是启动延迟加载的,我们如果不需要也可以手动禁止:

1 db.Configuration.LazyLoadingEnabled = false;,

创建上下文DbContext

  我对EF中上下文的理解:可以把上下文看成一个数据库控制器,我们可以在其中查询、更改、删除数据,然后通过连接获取或是提交。就像是遥控车的遥控器一样,EF是这个遥控器的核心部件,天线是连接字符串,遥控车是数据库,这个比喻可能不是很恰当,但就是这个意思,大家都懂得。

1     public class NewsContext : DbContext2     {3         public DbSet<New> News { get; set; }4         public DbSet<NewType> NewTypes { get; set; }5     }

  DbSet表示上下文中给定类型的所有实体的集合或可从数据库中查询的给定类型的所有实体的集合,就像是一个包裹,需要什么东西就往里面装什么东西。

创建数据库、读/写数据

  在Program.cs的Main方法中填写代码:

复制代码
 1             using (var db = new NewsContext()) 2             { 3                 Console.Write("输入新闻类型标题: "); 4                 var name = Console.ReadLine(); 5  6                 var type_Model = new NewType { Name = name }; 7                 db.NewTypes.Add(type_Model); 8                 db.SaveChanges(); 9 10                 Console.WriteLine("查询新闻类型标题:");11                 var search_type = Console.ReadLine();12                 var query = from b in db.NewTypes13                             where b.Name == search_type14                             select b;15 16                 Console.WriteLine("查询结果:");17                 foreach (var item in query)18                 {19                     Console.WriteLine(item.Name);20                 }21 22                 Console.ReadKey();23             } 
复制代码

  上面代码创建一个上下文对象实例,通过该实例添加一个新闻实体,然后通过输入的值,linq查询结果输出。

  通过上面的操作,我们并没有创建什么连接字符串和数据库操作,但是打开数据库就可以看到我们通过Code First创建的数据库了。

  我当时做的时候,运行代码没有错误,但是用.\SQLEXPRESS和localhost登陆都看不到数据库,安装vs2012就给自动安装了localdb,因为我本地没 .\SQLEXPRESS,MSDN相关注解:

  • 如果本地 SQL Express 实例可用(默认情况下随 Visual Studio 2010 安装),则 Code First 已对该实例创建了数据库
  • 如果 SQL Express 不可用,则 Code First 将尝试使用 LocalDb(默认情况下随 Visual Studio 2012 安装)

配置连接字符串

  通过上面默认生成数据库规则可以看出,数据库名是项目命名空间+上下文,有时候我们需要自己定义生成数据库名称,或是生成数据库到指定的服务器,而且有时候数据库迁移了,我们不能再重新生成一遍吧,这时候我们就要自定义数据库连接字符串了:

  <connectionStrings>    <add name="DEMO" connectionString="Data Source=.;Initial Catalog=EFCodeFirst;Integrated Security=True;" providerName="System.Data.SqlClient"/>  </connectionStrings></configuration>

  需要注意的是connectionStrings必须放在configuration节点内的最下面,如果放在最上面会报下面这种错误:

  我们重新按照上面的操作运行程序,就可以在指定的服务器.\SQLEXPRESS,生成指定的数据库CodeFirstDemoDB。

Code First 迁移

  关于Code First 迁移其实就是我们在更改模型的时候,数据库要相应的更改,打开工具-库程序包管理器-程序包管理器控制台。

  1,例如我们上面创建NewTypes表的时候,没有指定字段的长度,默认是创建字段类型是nvarchar(MAX),有时候我们觉得字段长度太长,需要修改一下字段长度,不要直接去修改数据库,而是在模型中修改:

1         [MaxLength(50)]2         public string Name { get; set; }

  MaxLength就是上面我们说到DataAnnotations命名空间下的类型,这边我们注意下,我们在生成数据库的时候添加了一条数据,Name字段值是“newtype one”,看看我们修改字段长度后,字段值是否发生变化?

  2,在程序包管理器控制台输入“Enable-Migrations”命令来启用迁移,运行完成后在项目中会创建一个Migrations文件夹,下来有两类文件:

  • Configuration.cs — 此文件包含“迁移”将用来迁移 BloggingContext 的设置。在本演练中不需要进行任何更改,但是,在此处可以指定种子数据、为其他数据库注册提供程序、更改生成迁移的命名空间等。
  • <时间戳>_InitialCreate.cs — 这是第一个迁移,它表示已经应用于数据库的更改。应用更改的目的是将其从空数据库迁移至包含博客和文章表的数据库。尽管我们让 Code First 自动创建这些表,现在我们选择“迁移”(已转化为一次“迁移”)。Code First 还在本地数据库中记录:该“迁移”已经应用。文件名中的时间戳用于排序。

  需要注意的是:在我们生成数据库的时候,除了New和NewType表外,还有一个系统生成表__MigrationHistory,从表名上就可以看出是迁移历史记录表。

  3,程序包管理器控制台输入“Add-Migration Update-NewType-Name”命令,Add-Migration表示增加一个迁移,后面是迁移名称,这个我们可以随便写,运行后会自动检测模型和数据库发生的变化,在Migrations文件夹下会生成一个“201403290930423_Update-NewType-Name.cs”文件,打开我们可以看到更新内容:

复制代码
 1     public partial class UpdateNewTypeName : DbMigration 2     { 3         public override void Up() 4         { 5             AlterColumn("dbo.NewTypes", "Name", c => c.String(maxLength: 50)); 6         } 7          8         public override void Down() 9         {10             AlterColumn("dbo.NewTypes", "Name", c => c.String());11         }12     }
复制代码

  从上面可以看出就是我们上面修改模型的内容,当然你也可以在这上面直接修改,比如你再加一个更新,可以一起提交到数据库。

  4,程序包管理器控制台输入“Update-Database”命令,表示将所有的迁移应用到数据库,打开数据库,我们看一下效果:

  从上面可以看出,字段Name的类型已经修改为nvarchar(50),而且字段值并没有发生变化,可以证明,Code First迁移并不是删除数据库再创建。

  Code First迁移除了上面说的字段类型修改还有很多内容,比如添加字段,删除字段,删除表等等,但都是大同小异,可以举一反三。

示例Demo下载

  下载地址:http://pan.baidu.com/s/1i3DS9b3












================================================================================

二、


一、前言

      前文中介绍了ModelFirst,他是先自己做好实体模型,然后生成数据库。现在小编给大家再介绍一种——CodeFirst,代码优先。

二、内容介绍

      Code First 这种方式需要先写一些代码,如实体对象,数据关系等,然后根据已有的代码描述,自动创建数据对象。但其实这种方法与Model First是非常类似的。我们自己写的代码,其实就是用代码表示实体模型,而Model First是用可视化的方式描述了实体模型。 
      下面通过实战演练来展示:

三、实战演练

打开VS2012 ,建立一个控制台应用程序:

这里写图片描述
这里写图片描述

                                                    图一 控制台应用程序

使用这种方式前提是要有EF的引用:右击引用,选择“管理Nuget程序包”,打开对话框。

这里写图片描述

                                                    图二 添加EF引用                                               

选择联机搜索,输入EntityFramework,搜索出来后,点击安装。

这里写图片描述

                                                    图三 添加EF引用                                                                                       

安装完后的效果:

这里写图片描述

                                                    图四 安装完后的效果      

这样我们的前期准备工作就结束了,接下来就是代码编写的部分:

首选我们创按两个类:User、Card。

User实体类:

/********************************************************************* * 作者:王雷 * 小组:暂无 * 说明:用户表类 * 创建日期:201651814:41:18 * 版本号:V1.0.0 ************************************************************************/using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.ComponentModel.DataAnnotations;namespace EFCodeFirst{    public class User    {        [Key]        public int Id { get; set; }        public string Name { get; set; }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Card实体类:

/********************************************************************* * 作者:王雷 * 小组:暂无 * 说明:卡实体类 * 创建日期:201651814:41:21 * 版本号:V1.0.0 ************************************************************************/using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.ComponentModel.DataAnnotations;namespace EFCodeFirst{    public class Card    {        [Key]        public int Id { get; set; }        public string CardName { get; set; }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

接着我们创建上下文类:CodeFirstContext,它继承于DbContext类。写一下这个类的构造函数,将Value传进去,Value就是配置文件中链接数据库的代码以及一个关于驱动的代码,要注意其中的对应关系,最后把实体放到集合就可以了。

/********************************************************************* * 作者:王雷 * 小组:暂无 * 说明:上下文 * 创建日期:201651815:06:49 * 版本号:V1.0.0 ************************************************************************/using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EFCodeFirst{    public class CodeFirstContext : DbContext    {        //构造函数        public CodeFirstContext()            : base("name = DEMO")        {         }        public DbSet<User> User { get; set; }        public DbSet<Card> Card { get; set; }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

配置文件代码如下:

<?xml version="1.0" encoding="utf-8"?><configuration>  <configSections>    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />  </configSections>  <startup>    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />  </startup>  <entityFramework>    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">      <parameters>        <parameter value="v11.0" />      </parameters>    </defaultConnectionFactory>    <providers>      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />    </providers>  </entityFramework>  <!--这是自己添加的代码-->  <connectionStrings>    <add name="DEMO" connectionString="Data Source=.;Initial Catalog=EFCodeFirst;Integrated Security=True;" providerName="System.Data.SqlClient"/>  </connectionStrings></configuration>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

主函数中创建一个数据库,添加数据,测试成果:

using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EFCodeFirst{    class Program    {        static void Main(string[] args)        {            //创建上下文            CodeFirstContext dbcontext = new CodeFirstContext();            //创建数据库            dbcontext.Database.CreateIfNotExists();            //创建表,并将字段加入进去            User u = new User();            u.Name = "wang";            u.Id = 1;            Card c = new Card();            c.CardName = "lei";            c.Id = 1;            //将实体赋予上下文,并添加到表里            dbcontext.User.Add(u);            //保存            dbcontext.SaveChanges();            Console.WriteLine("成功创建数据库和表");            Console.ReadKey();        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

执行程序,结果如下:

这里写图片描述

                                                    图五 结果如下

生成的数据库:

这里写图片描述

                                                    图六 生成的数据库

四、小结

      建立一个控制台项目。通过Nuget来获取Entity Framework。可以看出微软为我们建立的底层的框架还是蛮有用的,非常方便。希望小编的对这几种方式能对您有所启发。到这里为止呢~小编就为大家介绍完了EF的三种情况,在后面的博客中会给大家介绍一下在使用EF映射中会出现的问题。敬请期待~~


原创粉丝点击