在Entity Framework 中用 Code First 创建新的数据库 (原文链接

本文将逐步介绍怎样用Code First 创建新数据库,使用在代码中定义类和API中提供的特性(Attribute)的方式来流畅地创建数据模型到新数据库或已经存在的空数据库。

1. 新建应用程序()

为了简单起见,我们将新建一个使用Code First执行数据访问的控制台应用程序。

  • 打开VS
  • 新建项目为 控制台应用程序

2. 新建数据模型

我们先新建两个简单的实体类. 参考代码如下:

```
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; } public virtual List<Post- Posts { get; set; }
} public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; } public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
```

您会注意到,我们将两个导航属性(Blog.Posts和Post.Blog)定义为虚属性(关键字virtual)。 这种定义实现了EF框架的延迟加载功能。
延迟加载的意思是当你尝试访问这些属性时,这些属性的内容将自动从数据库加载。

3. 创建一个 DbContext

现在定义一个新的数据库上下文(DbContext),它继承自System.Data.Entity.DbContext,并为我们的模型中的每个类在这个DbContext中定义一个强类型的DbSet <TEntity>,比如: public DbSet<Post> Posts{get;set;}
DbContext代表与数据库的会话,我们可以通过DbContext查询和保存数据。

在此之前,我们要通过 NuGet 安装 EntityFramework.

  • 项目中右键选择NuGet包管理器。点击链接可以下载最新版的Nuget管理器 最新版本的NuGet.
  • 选择联机标签
  • 搜索 EntityFramework
  • 点击 安装Install

引用命名空间:

using System.Data.Entity;

在你新定义的 BloggingContext 中定义强类型DbSet,代码如下:

public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}

下文是完整的代码.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity; namespace CodeFirstNewDatabaseSample
{
class Program
{
static void Main(string[] args)
{
}
} public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; } public virtual List<Post- Posts { get; set; }
} public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; } public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
} public class BloggingContext : DbContext
{
public DbSet<Blog- Blogs { get; set; }
public DbSet<Post- Posts { get; set; }
}
}

这就是开始存储和检索数据所需的所有代码。 显然,幕后还有很多事情,这个我们稍后再来看看,首先让我们继续往下看。

4. 读取 & 写入数据

在 Program.cs 中实现如下文中的 Main 方法。
创建一个新的 DbContext的对象实例,再用它去插入一个新的Blog对象到数据库.再用Linq to Sql 从数据库中查询所有的Blogs,并按 Name 属性排序。
在此过程中你完全感觉不到你在操作数据库,是的,你就是在操作面向对象语言,EF帮你实现了与数据库的所有交互。

class Program
{
static void Main(string[] args)
{
using (var db = new BloggingContext())
{
// 创建一个新的需要保存到数据库的Blog对象
Console.Write("Enter a name for a new Blog: ");
var name = Console.ReadLine(); var blog = new Blog { Name = name };
db.Blogs.Add(blog);
db.SaveChanges(); // 从数据库中查询所有的Blogs,并输出到控制台
var query = from b in db.Blogs
orderby b.Name
select b; Console.WriteLine("All blogs in the database:");
foreach (var item in query)
{
Console.WriteLine(item.Name);
} Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}

现在你可以运行程序并查看它的输出了。输出结果如下:

Enter a name for a new Blog: ADO.NET Blog
All blogs in the database:
ADO.NET Blog
Press any key to exit...

好神奇,我的数据到底存储在哪里呢?

其实,DbContext帮你默认创建了一个数据库.

  • 在你安装VS2010及以上版本的时候,就会默认安装一个 Local Sql Express的数据库实例(它的连接方式:.\sqlexpress),默认情况下(没有指定DbConnectionString的情况下)Code First就是将数据库创建在这里(你可以在配置文件中指定ConnectionString,来控制Code First将数据库创建在哪里)

  • 当默认的 SQL Express 不能用或访问不到时,Code First就会尝试使用另一个实例LocalDb(它默认会在安装VS2012及以上版本时安装)

  • 在默认情况下,Code First会按照你定义的DbContext的完整限定名来创建数据库,如 CodeFirstNewDatabaseSample.BloggingContext

有关更详细情况你可以查看这篇文章 How DbContext Discovers the Model and Database Connection

5.处理数据变更

现在是时候对我们的模型进行一些更改,当我们进行这些更改时,我们还需要同步更新数据库结构。
为此,我们将使用一个名为Code First Migrations的功能,或简称为Migrations

首先,为我们定义的BloggingContext启用Code First Migrations.

  • 工具 -> NuGet管理器 -> 程序包控制台

  • 选择你定义的DbContext(BloggingContext)所在的项目/工程(Project)为默认项目

  • 输入命令: Enable-Migrations

  • 程序包控制台会在DbContext所在项目自动为我们生成一个名为Migrations的文件夹,并自动生成了两个文件:

    • Configuration.cs : 这个文件定义了Migrations将用于迁移BloggingContext的设置。一般情况下我们不需要为此做任何更改,但是您可以在此指定种子数据(数据库初始化数据).
    • <时间字符串>_InitialCreate.cs : 这里定义的是已经应用了到目前为止的数据库变更的第一次Migration,它将会在一个空的数据库中创建"Blogs"和Posts两个数据表。在这个Migration中,Code First将代码转换成了从对象模型到数据模型的迁移,并且,Code First还在数据库中记录了迁移版本,这些版本是以时间排序的。

现在我们往 Blog 类中添加一个 Url 属性:

public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public virtual List<Post> Posts { get; set; }
}
  • 程序包控制台输入命令 Add-Migration AddUrl,并执行. Add-Migration 命令会检查之前所有的迁移与现有实体模型之间的差异,将在从上一次迁移到现在的所有变更应用到本次迁移中(即生成到 yyyyMMdd…_AddUrl.cs文件中)。命令(Add-Migration AddUrl)中 ’AddUrl'是命令的参数,即指定迁移的命名为 ‘AddUrl’.生成的代码如下:
namespace CodeFirstNewDatabaseSample.Migrations
{
using System;
using System.Data.Entity.Migrations; public partial class AddUrl : DbMigration
{
public override void Up()
{
AddColumn("dbo.Blogs", "Url", c =- c.String());
} public override void Down()
{
DropColumn("dbo.Blogs", "Url");
}
}
}
  • 程序包控制台输入并执行命令 Update-Database.这个命令会将所有待更新的迁移更新到数据库。因为之前InitialCreate的迁移已经更新到数据库,所以这一次更新只会应用我们刚刚生成的```AddUrl``的迁移。

Tip: 你可以附加命令参数 -Verbose 用于查看将要执行的更新的SQL脚本

6. 数据模型标识(对于’Data Annotations'这个词的翻译我个人认为是数据模型标识,如果有更好的翻译,请帮忙指正,谢谢)

到目前为止,我们只是依赖EF的默认命名约定来定义模型,但是对于有一些场景我们无法去遵循这个约定,这个时候我们就要进行进一步的配置了。关于这部分的知识,可以在本文中查看数据模型标识的相关Attribute支持,在下一部分中会有详细介绍.

  • 我们添加一个新的实体模型 User
public class User
{
public string Username { get; set; }
public string DisplayName { get; set; }
}
  • 当然,我们相应的也要在DbContext中添加一个User的强类型DbSet<User>
public class BloggingContext : DbContext
{
public DbSet<Blog- Blogs { get; set; }
public DbSet<Post- Posts { get; set; }
public DbSet<User- Users { get; set; }
}
  • 当我们尝试使用 Add-Migration ...命令去生成新的数据迁移时,会发现一个错误:“EntityType ‘User’ has no key defined, Define the key for this EntityType”, 即实体模型 'User’没有定义主键,请为实体模型’User’定义主键。 这是因为EF无法主动发现 UsernameUser的主键。
  • 这个时候我们就需要给UserUsername属性添加一个KeyAttribute的特性,用于告诉EF,我们将具备KeyAttribute特性的属性定义为模型的主键,即 Username.

引用命名空间如下:

using System.ComponentModel.DataAnnotations;
  • 现在我们用Key来标识Username为主键
public class User
{
[Key]
public string Username { get; set; }
public string DisplayName { get; set; }
}
  • 接下来,用add-migration AddUser命令来创建这些更新的迁移文件
  • 执行Update-Database命令,将迁移更新到数据库。

这个时候,我们发现数据库中已经创建好了新的数据表 Users

以下是EF提供的数据模型标识特性(Attribute)清单:

特性名 特性描述
KeyAttribute 用于指定实体的唯一标识,即主键
StringLengthAttribute 指定字段的最大字符数和最小字符数
MaxLengthAttribute 用于指定字段的最大长度
ConcurrencyCheckAttribute 指定属性参与乐观并发检查。
RequiredAttribute 标记为非空(必填)字段
TimestampAttribute 行版本类型 (也称为序列号) 是保证可在数据库中唯一一个二进制数字。 它不表示的实际时间。 行版本数据不是以可视方式有意义的。 因此,当 TimestampAttribute 属性用于动态数据字段,则将不显示列除非 ScaffoldColumnAttribute 列的属性显式设置为 true。
ComplexTypeAttribute 表示该类是复杂类型。 复杂类型是实体类型的非标量属性,实体类型允许在实体内组织标量属性。 复杂类型没有键,并且实体框架不能脱离父对象来管理复杂类型。
ColumnAttribute 表示属性将映射到的数据库列
TableAttribute 指定类将映射到的数据库表。
InversePropertyAttribute 指定表示同一关系的另一端的导航属性的反向属性。
ForeignKeyAttribute 外键标识
DatabaseGeneratedAttribute 指定数据库生成属性值的方式。一般用于指定标识列的生成方式
NotMappedAttribute 表示应从数据库映射中排除属性或类。

7. Fluent API

在上一节中我们研究了通过数据模型标识特性来补充或者覆盖默认情况下EF检测到的模型。那么,Fluent API其实还提供了另一种方法来配置模型

我们知道,大多数模型可通过简单的数据模型标识来完成定义或配置,但Code First提供了一种更先进的试来指定模型配置,即Fluent API,除了涵盖数据标识可以实现的所有操作外,还提供了一些数据模型标识所不可能实现的一些更高级配置方式。此外,数据模型标识和Fluent API这种高级配置方式是可以一起使用的。

我们可以通过Fluent API提供的支持在DbContext中重写OnModelCreating方法。我们一起来看一下,怎么样在更新数据模型时将在User实体中定义为 DisplayName 的属性在数据库中映射为字段名 display_name.

  • BloggingContext中重写OnModelCreating方法,代码如下:
public class BloggingContext : DbContext
{
public DbSet<Blog- Blogs { get; set; }
public DbSet<Post- Posts { get; set; }
public DbSet<User- Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User-()
.Property(u =- u.DisplayName)
.HasColumnName("display_name");
}
}
  • 程序包控制台 执行命令 Add-Migration ChangeDisplayName,生成对于此变更的新的迁移
  • 执行 Update-Database命令将此迁移更新到数据库

小结

  • 使用Code First 定义一个新的数据模型
  • 使用DbContext检索或存储数据
  • 将模型的变更通过数据迁移命令(Migrations)更新到数据库
  • 使用Fluent API配置模型

在Entity Framework 中用 Code First 创建新的数据库的更多相关文章

  1. 创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表

    创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表 创建数据模型类(POCO类) 在Models文件夹下添 ...

  2. Entity Framework 6 Code First创建

    基本上我是DB先设计好的,所以就按现存在的table去写程式. 1.Web.config里配置Db连接字串,Connection String Name为DefaultConnection <c ...

  3. Entity Framework 6 Code First新特性:支持存储过程

    Entity Framework 6提供支持存储过程的新特性,本文具体演示Entity Framework 6 Code First的存储过程操作. Code First的插入/修改/删除存储过程 默 ...

  4. Entity Framework Core Code First 项目实践

    Entity Framework Core Code First 实践 任何一种技术的出现都是为了解决一系列特定的问题,只有了解了技术所要解决的关键问题,才能理解它的真正用途,之后,才能在实践中用好它 ...

  5. Entity Framework 之 Code First

    使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First [前言] 如果是Code First老鸟或者对Entity Framework不感兴趣,就不用浪费 ...

  6. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

  7. AppBox升级进行时 - 拥抱Entity Framework的Code First开发模式

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 从Subsonic到Entity Framework Subsonic最早发布 ...

  8. MVC2、MVC3、MVC4、MVC5之间的区别 以及Entity Framework 6 Code First using MVC 5官方介绍教程

    现在MVC的技术日趋成熟,面对着不同版本的MVC大家不免有所迷惑 -- 它们之间有什么不同呢?下面我把我搜集的信息汇总一下,以便大家能更好的认识不同版本MVC的功能,也便于自己查阅. View Eng ...

  9. Entity Framework 6 Code First的简单使用和更新数据库结构

    一.安装Entity Framework 6 在项目中右击选择“管理NuGet程序包",联机搜索Entity Framework,点击安装 二.配置数据库连接 在App.config中加入数 ...

随机推荐

  1. 【Android Developers Training】 100. 使用Intent修改联系人数据

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  2. php 时间戳转化成天数 四舍五入 整数

    public function edit() { global $_W; global $_GPC; $openid=$_W['openid']; $boards = pdo_fetchall('se ...

  3. Centos 6.x 部署pptp VPN

    安装 系统检测不到PPTP的时候  使用一下方法安装PPTP 下载地址:http://poptop.sourceforge.net/yum/stable/packages rpm -ivh http: ...

  4. gulp 运用 的理解

    ugulp.task('build', function() { runSequence('clean', 'copy', ['uglify', 'sass', 'htmlmin'], 'base64 ...

  5. Linux网络配置及相关命令

    Linux的网络配置是曾一直是我学习Linux的埋骨之地,投入了大量的精力和心神让自己的虚拟机联网.后来发现,仅仅是一个大意,我在这个坑上一躺就是一年半.现在总结一下这个伤心地.希望对有帮助. VMw ...

  6. webpack教程(三)——热刷新

    现在我们如果修改代码,需要重新打包,再一次在命令行下输入webpack命令,很麻烦. 热刷新是什么呢?就是我们该完代码保存之后webpack会自动打包引起浏览器自动刷新,你只需要把精力都专注在代码研发 ...

  7. HTML RGB 颜色表 16进制表 颜色对应表

    HTML RGB 颜色表 16进制表 颜色对应表  16 常用颜色表(颜色 + RGB + 名字): Color Value Name   Color Value Name   #00FFFF aqu ...

  8. editPuls 常用知识

    1.创建模板 1).创建模板页(*.html) 2).Tools->Preferences->File->Templates->HTML->file name重新选定模板 ...

  9. [Hadoop源码系列] FairScheduler分配申请和分配container的过程

    1.如何申请资源 1.1 如何启动AM并申请资源 1.1.1 如何启动AM val yarnClient = YarnClient.createYarnClient setupCredentials( ...

  10. Excel导出百万级数据解决方案

    因项目业务,需要导出百万级数据到excel,在研究了各种方案后,最终确定了用POI的SXSSFWorkbook. SXSSFWorkbook是POI3.8以上新增的,excel2007后每个sheet ...