创建电影(Movie)表

要存储影片,我们需要一张电影(Movie)表。我们可以使用传统的方式创建该表,如使用 SQL Management Studio,但是我们更喜欢使用 Fluent Migrator 创建 迁移类(migration) 的方式创建表。

Fluent Migrator 是一个 .NET 迁移框架,它与 Ruby 的 Rails 迁移框架类似。迁移(Migrations)用结构化的方式改变数据库架构(database schema),替代创建大量必须通过开发人员手工运行的 sql 脚本。迁移解决由一个数据库架构演变为多个数据库的问题(例如,开发人员的本地数据库、测试数据库和生产数据库)。数据库架构的更改在一个类中使用 C# 描述,可以把该类签入到版本控制系统中。

关于 FluentMigrator 的更多信息,详见 https://github.com/schambers/fluentmigrator。

解决方案资源管理器 中导航到 Modules / Common / Migrations / DefaultDB

Initial Migration Folder

在这里,我们已经有几个迁移类。一个迁移类就像一个操纵数据库结构的 DML 脚本。

DefaultDB_20141103_140000_Initial.cs 为例,它包含创建 Northwind 表和 Users 表的初始迁移内容。

在同一文件夹中,创建一个名为 DefaultDB_20160519_115100_MovieTable.cs 的文件。你可以拷贝一个现有的迁移类文件,然后重命名并修改内容。

迁移类文件名称/类名其实不重要,但建议你保持一致性并且正确地排序。

20160519_115100 对应于我们编写迁移类的 yyyyMMdd_HHmmss 格式的时间。它还将作为此迁移的唯一标识。

我们的迁移类文件看起来应该像下面这样:

  1. using FluentMigrator;
  2. using System;
  3. namespace MovieTutorial.Migrations.DefaultDB
  4. {
  5. [Migration(20160519115100)]
  6. public class DefaultDB_20160519_115100_MovieTable : Migration
  7. {
  8. public override void Up()
  9. {
  10. Create.Schema("mov");
  11. Create.Table("Movie").InSchema("mov")
  12. .WithColumn("MovieId").AsInt32()
  13. .Identity().PrimaryKey().NotNullable()
  14. .WithColumn("Title").AsString(200).NotNullable()
  15. .WithColumn("Description").AsString(1000).Nullable()
  16. .WithColumn("Storyline").AsString(Int32.MaxValue).Nullable()
  17. .WithColumn("Year").AsInt32().Nullable()
  18. .WithColumn("ReleaseDate").AsDateTime().Nullable()
  19. .WithColumn("Runtime").AsInt32().Nullable();
  20. }
  21. public override void Down()
  22. {
  23. }
  24. }
  25. }

确保你使用的命名空间是 MovieTutorial.Migrations.DefaultDB,因为 Serene 模板仅在此命名空间下对默认数据库应用迁移。

Up() 方法中,当应用指定的迁移时,数据库将创建名为 mov 的 schema 。为避免与现有表发生冲突,我们为电影表使用一个独立的 schema。该方法将创建一个名为 Movie 的表,其字段有 “MovieId, Title, Description…”。

我们可以实现 Down() 方法,以便能够撤消这个迁移(删除电影表和 schema (mov) 等),但对于这个示例,我们让它空着。

不能撤消迁移可能并没有太大影响,但误删除表便会造成更大的损害。

在类的顶部,我们使用 Migration 特性。

  1. [Migration(20160519115100)]

这里指定此迁移的唯一键。迁移应用到数据库后,在一个特定于 FluentMigrator([dbo].[VersionInfo]) 的特殊表中记录该值,因此同一迁移不会被再次应用。

迁移的唯一健应该与类名同步(保持一致),但没有强调迁移唯一键必须是 Int64 编号。

迁移是按唯一键顺序执行的,所以迁移的唯一键要使用一个可排序的日期时间模式,如把 yyyyMMdd 作为迁移唯一键就是个好主意。

请确保你始终使用相同数量的字符作为迁移的唯一键,如 14位 (20160519115100)。否则你的迁移命令会一团糟,由于使用混乱的顺序迁移,因此你会得到迁移错误。

执行迁移

默认情况下,Serene 模板将在应用程序启动时自动运行 MovieTutorial.Migrations.DefaultDB 命名空间下的所有迁移。运行迁移代码的是文件 App_Start/SiteInitialization.csApp_Start/SiteInitialization.Migrations.cs

SiteInitialization.Migrations.cs:

  1. namespace MovieTutorial
  2. {
  3. //...
  4. public static partial class SiteInitialization
  5. {
  6. private static string[] databaseKeys = new[] { "Default", "Northwind" };
  7. //...
  8. private static void EnsureDatabase(string databaseKey)
  9. {
  10. //...
  11. }
  12. public static bool SkippedMigrations { get; private set; }
  13. private static void RunMigrations(string databaseKey)
  14. {
  15. // ...
  16. // safety check to ensure that we are not modifying an
  17. // arbitrary database. remove these two lines if you want
  18. // MovieTutorial migrations to run on your DB.
  19. if (cs.ConnectionString.IndexOf(typeof(SiteInitialization).Namespace +
  20. @"_" + databaseKey + "_v1",
  21. StringComparison.OrdinalIgnoreCase) < 0)
  22. {
  23. SkippedMigrations = true;
  24. return;
  25. }
  26. // ...
  27. using (var sw = new StringWriter())
  28. {
  29. // ...
  30. var runner = new RunnerContext(announcer)
  31. {
  32. Database = databaseType,
  33. Connection = cs.ConnectionString,
  34. Targets = new string[] {
  35. typeof(SiteInitialization).Assembly.Location },
  36. Task = "migrate:up",
  37. WorkingDirectory = Path.GetDirectoryName(
  38. typeof(SiteInitialization).Assembly.Location),
  39. Namespace = "MovieTutorial.Migrations." + databaseKey + "DB"
  40. };
  41. new TaskExecutor(runner).Execute();
  42. }
  43. }
  44. }
  45. }

这里有对数据库名称进行安全性检查,以避免在 Serene 默认数据库 (MovieTutorial_Default_v1) 之外的其他数据库上运行迁移。如果你了解其中的风险,可以删除此检查。例如,如果你把 web.config 中的默认连接更改为你自己的生产数据库,迁移将在生产数据库上运行,你将得到 Northwind 等表,即使之前你的生产数据库没有这些表。

现在按 F5 运行应用程序并在默认数据库中创建电影表。

确认迁移类已经运行

使用 Sql Server Management Studio 或 Visual Studio -> Connection To Database,打开数据库 MovieTutorial_Default_v1 database in server (localdb)\v11.0 的连接。

(localdb)\v11.0 是 SQL Server 2012 LocalDB 创建的 LocalDB 实例。

如果你还没有安装 LocalDB ,可从 https://www.microsoft.com/en-us/download/details.aspx?id=29062 下载。

如果你有 SQL Server 2014 LocalDB,你的服务器名(server name)应该变为 (localdb)\MSSqlLocalDB 或者 (localdb)\v12.0,所以你应该修改 web.config 文件的连接字符串。

你也可以使用另外一个 SQL server 实例,只需把连接字符串配置为目标服务器,并删除迁移的安全检查。

你应该在 SQL 对象资源管理器中看到 [mov].[Movies] 表。

同样地,当你查看 [dbo].[VersionInfo] 表数据时,最后一行的 Version 列应为 20160519115100。它表明已经在此数据库执行该版本(迁移唯一键)的迁移。

Initial Migration Folder

通常,你不必在每一个迁移后都做这些检查。在这里,我们只是演示如果你将来遇到迁移问题,你应该在到哪里去检查。