使用数据库和 ASP.NET CoreWork with a database and ASP.NET Core

本文内容

作者:Rick AndersonJoe Audette

查看或下载示例代码如何下载)。

查看或下载示例代码如何下载)。

RazorPagesMovieContext 对象处理连接到数据库并将 Movie 对象映射到数据库记录的任务。在 Startup.cs 的 ConfigureServices 方法中向依赖关系注入容器注册数据库上下文:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddRazorPages();
  4. services.AddDbContext<RazorPagesMovieContext>(options =>
  5. options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
  6. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddRazorPages();
  4. services.AddDbContext<RazorPagesMovieContext>(options =>
  5. options.UseSqlite(Configuration.GetConnectionString("MovieContext")));
  6. }

ASP.NET Core 配置系统会读取 ConnectionString为了进行本地开发,它会从 appsettings.json 文件获取连接字符串 。

生成代码的数据库名称值 (Database={Database name}) 将并不不同。名称值是任意的。

  1. {
  2. "Logging": {
  3. "LogLevel": {
  4. "Default": "Information",
  5. "Microsoft": "Warning",
  6. "Microsoft.Hosting.Lifetime": "Information"
  7. }
  8. },
  9. "AllowedHosts": "*",
  10. "ConnectionStrings": {
  11. "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
  12. }
  13. }
  1. {
  2. "Logging": {
  3. "LogLevel": {
  4. "Default": "Warning"
  5. }
  6. },
  7. "AllowedHosts": "*",
  8. "ConnectionStrings": {
  9. "MovieContext": "Data Source=MvcMovie.db"
  10. }
  11. }

将应用部署到测试或生产服务器时,可以使用环境变量将连接字符串设置为实际的数据库服务器。有关详细信息,请参阅配置

SQL Server Express LocalDBSQL Server Express LocalDB

LocalDB 是轻型版的 SQL Server Express 数据库引擎,以程序开发为目标。LocalDB 作为按需启动并在用户模式下运行的轻量级数据库没有复杂的配置。默认情况下,LocalDB 数据库在 C:\Users\<user>\ 目录下创建 *.mdf 文件。

  • 从“视图”菜单中,打开“SQL Server 对象资源管理器”(SSOX) 。

“视图”菜单

  • 右键单击 Movie 表,然后选择“视图设计器” :

Movie 表上打开的上下文菜单

设计器中打开的 Movie 表

请注意 ID 旁边的密钥图标。默认情况下,EF 为该主键创建一个名为 ID 的属性。

  • 右键单击 Movie 表,然后选择“查看数据” :

显示表数据的打开的 Movie 表

SQLiteSQLite

SQLite 网站上表示:


SQLite 是一个自包含、高可靠性、嵌入式、功能完整、公共域的 SQL 数据库引擎。 SQLite 是世界上使用最多的数据库引擎。


可以下载许多第三方工具来管理并查看 SQLite 数据库。下面的图片来自 DB Browser for SQLite如果你有最喜欢的 SQLite 工具,请发表评论以分享你喜欢的方面。

显示电影数据库的 DB Browser for SQLite

备注

在本教程中,使用 Entity Framework Core 迁移功能(若可行)。迁移会更新数据库架构,使其与数据模型中的更改相匹配。但是,迁移仅能执行 EF Core 提供程序所支持的更改类型,且 SQLite 提供程序的功能将受限。例如,支持添加列,但不支持删除或更改列。如果已创建迁移以删除或更改列,则 ef migrations add 命令将成功,但 ef database update 命令会失败。由于上述限制,本教程不对 SQLite 架构更改使用迁移。转而在架构更改时,放弃并重新创建数据库。

要绕开 SQLite 限制,可手动写入迁移代码,在表内容更改时重新生成表。表重新生成涉及:

  • 创建新表。
  • 将旧表中的数据复制到新表中。
  • 放弃旧表。
  • 为新表重命名。

有关更多信息,请参见以下资源:

设定数据库种子Seed the database

使用以下代码在 Models 文件夹中创建一个名为 SeedData 的新类:

  1. using Microsoft.EntityFrameworkCore;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using RazorPagesMovie.Data;
  4. using System;
  5. using System.Linq;
  6. namespace RazorPagesMovie.Models
  7. {
  8. public static class SeedData
  9. {
  10. public static void Initialize(IServiceProvider serviceProvider)
  11. {
  12. using (var context = new RazorPagesMovieContext(
  13. serviceProvider.GetRequiredService<
  14. DbContextOptions<RazorPagesMovieContext>>()))
  15. {
  16. // Look for any movies.
  17. if (context.Movie.Any())
  18. {
  19. return; // DB has been seeded
  20. }
  21. context.Movie.AddRange(
  22. new Movie
  23. {
  24. Title = "When Harry Met Sally",
  25. ReleaseDate = DateTime.Parse("1989-2-12"),
  26. Genre = "Romantic Comedy",
  27. Price = 7.99M
  28. },
  29. new Movie
  30. {
  31. Title = "Ghostbusters ",
  32. ReleaseDate = DateTime.Parse("1984-3-13"),
  33. Genre = "Comedy",
  34. Price = 8.99M
  35. },
  36. new Movie
  37. {
  38. Title = "Ghostbusters 2",
  39. ReleaseDate = DateTime.Parse("1986-2-23"),
  40. Genre = "Comedy",
  41. Price = 9.99M
  42. },
  43. new Movie
  44. {
  45. Title = "Rio Bravo",
  46. ReleaseDate = DateTime.Parse("1959-4-15"),
  47. Genre = "Western",
  48. Price = 3.99M
  49. }
  50. );
  51. context.SaveChanges();
  52. }
  53. }
  54. }
  55. }

如果 DB 中有任何电影,则会返回种子初始值设定项,并且不会添加任何电影。

  1. if (context.Movie.Any())
  2. {
  3. return; // DB has been seeded.
  4. }

添加种子初始值设定项Add the seed initializer

在 Program.cs 中,修改 Main 方法以执行以下操作 :

  • 从依赖关系注入容器获取数据库上下文实例。
  • 调用 seed 方法,并将上下文传递给它。
  • Seed 方法完成时释放上下文。

下面的代码显示更新后的 Program.cs 文件。

  1. using Microsoft.AspNetCore.Hosting;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using Microsoft.Extensions.Hosting;
  4. using Microsoft.Extensions.Logging;
  5. using RazorPagesMovie.Models;
  6. using System;
  7. namespace RazorPagesMovie
  8. {
  9. public class Program
  10. {
  11. public static void Main(string[] args)
  12. {
  13. var host = CreateHostBuilder(args).Build();
  14. using (var scope = host.Services.CreateScope())
  15. {
  16. var services = scope.ServiceProvider;
  17. try
  18. {
  19. SeedData.Initialize(services);
  20. }
  21. catch (Exception ex)
  22. {
  23. var logger = services.GetRequiredService<ILogger<Program>>();
  24. logger.LogError(ex, "An error occurred seeding the DB.");
  25. }
  26. }
  27. host.Run();
  28. }
  29. public static IHostBuilder CreateHostBuilder(string[] args) =>
  30. Host.CreateDefaultBuilder(args)
  31. .ConfigureWebHostDefaults(webBuilder =>
  32. {
  33. webBuilder.UseStartup<Startup>();
  34. });
  35. }
  36. }

未运行 Update-Database 时出现以下异常:


SqlException: Cannot open database "RazorPagesMovieContext-" requested by the login. The login failed.
Login failed for user 'user name'.


测试应用Test the app

  • 删除 DB 中的所有记录。可以使用浏览器中的删除链接,也可以从 SSOX 执行此操作

  • 强制应用初始化(调用 Startup 类中的方法),使种子方法能够正常运行。若要强制进行初始化,必须先停止 IIS Express,然后再重新启动它。可以使用以下任一方法来执行此操作:

    • 右键单击通知区域中的 IIS Express 系统任务栏图标,然后点击“退出”或“停止站点” :

IIS Express 系统任务栏图标

上下文菜单

  1. - 如果是在非调试模式下运行 VS 的,请按 F5 以在调试模式下运行。
  2. - 如果是在调试模式下运行 VS 的,请停止调试程序并按 F5

删除 DB 中的所有记录(使种子方法运行)。停止并启动应用以设定数据库种子。

应用将显示设定为种子的数据。

在下一教程中将对数据的展示进行改进。

其他资源Additional resources

上一篇:已搭建基架的 Razor Pages下一篇:更新页面

查看或下载示例代码如何下载)。

查看或下载示例代码如何下载)。

RazorPagesMovieContext 对象处理连接到数据库并将 Movie 对象映射到数据库记录的任务。在 Startup.cs 的 ConfigureServices 方法中向依赖关系注入容器注册数据库上下文:

  1. // This method gets called by the runtime.
  2. // Use this method to add services to the container.
  3. public void ConfigureServices(IServiceCollection services)
  4. {
  5. services.Configure<CookiePolicyOptions>(options =>
  6. {
  7. // This lambda determines whether user consent for non-essential cookies is
  8. // needed for a given request.
  9. options.CheckConsentNeeded = context => true;
  10. options.MinimumSameSitePolicy = SameSiteMode.None;
  11. });
  12. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  13. services.AddDbContext<RazorPagesMovieContext>(options =>
  14. options.UseSqlServer(
  15. Configuration.GetConnectionString("RazorPagesMovieContext")));
  16. }
  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.Configure<CookiePolicyOptions>(options =>
  4. {
  5. // This lambda determines whether user consent for
  6. // non-essential cookies is needed for a given request.
  7. options.CheckConsentNeeded = context => true;
  8. options.MinimumSameSitePolicy = SameSiteMode.None;
  9. });
  10. services.AddDbContext<RazorPagesMovieContext>(options =>
  11. options.UseSqlite(Configuration.GetConnectionString("MovieContext")));
  12. services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
  13. }

有关 ConfigureServices 中使用的方法的详细信息,请参阅:

ASP.NET Core 配置系统会读取 ConnectionString为了进行本地开发,它会从 appsettings.json 文件获取连接字符串 。

生成代码的数据库名称值 (Database={Database name}) 将并不不同。名称值是任意的。

  1. {
  2. "Logging": {
  3. "LogLevel": {
  4. "Default": "Warning"
  5. }
  6. },
  7. "AllowedHosts": "*",
  8. "ConnectionStrings": {
  9. "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-1234;Trusted_Connection=True;MultipleActiveResultSets=true"
  10. }
  11. }
  1. {
  2. "Logging": {
  3. "LogLevel": {
  4. "Default": "Warning"
  5. }
  6. },
  7. "AllowedHosts": "*",
  8. "ConnectionStrings": {
  9. "MovieContext": "Data Source=MvcMovie.db"
  10. }
  11. }
  1. {
  2. "Logging": {
  3. "LogLevel": {
  4. "Default": "Warning"
  5. }
  6. },
  7. "AllowedHosts": "*",
  8. "ConnectionStrings": {
  9. "MovieContext": "Data Source=MvcMovie.db"
  10. }
  11. }

将应用部署到测试或生产服务器时,可以使用环境变量将连接字符串设置为实际的数据库服务器。有关详细信息,请参阅配置

SQL Server Express LocalDBSQL Server Express LocalDB

LocalDB 是轻型版的 SQL Server Express 数据库引擎,以程序开发为目标。LocalDB 作为按需启动并在用户模式下运行的轻量级数据库没有复杂的配置。默认情况下,LocalDB 数据库在 C:/Users/<user/> 目录下创建 *.mdf 文件。

  • 从“视图”菜单中,打开“SQL Server 对象资源管理器”(SSOX) 。

“视图”菜单

  • 右键单击 Movie 表,然后选择“视图设计器” :

Movie 表上打开的上下文菜单

设计器中打开的 Movie 表

请注意 ID 旁边的密钥图标。默认情况下,EF 为该主键创建一个名为 ID 的属性。

  • 右键单击 Movie 表,然后选择“查看数据” :

显示表数据的打开的 Movie 表

SQLiteSQLite

SQLite 网站上表示:


SQLite 是一个自包含、高可靠性、嵌入式、功能完整、公共域的 SQL 数据库引擎。 SQLite 是世界上使用最多的数据库引擎。


可以下载许多第三方工具来管理并查看 SQLite 数据库。下面的图片来自 DB Browser for SQLite如果你有最喜欢的 SQLite 工具,请发表评论以分享你喜欢的方面。

显示电影数据库的 DB Browser for SQLite

备注

在本教程中,使用 Entity Framework Core 迁移功能(若可行)。迁移会更新数据库架构,使其与数据模型中的更改相匹配。但是,迁移仅能执行 EF Core 提供程序所支持的更改类型,且 SQLite 提供程序的功能将受限。例如,支持添加列,但不支持删除或更改列。如果已创建迁移以删除或更改列,则 ef migrations add 命令将成功,但 ef database update 命令会失败。由于上述限制,本教程不对 SQLite 架构更改使用迁移。转而在架构更改时,放弃并重新创建数据库。

要绕开 SQLite 限制,可手动写入迁移代码,在表内容更改时重新生成表。表重新生成涉及:

  • 创建新表。
  • 将旧表中的数据复制到新表中。
  • 放弃旧表。
  • 为新表重命名。

有关更多信息,请参见以下资源:

SQLiteSQLite

SQLite 网站上表示:


SQLite 是一个自包含、高可靠性、嵌入式、功能完整、公共域的 SQL 数据库引擎。 SQLite 是世界上使用最多的数据库引擎。


可以下载许多第三方工具来管理并查看 SQLite 数据库。下面的图片来自 DB Browser for SQLite如果你有最喜欢的 SQLite 工具,请发表评论以分享你喜欢的方面。

显示电影数据库的 DB Browser for SQLite

备注

在本教程中,使用 Entity Framework Core 迁移功能(若可行)。迁移会更新数据库架构,使其与数据模型中的更改相匹配。但是,迁移仅能执行 EF Core 提供程序所支持的更改类型,且 SQLite 提供程序的功能将受限。例如,支持添加列,但不支持删除或更改列。如果已创建迁移以删除或更改列,则 ef migrations add 命令将成功,但 ef database update 命令会失败。由于上述限制,本教程不对 SQLite 架构更改使用迁移。转而在架构更改时,放弃并重新创建数据库。

要绕开 SQLite 限制,可手动写入迁移代码,在表内容更改时重新生成表。表重新生成涉及:

  • 创建新表。
  • 将旧表中的数据复制到新表中。
  • 放弃旧表。
  • 为新表重命名。

有关更多信息,请参见以下资源:

设定数据库种子Seed the database

使用以下代码在 Models 文件夹中创建一个名为 SeedData 的新类:

  1. using Microsoft.EntityFrameworkCore;
  2. using Microsoft.Extensions.DependencyInjection;
  3. using System;
  4. using System.Linq;
  5. namespace RazorPagesMovie.Models
  6. {
  7. public static class SeedData
  8. {
  9. public static void Initialize(IServiceProvider serviceProvider)
  10. {
  11. using (var context = new RazorPagesMovieContext(
  12. serviceProvider.GetRequiredService<
  13. DbContextOptions<RazorPagesMovieContext>>()))
  14. {
  15. // Look for any movies.
  16. if (context.Movie.Any())
  17. {
  18. return; // DB has been seeded
  19. }
  20. context.Movie.AddRange(
  21. new Movie
  22. {
  23. Title = "When Harry Met Sally",
  24. ReleaseDate = DateTime.Parse("1989-2-12"),
  25. Genre = "Romantic Comedy",
  26. Price = 7.99M
  27. },
  28. new Movie
  29. {
  30. Title = "Ghostbusters ",
  31. ReleaseDate = DateTime.Parse("1984-3-13"),
  32. Genre = "Comedy",
  33. Price = 8.99M
  34. },
  35. new Movie
  36. {
  37. Title = "Ghostbusters 2",
  38. ReleaseDate = DateTime.Parse("1986-2-23"),
  39. Genre = "Comedy",
  40. Price = 9.99M
  41. },
  42. new Movie
  43. {
  44. Title = "Rio Bravo",
  45. ReleaseDate = DateTime.Parse("1959-4-15"),
  46. Genre = "Western",
  47. Price = 3.99M
  48. }
  49. );
  50. context.SaveChanges();
  51. }
  52. }
  53. }
  54. }

如果 DB 中有任何电影,则会返回种子初始值设定项,并且不会添加任何电影。

  1. if (context.Movie.Any())
  2. {
  3. return; // DB has been seeded.
  4. }

添加种子初始值设定项Add the seed initializer

在 Program.cs 中,修改 Main 方法以执行以下操作 :

  • 从依赖关系注入容器获取数据库上下文实例。
  • 调用 seed 方法,并将上下文传递给它。
  • Seed 方法完成时释放上下文。

下面的代码显示更新后的 Program.cs 文件。

  1. using Microsoft.AspNetCore;
  2. using Microsoft.AspNetCore.Hosting;
  3. using Microsoft.Extensions.DependencyInjection;
  4. using Microsoft.Extensions.Logging;
  5. using RazorPagesMovie.Models;
  6. using System;
  7. using Microsoft.EntityFrameworkCore;
  8. namespace RazorPagesMovie
  9. {
  10. public class Program
  11. {
  12. public static void Main(string[] args)
  13. {
  14. var host = CreateWebHostBuilder(args).Build();
  15. using (var scope = host.Services.CreateScope())
  16. {
  17. var services = scope.ServiceProvider;
  18. try
  19. {
  20. var context=services.
  21. GetRequiredService<RazorPagesMovieContext>();
  22. context.Database.Migrate();
  23. SeedData.Initialize(services);
  24. }
  25. catch (Exception ex)
  26. {
  27. var logger = services.GetRequiredService<ILogger<Program>>();
  28. logger.LogError(ex, "An error occurred seeding the DB.");
  29. }
  30. }
  31. host.Run();
  32. }
  33. public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
  34. WebHost.CreateDefaultBuilder(args)
  35. .UseStartup<Startup>();
  36. }
  37. }

生产应用不会调用 Database.Migrate它会添加到上面的代码中,以防止在未运行 Update-Database 时出现以下异常:

SqlException:无法打开登录请求的数据库“RazorPagesMovieContext-21”。登录失败。用户“用户名”登录失败。

测试应用Test the app

  • 删除 DB 中的所有记录。可以使用浏览器中的删除链接,也可以从 SSOX 执行此操作

  • 强制应用初始化(调用 Startup 类中的方法),使种子方法能够正常运行。若要强制进行初始化,必须先停止 IIS Express,然后再重新启动它。可以使用以下任一方法来执行此操作:

    • 右键单击通知区域中的 IIS Express 系统任务栏图标,然后点击“退出”或“停止站点” :

IIS Express 系统任务栏图标

上下文菜单

  1. - 如果是在非调试模式下运行 VS 的,请按 F5 以在调试模式下运行。
  2. - 如果是在调试模式下运行 VS 的,请停止调试程序并按 F5

删除 DB 中的所有记录(使种子方法运行)。停止并启动应用以设定数据库种子。

应用将显示设定为种子的数据。

删除 DB 中的所有记录(使种子方法运行)。停止并启动应用以设定数据库种子。

应用将显示设定为种子的数据。

应用将显示设定为种子的数据:

在 Chrome 中打开的显示电影数据的电影应用程序

在下一教程中将对数据的展示进行整理。

其他资源Additional resources

上一篇:已搭建基架的 Razor Pages下一篇:更新页面