5.2 Entity Framework Core (EF Core)


文档摘要

5.2 Entity Framework Core (EF Core) 5.2 Entity Framework Core (EF Core) Entity Framework Core (EF Core) 是一个轻量级、可扩展、开源且跨平台的对象关系映射 (ORM) 框架,适用于 .NET。它允许 .NET 开发人员使用 .NET 对象与数据库交互,而无需编写大量的数据访问代码。EF Core 支持多种数据库提供程序,包括 SQL Server、MySQL、PostgreSQL、SQLite 和 Cosmos DB。 5.2.1 EF Core 的优势 简化数据访问: EF Core 将数据库表映射到 .

## 5.2 Entity Framework Core (EF Core) ## 5.2 Entity Framework Core (EF Core) Entity Framework Core (EF Core) 是一个轻量级、可扩展、开源且跨平台的对象关系映射 (ORM) 框架,适用于 .NET。它允许 .NET 开发人员使用 .NET 对象与数据库交互,而无需编写大量的数据访问代码。EF Core 支持多种数据库提供程序,包括 SQL Server、MySQL、PostgreSQL、SQLite 和 Cosmos DB。 ### 5.2.1 EF Core 的优势 * **简化数据访问:** EF Core 将数据库表映射到 .NET 类,简化了数据访问操作,开发者可以使用 LINQ 查询来操作数据,无需编写复杂的 SQL 语句。 * **对象关系映射 (ORM):** EF Core 自动处理对象和关系数据库之间的映射,减少了手动编写数据访问代码的需求。 * **跨平台支持:** EF Core 可以在 Windows、Linux 和 macOS 上运行,支持 .NET Core 和 .NET Framework。 * **多种数据库支持:** EF Core 支持多种数据库提供程序,允许开发者根据项目需求选择合适的数据库。 * **代码优先、数据库优先和模型优先开发:** EF Core 支持多种开发模式,开发者可以根据项目需求选择最适合的模式。 * **迁移:** EF Core 提供了迁移功能,可以轻松地更新数据库架构以匹配模型更改。 * **性能优化:** EF Core 提供了多种性能优化选项,例如延迟加载、显式加载和跟踪行为控制。 ### 5.2.2 EF Core 的开发模式 EF Core 支持三种主要的开发模式: * **代码优先 (Code First):** 在代码优先模式中,开发者首先定义 .NET 类(实体),然后 EF Core 根据这些类自动创建数据库架构。这是最常用的开发模式。 * **数据库优先 (Database First):** 在数据库优先模式中,开发者首先创建数据库,然后 EF Core 根据数据库架构生成 .NET 类。 * **模型优先 (Model First):** 在模型优先模式中,开发者使用 EF Core 设计器创建数据模型,然后 EF Core 根据模型生成数据库架构和 .NET 类。 这种模式在EF Core中已经不再被官方支持,因此不建议使用。 ### 5.2.3 代码优先模式实践 下面是一个使用代码优先模式创建 EF Core 应用程序的示例。 **1. 创建 ASP.NET Core Web API 项目** 使用 Visual Studio 或 .NET CLI 创建一个新的 ASP.NET Core Web API 项目。 **2. 安装 EF Core NuGet 包** 安装以下 NuGet 包: ```powershell Install-Package Microsoft.EntityFrameworkCore.SqlServer Install-Package Microsoft.EntityFrameworkCore.Tools Install-Package Microsoft.EntityFrameworkCore.Design ``` * `Microsoft.EntityFrameworkCore.SqlServer`: SQL Server 数据库提供程序。 * `Microsoft.EntityFrameworkCore.Tools`: 用于执行 EF Core 命令的工具。 * `Microsoft.EntityFrameworkCore.Design`: 用于设计时操作,例如创建迁移。 **3. 定义实体类** 创建一个名为 `TodoItem` 的实体类: ```csharp using System.ComponentModel.DataAnnotations; namespace TodoApi.Models { public class TodoItem { [Key] public long Id { get; set; } [Required] public string Name { get; set; } public bool IsComplete { get; set; } } } ``` **4. 创建 DbContext 类** 创建一个名为 `TodoContext` 的 DbContext 类,它代表数据库上下文: ```csharp using Microsoft.EntityFrameworkCore; using TodoApi.Models; namespace TodoApi.Models { public class TodoContext : DbContext { public TodoContext(DbContextOptions options) : base(options) { } public DbSet TodoItems { get; set; } } } ``` **5. 配置 DbContext** 在 `Startup.cs` 文件中,配置 DbContext 以使用 SQL Server 数据库: ```csharp using Microsoft.EntityFrameworkCore; using TodoApi.Models; public void ConfigureServices(IServiceCollection services) { services.AddDbContext(options => options.UseSqlServer(Configuration.GetConnectionString("TodoContext"))); services.AddControllers(); } ``` 在 `appsettings.json` 文件中,添加连接字符串: ```json { "ConnectionStrings": { "TodoContext": "Server=(localdb)\\mssqllocaldb;Database=TodoApi;Trusted_Connection=True;MultipleActiveResultSets=true" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" } ``` **6. 创建迁移** 使用 EF Core Tools 创建迁移: ```powershell Add-Migration InitialCreate ``` 这将创建一个名为 `Migrations` 的文件夹,其中包含迁移文件。 **7. 更新数据库** 使用 EF Core Tools 更新数据库: ```powershell Update-Database ``` 这将根据迁移文件创建数据库架构。 **8. 创建 Controller** 创建一个 API Controller 来处理 TodoItem 的 CRUD 操作: ```csharp using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using TodoApi.Models; namespace TodoApi.Controllers { [Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase { private readonly TodoContext _context; public TodoItemsController(TodoContext context) { _context = context; } // GET: api/TodoItems [HttpGet] public async Task>> GetTodoItems() { return await _context.TodoItems.ToListAsync(); } // GET: api/TodoItems/5 [HttpGet("{id}")] public async Task> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; } // PUT: api/TodoItems/5 [HttpPut("{id}")] public async Task PutTodoItem(long id, TodoItem todoItem) { if (id != todoItem.Id) { return BadRequest(); } _context.Entry(todoItem).State = EntityState.Modified; try { await _context.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) { if (!TodoItemExists(id)) { return NotFound(); } else { throw; } } return NoContent(); } // POST: api/TodoItems [HttpPost] public async Task> PostTodoItem(TodoItem todoItem) { _context.TodoItems.Add(todoItem); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem); } // DELETE: api/TodoItems/5 [HttpDelete("{id}")] public async Task> DeleteTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } _context.TodoItems.Remove(todoItem); await _context.SaveChangesAsync(); return todoItem; } private bool TodoItemExists(long id) { return _context.TodoItems.Any(e => e.Id == id); } } } ``` **9. 测试 API** 运行应用程序,并使用 Swagger 或 Postman 测试 API。 ### 5.2.4 EF Core 的关系配置 EF Core 支持配置实体之间的关系,包括一对一、一对多和多对多关系。 **一对一关系** 例如,假设有一个 `Person` 实体和一个 `Address` 实体,一个人只有一个地址: ```csharp public class Person { public int Id { get; set; } public string Name { get; set; } public Address Address { get; set; } } public class Address { public int Id { get; set; } public string Street { get; set; } public string City { get; set; } public int PersonId { get; set; } public Person Person { get; set; } } ``` 在 `DbContext` 中配置关系: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .HasOne(p => p.Address) .WithOne(a => a.Person) .HasForeignKey(a => a.PersonId); } ``` **一对多关系** 例如,假设有一个 `Blog` 实体和 `Post` 实体,一个博客可以有多个帖子: ```csharp public class Blog { public int Id { get; set; } public string Title { get; set; } public List Posts { get; set; } } public class Post { public int Id { get; set; } public string Content { get; set; } public int BlogId { get; set; } public Blog Blog { get; set; } } ``` 在 `DbContext` 中配置关系: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .HasOne(p => p.Blog) .WithMany(b => b.Posts) .HasForeignKey(p => p.BlogId); } ``` **多对多关系** 例如,假设有一个 `Student` 实体和 `Course` 实体,一个学生可以选修多个课程,一个课程可以被多个学生选修: ```csharp public class Student { public int Id { get; set; } public string Name { get; set; } public List StudentCourses { get; set; } } public class Course { public int Id { get; set; } public string Title { get; set; } public List StudentCourses { get; set; } } public class StudentCourse { public int StudentId { get; set; } public Student Student { get; set; } public int CourseId { get; set; } public Course Course { get; set; } } ``` 在 `DbContext` 中配置关系: ```csharp protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity() .HasKey(sc => new { sc.StudentId, sc.CourseId }); modelBuilder.Entity() .HasOne(sc => sc.Student) .WithMany(s => s.StudentCourses) .HasForeignKey(sc => sc.StudentId); modelBuilder.Entity() .HasOne(sc => sc.Course) .WithMany(c => c.StudentCourses) .HasForeignKey(sc => sc.CourseId); } ``` ### 5.2.5 EF Core 的查询 EF Core 提供了多种查询数据的方式,包括 LINQ 查询和原始 SQL 查询。 **LINQ 查询** LINQ (Language Integrated Query) 允许开发者使用 .NET 语言(例如 C#)来查询数据。 EF Core 将 LINQ 查询转换为 SQL 查询,并在数据库中执行。 ```csharp // 获取所有 TodoItems var todoItems = await _context.TodoItems.ToListAsync(); // 获取 Id 为 1 的 TodoItem var todoItem = await _context.TodoItems.FindAsync(1); // 获取所有 IsComplete 为 true 的 TodoItems var completeTodoItems = await _context.TodoItems.Where(t => t.IsComplete).ToListAsync(); ``` **原始 SQL 查询** EF Core 也支持执行原始 SQL 查询,这在需要执行复杂查询或使用数据库特定功能时非常有用。 ```csharp // 执行原始 SQL 查询 var todoItems = await _context.TodoItems.FromSqlRaw("SELECT * FROM TodoItems WHERE IsComplete = 1").ToListAsync(); ``` ### 5.2.6 EF Core 的迁移 EF Core 的迁移功能允许开发者轻松地更新数据库架构以匹配模型更改。 **创建迁移** ```powershell Add-Migration ``` **更新数据库** ```powershell Update-Database ``` **回滚迁移** ```powershell Update-Database ``` ### 5.2.7 EF Core 的性能优化 EF Core 提供了多种性能优化选项,包括: * **延迟加载 (Lazy Loading):** 延迟加载只在需要时才加载相关数据。 虽然方便,但可能导致 N+1 问题。 * **显式加载 (Eager Loading):** 显式加载在查询时加载所有相关数据。 使用 `Include` 方法可以实现显式加载。 * **跟踪行为控制 (Tracking Behavior):** 控制 EF Core 是否跟踪实体的更改。 禁用跟踪可以提高只读查询的性能。 使用 `AsNoTracking` 方法禁用跟踪。 * **编译查询 (Compiled Queries):** 编译查询可以提高重复查询的性能。 ### 5.2.8 EF Core 的状态管理 EF Core 负责跟踪实体的状态,例如 `Added`、`Modified` 和 `Deleted`。 当调用 `SaveChanges` 方法时,EF Core 会根据实体的状态执行相应的数据库操作。 **状态转换图** ```mermaid graph TD A[Detached] --> B(Added); A --> C(Unchanged); C --> D(Modified); C --> E(Deleted); B --> F{SaveChanges()}; D --> F; E --> F; F --> C; ``` * **Detached:** 实体未被 DbContext 跟踪。 * **Added:** 实体已添加到 DbContext,但尚未保存到数据库。 * **Unchanged:** 实体已从数据库加载,并且未被修改。 * **Modified:** 实体已被修改。 * **Deleted:** 实体已被标记为删除。 ### 5.2.9 总结 EF Core 是一个强大的 ORM 框架,可以简化 .NET 应用程序的数据访问操作。 通过使用 EF Core,开发者可以使用 .NET 对象与数据库交互,而无需编写大量的数据访问代码。 EF Core 支持多种开发模式、数据库提供程序和性能优化选项,可以满足各种项目需求。 通过学习和实践 EF Core,可以提高开发效率和应用程序的性能。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U