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

作者:Rick AndersonJoe AudetteBy Rick Anderson and Joe Audette

查看或下载示例代码如何下载)。View or download sample code (how to download).

RazorPagesMovieContext 对象处理连接到数据库并将 Movie 对象映射到数据库记录的任务。The RazorPagesMovieContext object handles the task of connecting to the database and mapping Movie objects to database records. 在 Startup.cs 的 ConfigureServices 方法中向依赖关系注入容器注册数据库上下文:The database context is registered with the Dependency Injection container in the ConfigureServices method in Startup.cs:

// 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")));
}

有关 ConfigureServices 中使用的方法的详细信息,请参阅:For more information on the methods used in ConfigureServices, see:

ASP.NET Core 配置系统会读取 ConnectionStringThe ASP.NET Core Configuration system reads the ConnectionString. 为了进行本地开发,它会从 appsettings.json 文件获取连接字符串。For local development, it gets the connection string from the appsettings.json file.

生成代码的数据库名称值 (Database={Database name}) 将并不不同。The name value for the database (Database={Database name}) will be different for your generated code. 名称值是任意的。The name value is arbitrary.

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "RazorPagesMovieContext": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesMovieContext-1234;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

将应用部署到测试或生产服务器时,可以使用环境变量将连接字符串设置为实际的数据库服务器。When the app is deployed to a test or production server, an environment variable can be used to set the connection string to a real database server. 有关详细信息,请参阅配置See Configuration for more information.

SQL Server Express LocalDBSQL Server Express LocalDB

LocalDB 是轻型版的 SQL Server Express 数据库引擎,以程序开发为目标。LocalDB is a lightweight version of the SQL Server Express database engine that's targeted for program development. LocalDB 作为按需启动并在用户模式下运行的轻量级数据库没有复杂的配置。LocalDB starts on demand and runs in user mode, so there's no complex configuration. 默认情况下,LocalDB 数据库在 C:/Users/<user/> 目录下创建 *.mdf 文件。By default, LocalDB database creates *.mdf files in the C:/Users/<user/> directory.

  • 从“视图”菜单中,打开“SQL Server 对象资源管理器”(SSOX)。From the View menu, open SQL Server Object Explorer (SSOX).

    “视图”菜单

  • 右键单击 Movie 表,然后选择“视图设计器”:Right click on the Movie table and select View Designer:

    Movie 表上打开的上下文菜单

    设计器中打开的 Movie 表

请注意 ID 旁边的密钥图标。Note the key icon next to ID. 默认情况下,EF 为该主键创建一个名为 ID 的属性。By default, EF creates a property named ID for the primary key.

  • 右键单击 Movie 表,然后选择“查看数据”:Right click on the Movie table and select View Data:

    显示表数据的打开的 Movie 表

设定数据库种子Seed the database

使用以下代码在 Models 文件夹中创建一个名为 SeedData 的新类:Create a new class named SeedData in the Models folder with the following code:

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 there are any movies in the DB, the seed initializer returns and no movies are added.

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

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

在 Program.cs 中,修改 Main 方法以执行以下操作:In Program.cs, modify the Main method to do the following:

  • 从依赖关系注入容器获取数据库上下文实例。Get a DB context instance from the dependency injection container.
  • 调用 seed 方法,并将上下文传递给它。Call the seed method, passing to it the context.
  • Seed 方法完成时释放上下文。Dispose the context when the seed method completes.

下面的代码显示更新后的 Program.cs 文件。The following code shows the updated Program.cs file.

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.MigrateA production app would not call Database.Migrate. 它会添加到上面的代码中,以防止在未运行 Update-Database 时出现以下异常:It's added to the preceding code to prevent the following exception when Update-Database has not been run:

SqlException:无法打开登录请求的数据库“RazorPagesMovieContext-21”。SqlException: Cannot open database "RazorPagesMovieContext-21" requested by the login. 登录失败。The login failed. 用户“用户名”登录失败。Login failed for user 'user name'.

测试应用Test the app

  • 删除 DB 中的所有记录。Delete all the records in the DB. 可以使用浏览器中的删除链接,也可以从 SSOX 执行此操作You can do this with the delete links in the browser or from SSOX

  • 强制应用初始化(调用 Startup 类中的方法),使种子方法能够正常运行。Force the app to initialize (call the methods in the Startup class) so the seed method runs. 若要强制进行初始化,必须先停止 IIS Express,然后再重新启动它。To force initialization, IIS Express must be stopped and restarted. 可以使用以下任一方法来执行此操作:You can do this with any of the following approaches:

    • 右键单击通知区域中的 IIS Express 系统任务栏图标,然后点击“退出”或“停止站点”:Right click the IIS Express system tray icon in the notification area and tap Exit or Stop Site:

      IIS Express 系统任务栏图标

      上下文菜单

      • 如果是在非调试模式下运行 VS 的,请按 F5 以在调试模式下运行。If you were running VS in non-debug mode, press F5 to run in debug mode.
      • 如果是在调试模式下运行 VS 的,请停止调试程序并按 F5。If you were running VS in debug mode, stop the debugger and press F5.

应用将显示设定为种子的数据:The app shows the seeded data:

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

在下一教程中将对数据的展示进行整理。The next tutorial will clean up the presentation of the data.

其他资源Additional resources