使用数据库和 ASP.NET CoreWork with a database and ASP.NET Core
本文内容
作者:Rick Anderson 和 Joe Audette
RazorPagesMovieContext
对象处理连接到数据库并将 Movie
对象映射到数据库记录的任务。在 Startup.cs 的 ConfigureServices
方法中向依赖关系注入容器注册数据库上下文:
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("MovieContext")));
}
ASP.NET Core 配置系统会读取 ConnectionString
。为了进行本地开发,它会从 appsettings.json 文件获取连接字符串 。
生成代码的数据库名称值 (Database={Database name}
) 将并不不同。名称值是任意的。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MovieContext": "Data Source=MvcMovie.db"
}
}
将应用部署到测试或生产服务器时,可以使用环境变量将连接字符串设置为实际的数据库服务器。有关详细信息,请参阅配置。
SQL Server Express LocalDBSQL Server Express LocalDB
LocalDB 是轻型版的 SQL Server Express 数据库引擎,以程序开发为目标。LocalDB 作为按需启动并在用户模式下运行的轻量级数据库没有复杂的配置。默认情况下,LocalDB 数据库在 C:\Users\<user>\
目录下创建 *.mdf
文件。
- 从“视图”菜单中,打开“SQL Server 对象资源管理器”(SSOX) 。
- 右键单击
Movie
表,然后选择“视图设计器” :
请注意 ID
旁边的密钥图标。默认情况下,EF 为该主键创建一个名为 ID
的属性。
- 右键单击
Movie
表,然后选择“查看数据” :
SQLiteSQLite
SQLite 网站上表示:
SQLite 是一个自包含、高可靠性、嵌入式、功能完整、公共域的 SQL 数据库引擎。 SQLite 是世界上使用最多的数据库引擎。
可以下载许多第三方工具来管理并查看 SQLite 数据库。下面的图片来自 DB Browser for SQLite。如果你有最喜欢的 SQLite 工具,请发表评论以分享你喜欢的方面。
备注
在本教程中,使用 Entity Framework Core 迁移功能(若可行)。迁移会更新数据库架构,使其与数据模型中的更改相匹配。但是,迁移仅能执行 EF Core 提供程序所支持的更改类型,且 SQLite 提供程序的功能将受限。例如,支持添加列,但不支持删除或更改列。如果已创建迁移以删除或更改列,则 ef migrations add
命令将成功,但 ef database update
命令会失败。由于上述限制,本教程不对 SQLite 架构更改使用迁移。转而在架构更改时,放弃并重新创建数据库。
要绕开 SQLite 限制,可手动写入迁移代码,在表内容更改时重新生成表。表重新生成涉及:
- 创建新表。
- 将旧表中的数据复制到新表中。
- 放弃旧表。
- 为新表重命名。
有关更多信息,请参见以下资源:
设定数据库种子Seed the database
使用以下代码在 Models 文件夹中创建一个名为 SeedData
的新类:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
using System;
using System.Linq;
namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},
new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},
new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}
如果 DB 中有任何电影,则会返回种子初始值设定项,并且不会添加任何电影。
if (context.Movie.Any())
{
return; // DB has been seeded.
}
添加种子初始值设定项Add the seed initializer
在 Program.cs 中,修改 Main
方法以执行以下操作 :
- 从依赖关系注入容器获取数据库上下文实例。
- 调用 seed 方法,并将上下文传递给它。
- Seed 方法完成时释放上下文。
下面的代码显示更新后的 Program.cs 文件。
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;
namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
未运行 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 系统任务栏图标,然后点击“退出”或“停止站点” :
- 如果是在非调试模式下运行 VS 的,请按 F5 以在调试模式下运行。
- 如果是在调试模式下运行 VS 的,请停止调试程序并按 F5。
删除 DB 中的所有记录(使种子方法运行)。停止并启动应用以设定数据库种子。
应用将显示设定为种子的数据。
在下一教程中将对数据的展示进行改进。
其他资源Additional resources
上一篇:已搭建基架的 Razor Pages下一篇:更新页面
RazorPagesMovieContext
对象处理连接到数据库并将 Movie
对象映射到数据库记录的任务。在 Startup.cs 的 ConfigureServices
方法中向依赖关系注入容器注册数据库上下文:
// This method gets called by the runtime.
// Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is
// needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("RazorPagesMovieContext")));
}
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for
// non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<RazorPagesMovieContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("MovieContext")));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}
有关 ConfigureServices
中使用的方法的详细信息,请参阅:
- 面向
CookiePolicyOptions
的 ASP.NET Core 中的欧盟一般数据保护条例 (GDPR) 支持。 - SetCompatibilityVersion
ASP.NET Core 配置系统会读取 ConnectionString
。为了进行本地开发,它会从 appsettings.json 文件获取连接字符串 。
生成代码的数据库名称值 (Database={Database name}
) 将并不不同。名称值是任意的。
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-1234;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MovieContext": "Data Source=MvcMovie.db"
}
}
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MovieContext": "Data Source=MvcMovie.db"
}
}
将应用部署到测试或生产服务器时,可以使用环境变量将连接字符串设置为实际的数据库服务器。有关详细信息,请参阅配置。
SQL Server Express LocalDBSQL Server Express LocalDB
LocalDB 是轻型版的 SQL Server Express 数据库引擎,以程序开发为目标。LocalDB 作为按需启动并在用户模式下运行的轻量级数据库没有复杂的配置。默认情况下,LocalDB 数据库在 C:/Users/<user/>
目录下创建 *.mdf
文件。
- 从“视图”菜单中,打开“SQL Server 对象资源管理器”(SSOX) 。
- 右键单击
Movie
表,然后选择“视图设计器” :
请注意 ID
旁边的密钥图标。默认情况下,EF 为该主键创建一个名为 ID
的属性。
- 右键单击
Movie
表,然后选择“查看数据” :
SQLiteSQLite
SQLite 网站上表示:
SQLite 是一个自包含、高可靠性、嵌入式、功能完整、公共域的 SQL 数据库引擎。 SQLite 是世界上使用最多的数据库引擎。
可以下载许多第三方工具来管理并查看 SQLite 数据库。下面的图片来自 DB Browser for SQLite。如果你有最喜欢的 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 工具,请发表评论以分享你喜欢的方面。
备注
在本教程中,使用 Entity Framework Core 迁移功能(若可行)。迁移会更新数据库架构,使其与数据模型中的更改相匹配。但是,迁移仅能执行 EF Core 提供程序所支持的更改类型,且 SQLite 提供程序的功能将受限。例如,支持添加列,但不支持删除或更改列。如果已创建迁移以删除或更改列,则 ef migrations add
命令将成功,但 ef database update
命令会失败。由于上述限制,本教程不对 SQLite 架构更改使用迁移。转而在架构更改时,放弃并重新创建数据库。
要绕开 SQLite 限制,可手动写入迁移代码,在表内容更改时重新生成表。表重新生成涉及:
- 创建新表。
- 将旧表中的数据复制到新表中。
- 放弃旧表。
- 为新表重命名。
有关更多信息,请参见以下资源:
设定数据库种子Seed the database
使用以下代码在 Models 文件夹中创建一个名为 SeedData
的新类:
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
namespace RazorPagesMovie.Models
{
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var context = new RazorPagesMovieContext(
serviceProvider.GetRequiredService<
DbContextOptions<RazorPagesMovieContext>>()))
{
// Look for any movies.
if (context.Movie.Any())
{
return; // DB has been seeded
}
context.Movie.AddRange(
new Movie
{
Title = "When Harry Met Sally",
ReleaseDate = DateTime.Parse("1989-2-12"),
Genre = "Romantic Comedy",
Price = 7.99M
},
new Movie
{
Title = "Ghostbusters ",
ReleaseDate = DateTime.Parse("1984-3-13"),
Genre = "Comedy",
Price = 8.99M
},
new Movie
{
Title = "Ghostbusters 2",
ReleaseDate = DateTime.Parse("1986-2-23"),
Genre = "Comedy",
Price = 9.99M
},
new Movie
{
Title = "Rio Bravo",
ReleaseDate = DateTime.Parse("1959-4-15"),
Genre = "Western",
Price = 3.99M
}
);
context.SaveChanges();
}
}
}
}
如果 DB 中有任何电影,则会返回种子初始值设定项,并且不会添加任何电影。
if (context.Movie.Any())
{
return; // DB has been seeded.
}
添加种子初始值设定项Add the seed initializer
在 Program.cs 中,修改 Main
方法以执行以下操作 :
- 从依赖关系注入容器获取数据库上下文实例。
- 调用 seed 方法,并将上下文传递给它。
- Seed 方法完成时释放上下文。
下面的代码显示更新后的 Program.cs 文件。
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RazorPagesMovie.Models;
using System;
using Microsoft.EntityFrameworkCore;
namespace RazorPagesMovie
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context=services.
GetRequiredService<RazorPagesMovieContext>();
context.Database.Migrate();
SeedData.Initialize(services);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
生产应用不会调用 Database.Migrate
。它会添加到上面的代码中,以防止在未运行 Update-Database
时出现以下异常:
SqlException:无法打开登录请求的数据库“RazorPagesMovieContext-21”。登录失败。用户“用户名”登录失败。
测试应用Test the app
删除 DB 中的所有记录。可以使用浏览器中的删除链接,也可以从 SSOX 执行此操作
强制应用初始化(调用
Startup
类中的方法),使种子方法能够正常运行。若要强制进行初始化,必须先停止 IIS Express,然后再重新启动它。可以使用以下任一方法来执行此操作:- 右键单击通知区域中的 IIS Express 系统任务栏图标,然后点击“退出”或“停止站点” :
- 如果是在非调试模式下运行 VS 的,请按 F5 以在调试模式下运行。
- 如果是在调试模式下运行 VS 的,请停止调试程序并按 F5。
删除 DB 中的所有记录(使种子方法运行)。停止并启动应用以设定数据库种子。
应用将显示设定为种子的数据。
删除 DB 中的所有记录(使种子方法运行)。停止并启动应用以设定数据库种子。
应用将显示设定为种子的数据。
应用将显示设定为种子的数据:
在下一教程中将对数据的展示进行整理。