ASP.NET Core 6.0/8.0学习笔记(十五)——DbContext详解

一、什么是DbContext

1.DbContext,数据库上下文,用于构建数据库交互对象

二、创建与使用DbContext的几种方式

1.在服务中直接new一个Context对象,DbContext的配置方式同第十三节环境搭建
2.通过服务注入的方式创建上下文
3.配置DbContextOptionsBuilder(就是DbContext类中的相关代码配置)

public class HomeController: Controller
{
  //注入
    private readonly ILogger<HomeController> _logger:
    
    private readonly IConfiguration _configuration;
    public HomeController(ILogger<HomeController> logger,IConfiguration configuration)
    {
       _logger=logger:
       _configuration = configuration:
    }
    public IActionResult Index()
    {
      //创建一个DbContextOptionsBuilder对象
      DbContextOptionsBuilder<BloggingContext> optionsBuilder=new DbContextOptionsBuilder<BloggingContext>():
      //配置数据连接
      optionsBuilder.UseSqlServer(_configuration.GetConnectionString("Blogs")):
      BloggingContext context new BloggingContext (optionsBuilder.Options):
      context.Blogs.Add(new Blog(){Url ="MyTestURL"}):
      context.SaveChanges();
      return View();
    }
}
  1. 如果DbContext类不需要再次被继承,则使用带泛型的Options,否则使用不带泛型的Options

三、DbContext的生命周期

1.DbContext 的生存期从创建实例时开始,并在释放实例时结束。 DbContext 实例旨在用于单个工作单元。 这意味着 DbContext 实例的生存期通常很短。(来自于官方文档)
(1)什么是“工作单元”:在业务逻辑的代码中,从初始化一个DbContext对象,并使用该对象完成一系列对于数据库的操作,最后提交操作,销毁DbContext实例,这一过程称为一个工作单元。
(2)工作单元将持续跟踪在可能影响数据库的业务事务中执行的所有操作。 当完成操作后,它将找出更改数据库作为工作结果时需要执行的所有操作。
(3)一个典型的工作单元:new DbContext()=>context.SaveChanges()=>context.Dispose()

四、DbContext工厂的使用

1.由于DbContext默认的生命周期是Scope。当一个工作单元结束时,DbContext对象会被立即释放。假设一个方法体中存在多个工作单元时,就需要使用“工厂”来管理DbContext。(官方文档中指出“某些应用程序类型(例如 ASP.NET Core Blazor)使用依赖关系注入,但不创建与所需的 DbContext 生存期一致的服务作用域”)
2.工厂的使用
(1)首先在Program.cs中加载DbContextFactory服务:

using System;
using Microsoft.EntityFrameworkCore;

var builder=WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

//add DbContext Factory Service to DI container
builder.Services.AddDbContextFactory<BlogContext>(p=>{
    p.UseSqlServer(builder.Configuration.GetConnectionString("Blogs"));
});

var app=builder.Build();

(2)通过服务的方式注入工厂:创建一个控制器FactoryContextController,在控制器中注入工厂
(3)在Action中通过注入的Factory对象的CreateDbContext()方法获取到上下文对象,其余用法同以前。注意使用using管理资源:

namespace DbContextFactoryControllers
{
     public class FactoryContextController:Controller
     {
        private readonly IDbContextFactory<BlogsContext> _factory;

        public FactoryContextController(IDbContextFactory<BlogsContext> factory)
        {
            _factory = factory;
        }

        public IActionResult Get()
        {
            using (var context = _factory.CreateContext())
            {
                // Add a Entity To Database
                context.Blogs.Add(new Blog { Name = "My Blog" });
                //Save the current change and commit the change to the database
                context.SaveChanges();
            }
            return Ok();
     }
}

五、避免DbContext线程处理问题

1.DbContext不是线程安全的
2.EF Core不支持在同一个DbContext实例上运行多个并行操作。因此使用异步查询或其他操作时需要使用await运算符,确保所有的异步操作完成于另一个方法调用之前。
3.当EF Core监测到尝试同时使用DbContext实例时,将会引发InvaildOpreationException
4.解决:使用async与await运算符

  public async IActionResult Index()
        {
            using (var context = _factory.CreateContext())
            {
              
                await context.Blogs.Add(new Blog { Name = "My Blog" });
                await context.SaveChanges();
            }
            return Ok();
     }

六、DbContext连接池

1.为什么要使用DbContext连接池:为了程序的性能考虑。因为频繁的创建与销毁DbContext会消耗性能。但是DbContext是一个轻量级对象,创建及释放该对象都不涉及数据库操作,在大多数应用程序中都可以直接创建与释放该对象而不造成影响。但是在高性能程序中就需要注意性能问题。
2.使用DbContext连接池可以解决该问题。但是“池子”不是越大越好,最大为1024,一般不要超过这个大小。一旦超过了就会失效,重新走创建对象或者抛异常。
3.使用上下文池并不会立即销毁上下文对象,而是在释放上下文对象时重置对象状态并将其存储在内部池中。在下一次请求时,将直接返回该实例。
4.使用:
(1)注入连接池:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers();

// Add DbContextPool to the container
builder.Services.AddDbContextPool<BlogsContext>(p=>{
    p.UseSqlServer(builder.Configuration.GetConnectionString("Blogs"));
});

(2)在控制器中直接注入使用该对象即可:用法与普通DbContext一致:

public class ContextPoolController Controller
{
    private readonly BloggingContext_context:

    public ContextPoolController(BloggingContext context)
    {
        _context =context:
    }

    public asyne Task<IActionResult>Index()
    {
        await_context.Blogs.AddAsync (new Blog(){
        Url= "TestURL"});
        await_context.SaveChangesAsync ()
        return View();
    }
}

注意:使用ContextPool不能再运行中修改连接字符串。
(3)使用非依赖注入的形式:首先创建参数对象,然后将参数对象传递给PooledDbContextOptionsBuilder<TDbContext>(options)方法。最后调用CreateDbContext方法即可

public class ContextPoolController Controller
{
  
    public asyne Task<IActionResult>Index()
    {
        var options = new DbContextOptionsBuilder<BlogsContext>()
        .UseSqlServer(Configuration.GetConnectionString("Blogs"));
        var factory=new PooledDbContextFactory<BlogsContext>(options);
        using (var context = factory.CreateContext())
        {
            await_context.Blogs.AddAsync (new Blog(){ Url= "TestURL"});
            await_context.SaveChangesAsync ();
        }
         return View();
    }
}
好的,我可以为您提供一个简单的教程,帮助您使用 ASP.NET Core 6.0 框架和 SQL Server 数据库生成注册登录界面。 1. 安装 SQL Server 数据库 如果您还没有安装 SQL Server 数据库,请使用此链接下载并安装 SQL Server 数据库:https://www.microsoft.com/en-us/sql-server/sql-server-downloads 2. 创建 ASP.NET Core 6.0 项目 打开 Visual Studio 2022 或更高版本,创建一个新的 ASP.NET Core 6.0 Web 应用程序项目。在创建项目时,选择 Web 应用程序模板。 3. 添加 Entity Framework Core 在解决方案资源管理器中,右键单击项目文件夹,选择“管理 NuGet 包”。在 NuGet 包管理器中,搜索并安装 Microsoft.EntityFrameworkCore.SqlServer 和 Microsoft.EntityFrameworkCore.Tools 包。 4. 创建数据库模型 在项目根目录中,创建一个名为 Models 的文件夹。在该文件夹中,创建一个名为 ApplicationUser.cs 的新类。在该类中,定义用户模型: ``` using Microsoft.AspNetCore.Identity; namespace YourProjectName.Models { public class ApplicationUser : IdentityUser { // 可以在此定义其他用户属性 } } ``` 5. 创建数据库上下文 在 Models 文件夹中创建一个名为 ApplicationDbContext.cs 的新类。在该类中,继承 DbContext 并将 ApplicationUser 添加到 DbSet: ``` using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace YourProjectName.Models { public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } } } ``` 6. 配置应用程序 在 Startup.cs 文件中,配置应用程序以使用 Entity Framework Core 和 SQL Server 数据库。在 ConfigureServices 方法中,添加以下代码: ``` services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>(); ``` 在 appsettings.json 文件中,添加以下代码: ``` "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=YourDatabaseName;Trusted_Connection=True;MultipleActiveResultSets=true" }, ``` 7. 生成注册和登录功能 在 Visual Studio 中,右键单击“Controllers”文件夹,选择“添加” > “新建项目项”。在“添加新项目项”对话框中,选择“Identity”模板,并选择“注册”和“登录”选项。单击“添加”按钮,Visual Studio 将为您生成注册和登录功能。 8. 运行应用程序 按 F5 键或单击“调试” > “启动调试”按钮以运行应用程序。您现在可以访问注册和登录页面。 希望这个简单的教程可以帮助到您!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GISer_Qing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值