雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

.NET Core MVC配置注入使用Entity Framework Core(EF) 无需手动释放

2024-07-04 39

Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技术。

在.NET Core MVC,ASP.NET Core Web 应用或者Blazor Server等项目中使用Entity Framework Core需要先安装Microsoft.EntityFrameworkCore包。如果需要连接微软的SqlServer数据库还要安装Microsoft.EntityFrameworkCore.SqlServer。

安装完成后开始配置Entity Framework Core,下面以ASP.NET Core Web 应用为例。

配置数据库连接字符串

在appsettings.json中配置数据库连接字符串

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "ConnectionStrings": {
    "SchoolContext": "Server=(localdb)\\mssqllocaldb;Database=SchoolContext-0e9;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

创建DbContext数据库上下文

using Microsoft.EntityFrameworkCore;
using ContosoUniversity.Models;

namespace ContosoUniversity.Data
{
    public class SchoolContext : DbContext
    {
        public SchoolContext (DbContextOptions<SchoolContext> options)
            : base(options)
        {
        }

        public DbSet<Student> Students { get; set; }
        public DbSet<Enrollment> Enrollments { get; set; }
        public DbSet<Course> Courses { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Course>().ToTable("Course");
            modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
            modelBuilder.Entity<Student>().ToTable("Student");
        }
    }
}

根据命名规范,一般DbSet都用复数形式。DbContext和实体类可以手动编写,也可以通过Microsoft.EntityFrameworkCore.Tools或者EF CLI工具反向工程自动生成。可以参考 Entity Framework Core反向工程DB First基于数据库生成DbContext和实体类 这边文章,可以把整个数据库表自动生成实体类和上下文,而且包含了Fluent API和数据注释,减少很多重复劳动。

配置Program.cs 注册上下文

ASP.NET Core 通过依赖关系注入进行生成。 服务(例如 SchoolContext)在应用程序启动期间通过依赖关系注入进行注册。 需要这些服务(如 Razor 页面)的组件通过构造函数参数提供相应服务。

using ContosoUniversity.Data;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// 注册服务
builder.Services.AddDbContext<SchoolContext>(options =>
  options.UseSqlServer(builder.Configuration.GetConnectionString("SchoolContext")));

通过调用 DbContextOptions 中的一个方法将数据库连接字符串在配置文件中的名称传递给上下文对象。

添加数据库异常筛选器(可选)

需要通过Nuget安装Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore包,如下面的代码所示:

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

builder.Services.AddRazorPages();

builder.Services.AddDbContext<SchoolContext>(options =>
  options.UseSqlServer(builder.Configuration.GetConnectionString("SchoolContext")));
// 添加 AddDatabaseDeveloperPageExceptionFilter
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
else
{
    app.UseDeveloperExceptionPage();
    // 添加UseMigrationsEndPoint
    app.UseMigrationsEndPoint();
}

Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet 包提供 Entity Framework Core 错误页的 ASP.NET Core 中间件。 此中间件有助于检测和诊断 Entity Framework Core 迁移错误。

通过构造函数参数得到上下文

protected SchoolContext _context;
public MyController(SchoolContext context)
{
    _context = context;
}

public async Task OnGetAsync()
{
    Students = await _context.Students.ToListAsync();
}

关于DbContext池的性能

DbContext 通常是一个轻型对象:创建和释放它不涉及数据库操作,而大多数应用程序都可以这样做,而不会对性能产生任何明显的影响。 但是,每个上下文实例确实设置了执行其职责所需的各种内部服务和对象,在高性能方案中,持续执行此操作的开销可能很大。 对于这些情况,EF Core 可以将上下文实例 池 化:释放上下文时,EF Core 会重置其状态并将其存储在内部池中;下次请求新实例时,将返回该共用实例,而不是设置新实例。 上下文池允许你在程序启动时只支付一次上下文设置成本,而不是连续支付。

上下文池与数据库连接池正交,数据库连接池在数据库驱动程序的较低级别进行管理。

EF Core 的 ASP.NET Core 应用中的典型模式涉及通过 AddDbContext将自定义DbContext类型注册到依赖项注入容器中。 然后,将通过控制器或 Razor Pages 中的构造函数参数获取该类型的实例。

EF 最佳实践

SaveChanges的时候数据库连接自动释放,所以不需要手动释放。

在.NET Core中通过依赖注入控制生命周期获得上下文,不需要using。

使用DbContext池,无需手动open,close,减少创建连接的开销。IIS关闭时才会彻底释放。

更新于:2个月前
赞一波!2

文章评论

全部评论