本视频和分步演练介绍通过 Code First 开发建立新数据库。这个方案包括建立不存在的数据库(Code First 创建)或者空数据库(Code First 向它添加新表)。借助 Code First,可以使用 C# 或 VB.Net 类定义模型。可以选择使用类的特性和属性执行其他配置,也可以使用 Fluent API 执行其他配置。
简单起见,我们将构建一个使用 Code First 执行数据访问的基本控制台应用程序。
我们使用类来定义一个非常简单的模型。在 Program.cs 文件中进行定义,但是实际应用程序中,可能会将类分为若干个单独的文件,可能作为单独的项目。
在 Program.cs 中的程序类定义下,添加以下两个类。
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)。这将启用实体框架的延迟加载功能。延迟加载意味着,尝试访问这些属性的内容时,将自动从数据库加载。
现在,可以定义派生上下文,用于表示数据库的一个会话,以便我们查询和保存数据。我们定义一个派生自 System.Data.Entity.DbContext 的上下文,并为模型中的每个类公开一个类型化 DbSet<TEntity>。
现在,开始使用来自实体框架的类型。因此,我们需要添加 EntityFramework NuGet 程序包。
在 Program.cs 顶部,为 System.Data.Entity 添加一个 using 语句。
using System.Data.Entity;
在 Program.cs 中的 Post 类下,添加以下派生上下文。
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
下面是 Program.cs 现在应包含内容的完整列表。
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; }
}
}
这是我们开始存储和检索数据所需的全部代码。显然,后台发生了许多事情。稍后,我们将进行了解。但是,首先让我们看看它是如何运行的。
实现 program.cs 中的 Main 方法,如下所示。这些代码为上下文创建一个新实例,然后使用该实例插入新博客。之后,它使用 LINQ 查询检索数据库中的所有博客(按标题的字母顺序进行排序)。
class Program
{
static void Main(string[] args)
{
using (var db = new BloggingContext())
{
// Create and save a new 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();
// Display all Blogs from the database
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 博客 All blogs in the database: ADO.NET 博客 Press any key to exit... |
按照约定,DbContext 已经创建了一个数据库。
这些仅仅是默认约定,除此之外,还有多种方式可更改 Code First 所用的数据库。有关更多信息,请参见DbContext 如何发现模型和数据库连接 主题。
可以在 Visual Studio 中使用服务器资源管理器连接至此数据库
现在,可以检查 Code First 已经创建的架构。
DbContext 通过查看我们定义的 DbSet 属性,了解模型包含哪些类。随后,它使用 Code First 约定的默认集来确定表和列的名称,确定数据类型,查找主键等。本演练稍后将介绍如何重写这些约定。
现在更改模型,当我们进行更改时,还需要更新数据库架构。为此,我们使用一个称为“Code First 迁移”(或简称“迁移”)的功能。
“迁移”是一组有序的步骤,描述如何升级(和降级)数据库架构。这些步骤(称为“迁移”)中的每个步骤均包含一些代码,用于描述要应用的更改。
第一步是为 BloggingContext 启用 Code First 迁移。
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; }
}
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");
}
}
}
新的 Url 列已添加至数据库中的 Blogs 表:
到目前为止,EF 发现了使用其默认约定的模型。但是,有时类不遵从约定,我们需要能够执行进一步配置。对此有两种方法;本节将介绍数据注释,下一节将介绍 Fluent API。
public class User
{
public string Username { get; set; }
public string DisplayName { get; set; }
}
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public DbSet<User> Users { get; set; }
}
using System.ComponentModel.DataAnnotations;
public class User
{
[Key]
public string Username { get; set; }
public string DisplayName { get; set; }
}
现在,新表已添加至数据库:
EF 支持的完整注释列表为:
上一节介绍了如何使用数据注释来补充或重写按约定检测的内容。另一种模型配置方法是通过 Code First Fluent API。
大多数模型配置都可使用简单数据注释进行。Fluent API 是一种更高级的方法,除某些数据注释不可能支持的更高级配置外,可以指定包含数据注释所有功能的模型配置。数据注释和 Fluent API 可一起使用。
要访问 Fluent API,需要在 DbContext 中重写 OnModelCreating 方法。假设我们需要重命名 User.DisplayName 存储至 display_name 的列。
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");
}
}
DisplayName 列现在重命名为 display_name:
本演练介绍了如何使用新数据库进行 Code First 开发。我们用类定义一个模型,然后使用该模型创建一个数据库,然后存储和检索数据。数据库创建之后,我们使用 Code First 迁移将架构更改为我们发展后的模型。此外还介绍了如何使用数据注释和 Fluent API 来配置模型。