Razor 页面教程系列第 4 部分

注意

此版本不是本文的最新版本。 有关当前版本,请参阅本文.NET 9 版本。

警告

此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本

重要

此信息与预发布产品相关,相应产品在商业发布之前可能会进行重大修改。 Microsoft 对此处提供的信息不提供任何明示或暗示的保证。

有关当前版本,请参阅本文.NET 9 版本。

作者:Joe Audette

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

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

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

生成的连接字符串类似于以下 JSON:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-f2e0482c-952d-4b1c-afe9-a1a3dfe52e55;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

警告

本文使用不需要对用户进行身份验证的本地数据库。 生产应用应使用可用的最安全的身份验证流。 有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流

SQL Server Express LocalDB

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

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

    “视图”菜单

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

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

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

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

    显示表数据的打开的 Movie 表

设定数据库种子

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

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;

namespace RazorPagesMovie.Models;

public static class SeedData
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        using (var context = new RazorPagesMovieContext(
            serviceProvider.GetRequiredService<
                DbContextOptions<RazorPagesMovieContext>>()))
        {
            if (context == null || context.Movie == null)
            {
                throw new ArgumentNullException("Null 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();
        }
    }
}

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

if (context.Movie.Any())
{
    return;
}

添加种子初始值设定项

使用下面突出显示的代码更新 Program.cs

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    SeedData.Initialize(services);
}

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthorization();

app.MapStaticAssets();
app.MapRazorPages();

app.Run();

在上述代码中,修改了 Program.cs 来执行以下操作:

  • 从依赖注入 (DI) 容器中获取数据库上下文实例。
  • 调用 seedData.Initialize 方法,并向其传递数据库上下文实例。
  • Seed 方法完成时释放上下文。 using 语句将确保释放上下文。

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

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

测试应用

删除数据库中的所有记录,使种子方法运行。 停止并启动应用以设定数据库种子。 如果数据库未设定种子,请在 if (context.Movie.Any()) 上放置断点并单步执行代码。

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

在浏览器中打开的显示电影数据的电影应用程序

后续步骤

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

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

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

生成的连接字符串类似于以下 JSON:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

警告

本文使用不需要对用户进行身份验证的本地数据库。 生产应用应使用可用的最安全的身份验证流。 有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流

SQL Server Express LocalDB

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

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

    “视图”菜单

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

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

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

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

    显示表数据的打开的 Movie 表

设定数据库种子

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

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;

namespace RazorPagesMovie.Models;

public static class SeedData
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        using (var context = new RazorPagesMovieContext(
            serviceProvider.GetRequiredService<
                DbContextOptions<RazorPagesMovieContext>>()))
        {
            if (context == null || context.Movie == null)
            {
                throw new ArgumentNullException("Null 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();
        }
    }
}

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

if (context.Movie.Any())
{
    return;
}

添加种子初始值设定项

使用下面突出显示的代码更新 Program.cs

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    SeedData.Initialize(services);
}

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

在上述代码中,修改了 Program.cs 来执行以下操作:

  • 从依赖注入 (DI) 容器中获取数据库上下文实例。
  • 调用 seedData.Initialize 方法,并向其传递数据库上下文实例。
  • Seed 方法完成时释放上下文。 using 语句将确保释放上下文。

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

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

测试应用

删除数据库中的所有记录,使种子方法运行。 停止并启动应用以设定数据库种子。 如果数据库未设定种子,请在 if (context.Movie.Any()) 上放置断点并单步执行代码。

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

在浏览器中打开的显示电影数据的电影应用程序

后续步骤

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

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

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

生成的连接字符串类似于以下 JSON:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

警告

本文使用不需要对用户进行身份验证的本地数据库。 生产应用应使用可用的最安全的身份验证流。 有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流

SQL Server Express LocalDB

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

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

    “视图”菜单

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

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

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

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

    显示表数据的打开的 Movie 表

设定数据库种子

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

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;

namespace RazorPagesMovie.Models;

public static class SeedData
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        using (var context = new RazorPagesMovieContext(
            serviceProvider.GetRequiredService<
                DbContextOptions<RazorPagesMovieContext>>()))
        {
            if (context == null || context.Movie == null)
            {
                throw new ArgumentNullException("Null 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();
        }
    }
}

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

if (context.Movie.Any())
{
    return;
}

添加种子初始值设定项

使用下面突出显示的代码更新 Program.cs

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    SeedData.Initialize(services);
}

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

在上述代码中,修改了 Program.cs 来执行以下操作:

  • 从依赖注入 (DI) 容器中获取数据库上下文实例。
  • 调用 seedData.Initialize 方法,并向其传递数据库上下文实例。
  • Seed 方法完成时释放上下文。 using 语句将确保释放上下文。

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

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

测试应用

删除数据库中的所有记录,使种子方法运行。 停止并启动应用以设定数据库种子。 如果数据库未设定种子,请在 if (context.Movie.Any()) 上放置断点并单步执行代码。

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

在浏览器中打开的显示电影数据的电影应用程序

后续步骤

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

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using RazorPagesMovie.Data;
var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

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

生成的连接字符串类似于以下 JSON:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

警告

本文使用不需要对用户进行身份验证的本地数据库。 生产应用应使用可用的最安全的身份验证流。 有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流

SQL Server Express LocalDB

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

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

    “视图”菜单

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

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

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

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

    显示表数据的打开的 Movie 表

设定数据库种子

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

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;

namespace RazorPagesMovie.Models
{
    public static class SeedData
    {
        public static void Initialize(IServiceProvider serviceProvider)
        {
            using (var context = new RazorPagesMovieContext(
                serviceProvider.GetRequiredService<
                    DbContextOptions<RazorPagesMovieContext>>()))
            {
                if (context == null || context.Movie == null)
                {
                    throw new ArgumentNullException("Null 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();
            }
        }
    }
}

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

if (context.Movie.Any())
{
    return;
}

添加种子初始值设定项

使用下面突出显示的代码更新 Program.cs

using Microsoft.EntityFrameworkCore;
using RazorPagesMovie.Data;
using RazorPagesMovie.Models;
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddDbContext<RazorPagesMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("RazorPagesMovieContext") ?? throw new InvalidOperationException("Connection string 'RazorPagesMovieContext' not found.")));

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    SeedData.Initialize(services);
}

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

在上述代码中,修改了 Program.cs 来执行以下操作:

  • 从依赖注入 (DI) 容器中获取数据库上下文实例。
  • 调用 seedData.Initialize 方法,并向其传递数据库上下文实例。
  • Seed 方法完成时释放上下文。 using 语句将确保释放上下文。

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

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

测试应用

删除数据库中的所有记录,使种子方法运行。 停止并启动应用以设定数据库种子。 如果数据库未设定种子,请在 if (context.Movie.Any()) 上放置断点并单步执行代码。

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

在浏览器中打开的显示电影数据的电影应用程序

后续步骤

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

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddDbContext<RazorPagesMovieContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

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

生成的连接字符串类似于以下 JSON:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

警告

本文使用不需要对用户进行身份验证的本地数据库。 生产应用应使用可用的最安全的身份验证流。 有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流

SQL Server Express LocalDB

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

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

    “视图”菜单

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

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

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

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

    显示表数据的打开的 Movie 表

设定数据库种子

使用以下代码在 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();
            }
        }
    }
}

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

if (context.Movie.Any())
{
    return;
}

添加种子初始值设定项

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>();
                });
    }
}

前面的代码修改了 Main 方法,以便执行以下操作:

  • 从依赖注入容器中获取数据库上下文实例。
  • 调用 seedData.Initialize 方法,并向其传递数据库上下文实例。
  • Seed 方法完成时释放上下文。 using 语句将确保释放上下文。

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

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

测试应用

  1. 删除数据库中的所有记录。 使用浏览器中的删除链接,也可以从 SSOX 执行此操作

  2. 通过调用 Startup 类中的方法强制应用初始化,使种子方法能够正常运行。 若要强制进行初始化,必须先停止 IIS Express,然后再重新启动它。 使用以下任一方法停止并重启 IIS:

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

      IIS Express 系统任务栏图标

      上下文菜单

    2. 如果应用是在非调试模式下运行的,请按 F5 以在调试模式下运行。

    3. 如果应用处于调试模式下,请停止调试程序并按 F5

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

在浏览器中打开的显示电影数据的电影应用程序

后续步骤

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

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

public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    services.AddDbContext<RazorPagesMovieContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("RazorPagesMovieContext")));
}

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

生成的连接字符串将类似于以下内容:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-bc;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

警告

本文使用不需要对用户进行身份验证的本地数据库。 生产应用应使用可用的最安全的身份验证流。 有关已部署测试和生产应用的身份验证的详细信息,请参阅安全身份验证流

SQL Server Express LocalDB

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

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

    “视图”菜单

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

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

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

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

    显示表数据的打开的 Movie 表

设定数据库种子

使用以下代码在 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();
            }
        }
    }
}

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

if (context.Movie.Any())
{
    return;
}

添加种子初始值设定项

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>();
                });
    }
}

前面的代码修改了 Main 方法,以便执行以下操作:

  • 从依赖注入容器中获取数据库上下文实例。
  • 调用 seedData.Initialize 方法,并向其传递数据库上下文实例。
  • Seed 方法完成时释放上下文。 using 语句将确保释放上下文。

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

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

测试应用

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

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

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

      IIS Express 系统任务栏图标

      上下文菜单

      • 如果应用是在非调试模式下运行的,请按 F5 以在调试模式下运行。
      • 如果应用处于调试模式下,请停止调试程序并按 F5

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

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

后续步骤