准备使用 Entity Framework Core(数据库优先)访问 SQL ServerPrepare to access SQL Server using Entity Framework Core (database-first)
操作环境
- Visual Studio的
-
- Visual Studio 2022
- 。网
-
- .NET 8
- 实体框架核心
-
- 实体框架核心 8.0
- SQL 服务器
-
- SQL Server 2022
* 以上是一个验证环境,但它可能适用于其他版本。
起先
Entity Framework Core 是一个 O/R 映射器库。 在访问数据库时,您可以通过代码中定义的模型(类)访问数据库的记录,而无需直接使用SQL语句。 这提供了以下好处:
- 由于SQL语句不是直接编写的,因此减少了SQL注入等安全风险。
- 由于 SQL 语句是字符串,因此即使语法错误,也不会检查构建错误,但由于模型是程序语法,因此可以在构建时检查错误。
Entity Framework Core 可以从现有数据库自动生成代码,以连接到这些模型和数据库。 相反,有一种方法可以手动编写代码,然后自动生成数据库。
前者称为“数据库优先”,后者称为“代码优先”。 还有“模型优先”,它从 ER 图等蓝图生成代码和数据库,但它在 Entity Framework Core 中并未广泛使用。
在本例中,我们将使用“数据库优先”模式,该模式在数据库已存在的基础上生成代码。
SQL Server 设置
为了访问此提示中的 SQL Server 数据库,请提前设置 SQL Server。 它可以在开发环境中的 PC 上设置,也可以通过网络在另一台 PC 上设置。 如果可以从开发环境连接到 SQL Server,那么就可以开始了。 在此提示中,SQL Server 安装在单独的环境中。
SQL Server 设置步骤被省略,因为它们是冗余的。 以下页面包含与 SQL Server 相关的提示,因此,如果您想了解如何设置它,请参考它。
创建表
这一次,我们将以 Mr./Ms. 的身份创建以下数据库和表。
- 数据库名称:TestDatabase
- 表名:用户
- 表列:[ID]、[名称]、[密码]、[年龄]、[电子邮件]、[生日]、[UpdateDateTime]
您可以以任何方式创建它,但如果您不想这样做,请针对 SQL Server 运行以下 SQL 来生成它。
以下是数据库创建 SQL,但由于数据库创建的路径会根据版本等而变化,因此使用 GUI 或命令而不是 SQL 创建它可能更可靠。
USE [master]
GO
CREATE DATABASE [TestDatabase]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'TestDatabase', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\TestDatabase.mdf' , SIZE = 8192KB , MAXSIZE = UNLIMITED, FILEGROWTH = 65536KB )
LOG ON
( NAME = N'TestDatabase_log', FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL16.MSSQLSERVER\MSSQL\DATA\TestDatabase_log.ldf' , SIZE = 8192KB , MAXSIZE = 2048GB , FILEGROWTH = 65536KB )
WITH CATALOG_COLLATION = DATABASE_DEFAULT, LEDGER = OFF
GO
ALTER DATABASE [TestDatabase] SET COMPATIBILITY_LEVEL = 160
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
begin
EXEC [TestDatabase].[dbo].[sp_fulltext_database] @action = 'enable'
end
GO
ALTER DATABASE [TestDatabase] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [TestDatabase] SET ANSI_NULLS OFF
GO
ALTER DATABASE [TestDatabase] SET ANSI_PADDING OFF
GO
ALTER DATABASE [TestDatabase] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [TestDatabase] SET ARITHABORT OFF
GO
ALTER DATABASE [TestDatabase] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [TestDatabase] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [TestDatabase] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [TestDatabase] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [TestDatabase] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [TestDatabase] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [TestDatabase] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [TestDatabase] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [TestDatabase] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [TestDatabase] SET DISABLE_BROKER
GO
ALTER DATABASE [TestDatabase] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [TestDatabase] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [TestDatabase] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [TestDatabase] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [TestDatabase] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [TestDatabase] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [TestDatabase] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [TestDatabase] SET RECOVERY FULL
GO
ALTER DATABASE [TestDatabase] SET MULTI_USER
GO
ALTER DATABASE [TestDatabase] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [TestDatabase] SET DB_CHAINING OFF
GO
ALTER DATABASE [TestDatabase] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [TestDatabase] SET TARGET_RECOVERY_TIME = 60 SECONDS
GO
ALTER DATABASE [TestDatabase] SET DELAYED_DURABILITY = DISABLED
GO
ALTER DATABASE [TestDatabase] SET ACCELERATED_DATABASE_RECOVERY = OFF
GO
EXEC sys.sp_db_vardecimal_storage_format N'TestDatabase', N'ON'
GO
ALTER DATABASE [TestDatabase] SET QUERY_STORE = ON
GO
ALTER DATABASE [TestDatabase] SET QUERY_STORE (OPERATION_MODE = READ_WRITE, CLEANUP_POLICY = (STALE_QUERY_THRESHOLD_DAYS = 30), DATA_FLUSH_INTERVAL_SECONDS = 900, INTERVAL_LENGTH_MINUTES = 60, MAX_STORAGE_SIZE_MB = 1000, QUERY_CAPTURE_MODE = AUTO, SIZE_BASED_CLEANUP_MODE = AUTO, MAX_PLANS_PER_QUERY = 200, WAIT_STATS_CAPTURE_MODE = ON)
GO
ALTER DATABASE [TestDatabase] SET READ_WRITE
GO
表创建 SQL。
USE [TestDatabase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[User](
[ID] [int] NOT NULL,
[Name] [nvarchar](20) NOT NULL,
[Password] [nvarchar](20) NOT NULL,
[Age] [int] NULL,
[Email] [nvarchar](200) NULL,
[Birthday] [date] NULL,
[UpdateDateTime] [datetime2](7) NULL,
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
记录追加 SQL。
USE [TestDatabase]
GO
INSERT [dbo].[User] ([ID], [Name], [Password], [Age], [Email], [Birthday], [UpdateDateTime]) VALUES (1, N'氏名1', N'aaaa', 20, N'aaaa@example.com', CAST(N'2020-04-01' AS Date), CAST(N'2021-03-14T00:00:00.0000000' AS DateTime2))
GO
INSERT [dbo].[User] ([ID], [Name], [Password], [Age], [Email], [Birthday], [UpdateDateTime]) VALUES (2, N'氏名2', N'bbbb', 30, N'bbbb@example.com', CAST(N'2010-04-01' AS Date), CAST(N'2021-03-14T00:00:00.0000000' AS DateTime2))
GO
Visual Studio 设置
我们假设您也已经设置了此设置。 如果您想了解设置步骤等,请在下一页进行总结。
创建项目
Entity Framework Core 不依赖于任何特定的执行环境,因此可以在许多项目中使用。 在本文中,我们将在简单的控制台应用程序环境中使用 Entity Framework Core。
在新项目中,选择“控制台应用”。
项目已创建。 项目名称是什么并不重要。
获取 Entity Framework Core 包
获取用于将 Entity Framework Core 与 NuGet 配合使用的包。
右键单击依赖项,然后选择“管理 NuGet 包”。
从选项卡中选择“浏览”后,输入 EntityFrameworkCore
搜索字段。 然后,应在列表中看到与 Entity Framework Core 相关的包。
由于这次我们将使用 SQL Server,因此我们将安装以下包。
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore
在此示例中,我们将安装 . 同时安装其他两个。
选择安装目标,然后单击“安装”按钮。 对于版本,请选择最新的稳定版本。
对话框基本上没问题,您可以单击“确定”。
同时安装其他两个。
我认为包看起来像这样:
从数据库表结构创建模型(代码)
若要自动生成模型和其他代码,请先生成项目以确保没有错误。 如果出现错误,模型创建将失败。 如果已验证没有错误,则无需生成它。
在 Visual Studio 中,打开包管理器控制台。 如果没有,可以从菜单“工具”、“NuGet 包管理器”、“包管理器控制台”中打开它。
将显示以下窗口,因此请确保右上角的“默认项目”是您要为其创建模型的项目。 (如果你有多个项目,你需要小心)
在输入字段中输入以下文本: 参数会根据环境而变化,因此请及时按照以下说明进行更改。
Scaffold-DbContext -Provider Microsoft.EntityFrameworkCore.SqlServer -Connection "Data Source=<サーバー名>\<インスタンス名>;Database=<データメース名>;user id=<接続ユーザー名>;password=<接続パスワード>;TrustServerCertificate=true" -f -OutputDir "<出力フォルダパス>" -Context "<コンテキストクラス名>" -UseDatabaseNames -DataAnnotations -NoPluralize
示例输入
Scaffold-DbContext -Provider Microsoft.EntityFrameworkCore.SqlServer -Connection "Data Source=TestServer;Database=TestDatabase;user id=TestUser;password=pass;TrustServerCertificate=true" -f -OutputDir "Models\Database" -Context "TestDatabaseDbContext" -UseDatabaseNames -DataAnnotations -NoPluralize
参数 | 说明参数 | 示例 |
---|---|---|
供应商 | 对于 SQL Server,它是 Microsoft.EntityFrameworkCore.SqlServer 固定的。 |
Microsoft.EntityFrameworkCore.SqlServer |
连接 | 要连接到数据库的连接字符串。 连接字符串可以与其他应用一起使用,因此请按照连接字符串的表示法指定要指定的内容。 可以使用 Windows 身份验证或 SQL Server 身份验证。 顺便说一下,它只是暂时用于创建模型,因此在发布此连接字符串的应用程序后,无需注意安全性。 如果您的密码中有符号,请小心逃逸。 | “数据源 = ServerName\SQLEXPRESS; Database=TestDatabase; 用户 id=用户名; 密码=**********” |
f | 即使程序已经存在,它也会被强行覆盖。 | 没有<> |
输出目录 | 要输出代码的文件夹路径。 相对于项目文件夹的路径 | 模型\数据库 |
上下文 | 使用实体框架时的上下文类名称 | TestDatabaseDbContext |
UseDatabaseNames(使用数据库名称) | 如果指定,则数据库的表名将按原样为类名。 如果未指定,则根据规则调整实体类名的大小写。 | 没有<> |
DataAnnotations | 指定后,列类型会自动将 DataAnnotation 特性追加到每个属性。 如果您想根据数据库类型自动执行输入检查,这将有点用。 | 没有<> |
Namespace | 生成的实体类所属的命名空间。 如果未指定,则根据文件夹确定命名空间。 | Test命名空间 |
Context命名空间 | 生成的 Context 所属的命名空间。 如果未指定,则根据文件夹确定命名空间。 | Test命名空间 |
NoOnConfiguring | 不要在代码中嵌入原始连接字符串。 | 没有<> |
NoPluralize | 确保 Context 中每个表名的属性名称不是复数形式。 | 没有<> |
当您按 Enter 键运行它时,将自动生成代码: 如果发生错误,将显示原因,因此请根据错误内容进行响应。
User
该表的模型代码如下。
using System.ComponentModel.DataAnnotations;
namespace SetupSqlServerDatabaseFirst.Models.Database;
public partial class User
{
[Key]
public int ID { get; set; }
[StringLength(20)]
public string Name { get; set; } = null!;
[StringLength(20)]
public string Password { get; set; } = null!;
public int? Age { get; set; }
[StringLength(200)]
public string? Email { get; set; }
public DateOnly? Birthday { get; set; }
public DateTime? UpdateDateTime { get; set; }
}
顺便说一下,之所以显示警告,是因为连接字符串是按原样在生成的上下文类的代码中编写的。 如果可能,连接字符串应存储在单独的位置,并在运行时进行设置,但在这种情况下,它是为了检查操作,因此我将保持原样。
尝试检索和显示记录
现在我们有了访问数据库中记录的代码,让我们尝试检索记录并在控制台上显示它们。
Program.cs
并按如下方式进行修改。
// See https://aka.ms/new-console-template for more information
using SetupSqlServerDatabaseFirst.Models.Database;
using System.Text.Json;
Console.WriteLine("Hello, World!");
// データベースコンテキストのインスタンスを生成する
using var dbContext = new TestDatabaseDbContext();
// データベースから User 一覧を取得する
var users = dbContext.User.ToList();
// 取得した User 情報をコンソールに書き出す
foreach (var user in users)
{
Console.WriteLine(JsonSerializer.Serialize(user));
}
在 中生成自动生成的 DbContext
类 new
。 它被声明为可以自动销毁数据库连接 using var
。
dbContext
生成属性以访问每个模型,因此在本例 User
中,您可以通过访问属性来 User
操作表中的记录。
发出的 SQL 是内部自动生成的,不需要注意。
ToList
这里,使用扩展方法来User
检索表中的所有记录。
foreach
其余部分是使用 and JsonSerializer.Serialize
方法User
在控制台上显示信息来完成的。
如User
上所述,表中的每一列都声明为一个属性,因此可以单独检索该值。