เตรียมการเข้าถึง SQL Server โดยใช้ Entity Framework Core (ฐานข้อมูลก่อน)

ปรับปรุงหน้า :
วันที่สร้างเพจ :

สภาพแวดล้อมในการทํางาน

วิชวลสตูดิโอ
  • วิชวลสตูดิโอ 2022
ตาข่าย
  • .NET 8
แกน Entity Framework
  • Entity Framework Core 8.0
เซิร์ฟเวอร์ SQL
  • SQL Server 2022

* ข้างต้นเป็นสภาพแวดล้อมการตรวจสอบ แต่อาจใช้ได้กับเวอร์ชันอื่น

ทีแรก

Entity Framework Core เป็นไลบรารีของตัวแมป O/R เมื่อเข้าถึงฐานข้อมูล คุณสามารถเข้าถึงระเบียนของฐานข้อมูลผ่านโมเดล (คลาส) ที่กําหนดไว้ในโค้ด โดยไม่ต้องใช้คําสั่ง SQL โดยตรง สิ่งนี้ให้ประโยชน์ดังต่อไปนี้:

  • เนื่องจากคําสั่ง SQL ไม่ได้เขียนโดยตรง ความเสี่ยงด้านความปลอดภัย เช่น การแทรก SQL จะลดลง
  • เนื่องจากคําสั่ง SQL เป็นสตริง แม้ว่าคุณจะทําผิดพลาดในไวยากรณ์ แต่ก็ไม่ได้รับการตรวจสอบข้อผิดพลาดในการสร้าง แต่เนื่องจากโมเดลเป็นไวยากรณ์ของโปรแกรม คุณจึงสามารถตรวจสอบข้อผิดพลาดได้ในเวลาที่สร้าง

Entity Framework Core สามารถสร้างโค้ดจากฐานข้อมูลที่มีอยู่โดยอัตโนมัติเพื่อเชื่อมต่อกับแบบจําลองและฐานข้อมูลเหล่านี้ ในทางกลับกันมีวิธีเขียนโค้ดด้วยตนเองแล้วสร้างฐานข้อมูลโดยอัตโนมัติ

อดีตเรียกว่า "ฐานข้อมูลก่อน" และหลังเรียกว่า "โค้ดก่อน" นอกจากนี้ยังมี "model-first" ซึ่งสร้างโค้ดและฐานข้อมูลจากพิมพ์เขียว เช่น ไดอะแกรม ER แต่ไม่ได้ใช้กันอย่างแพร่หลายใน Entity Framework Core

ในกรณีนี้ เราจะใช้รูปแบบ "ฐานข้อมูลก่อน" ที่สร้างโค้ดบนสมมติฐานที่ว่าฐานข้อมูลมีอยู่แล้ว

การตั้งค่า SQL Server

ในการเข้าถึงฐานข้อมูล SQL Server ในเคล็ดลับนี้โปรดตั้งค่า SQL Server ล่วงหน้า สามารถตั้งค่าบนพีซีในสภาพแวดล้อมการพัฒนาหรือบนพีซีเครื่องอื่นผ่านเครือข่าย หากคุณสามารถเชื่อมต่อกับ SQL Server จากสภาพแวดล้อมการพัฒนาของคุณ คุณก็พร้อมที่จะไป ในเคล็ดลับนี้ SQL Server จะถูกติดตั้งในสภาพแวดล้อมที่แยกต่างหาก

ขั้นตอนการตั้งค่า SQL Server ถูกละเว้นเนื่องจากมีความซ้ําซ้อน หน้าต่อไปนี้มีเคล็ดลับที่เกี่ยวข้องกับ SQL Server ดังนั้นหากคุณต้องการทราบวิธีตั้งค่าโปรดดู

สร้างตาราง

คราวนี้เราจะสร้างฐานข้อมูลและตารางต่อไปนี้เป็น Mr./Ms.

  • ชื่อฐานข้อมูล: TestDatabase
  • ชื่อตาราง: ผู้ใช้
  • คอลัมน์ตาราง: [ID], [ชื่อ], [รหัสผ่าน], [อายุ], [อีเมล], [วันเกิด], [UpdateDateTime]

คุณสามารถสร้างได้ด้วยวิธีใดก็ได้ แต่ถ้าคุณไม่ต้องการทํา ให้เรียกใช้ SQL ต่อไปนี้กับ SQL Server เพื่อสร้าง

ต่อไปนี้เป็น 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; ฐานข้อมูล=TestDatabase; รหัสผู้ใช้=ชื่อผู้ใช้; รหัสผ่าน=**********"
f แม้ว่าโปรแกรมจะมีอยู่แล้ว แต่ก็จะถูกบังคับเขียนทับ ไม่มี<>
เอาต์พุต เส้นทางโฟลเดอร์ที่คุณต้องการส่งออกโค้ด เส้นทางที่สัมพันธ์กับโฟลเดอร์โครงการ โมเดล\ฐานข้อมูล
บริบท ชื่อคลาสบริบทเมื่อใช้ Entity Framework TestDatabaseDbContext
UseDatabaseNames หากระบุชื่อตารางของฐานข้อมูลจะเป็นชื่อคลาสตามที่เป็นอยู่ หากไม่ได้ระบุ กรณีของชื่อคลาสเอนทิตีจะถูกปรับตามกฎ ไม่มี<>
คําอธิบายประกอบข้อมูล เมื่อระบุ ชนิดคอลัมน์จะผนวกแอตทริบิวต์ DataAnnotation ให้กับแต่ละคุณสมบัติโดยอัตโนมัติ สิ่งนี้มีประโยชน์เล็กน้อยหากคุณต้องการทําการตรวจสอบอินพุตโดยอัตโนมัติตามประเภทของฐานข้อมูล ไม่มี<>
เนมสเปซ เนมสเปซที่คลาสเอนทิตีที่สร้างขึ้นเป็นอยู่ หากไม่ได้ระบุ namespace จะถูกกําหนดตามโฟลเดอร์ TestNamespace
ContextNamespace เนมสเปซที่บริบทที่สร้างขึ้นเป็นอยู่ หากไม่ได้ระบุ namespace จะถูกกําหนดตามโฟลเดอร์ TestNamespace
NoOn การกําหนดค่า อย่าฝังสตริงการเชื่อมต่อดิบในโค้ดของคุณ ไม่มี<>
ไม่พหูพจน์ ตรวจสอบให้แน่ใจว่า ชื่อคุณสมบัติสําหรับแต่ละชื่อตารางในบริบทไม่ได้เป็นพหูพจน์ ไม่มี<>

เมื่อคุณกด 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));
}

สร้างคลาสnewที่สร้างขึ้นโดยอัตโนมัติDbContextใน มีการประกาศเพื่อให้สามารถทําลายการเชื่อมต่อฐานข้อมูลusing varได้โดยอัตโนมัติ

dbContext สร้างคุณสมบัติเพื่อเข้าถึงแต่ละโมเดล ดังนั้นในกรณีนี้ User คุณสามารถจัดการเรกคอร์ดในตารางได้โดยการเข้าถึง User คุณสมบัติ SQL ที่ออกจะถูกสร้างขึ้นโดยอัตโนมัติภายในและไม่จําเป็นต้องสังเกตเห็น

ToListที่นี่วิธีการขยายจะใช้เพื่อUserดึงระเบียนทั้งหมดในตาราง

foreachส่วนที่เหลือทําได้โดยใช้วิธีการ และ JsonSerializer.Serialize เพื่อUserแสดงข้อมูลบนคอนโซล ดังที่ได้Userกล่าวไว้ข้างต้นแต่ละคอลัมน์ในตารางจะถูกประกาศเป็นคุณสมบัติดังนั้นจึงเป็นไปได้ที่จะดึงค่าทีละรายการ