.Net Core Entity Framework Core 的基础封装

上篇讲到 c# Unit of Work 知识分享时,对于创建DBContext 的封装没有讲到,这次分享跟大家

复制代码
public interface IDbContextFactory
{
    DbContext CreateDbContext(string connectionString);
}

/// <summary>
/// 这里实现的思路是根据用户输入的代码来决定链接的是哪个数据库,从而实现数据库多租户的方式
/// DbContextFactory 将能够在一个请求周期内创建并复用单个 DbContext 实例
/// </summary>
public class DbContextFactory : IDbContextFactory
{
    private readonly IServiceScopeFactory _scopeFactory;
    private DbContext _dbContext;
    public DbContextFactory(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }
    public DbContext CreateDbContext(string connectionString)
    {
        if (_dbContext != null)
        {
            return _dbContext;
        }

        if (string.IsNullOrEmpty(connectionString))
        {
            throw new InvalidOperationException("链接字符串是空的...");
        }

        var scope = _scopeFactory.CreateScope();
        var optionsBuilder = new DbContextOptionsBuilder<NoteDbContext>();
        optionsBuilder.UseMySql(connectionString, new MySqlServerVersion(new Version()));
        optionsBuilder.AddInterceptors(new LoggingInterceptor());
        _dbContext = new NoteDbContext(optionsBuilder.Options);

        return _dbContext;
    }
}

IDbContextFactory接口和实现

到这里我查了一些资料,得出了在.netcore中直接使用AddDbContext 与使用我封装的DbContextFactory 区别说明,如果有错误,请各位指正

复制代码
/*
    使用 AddDbContext
    当使用 AddDbContext 方法注册 DbContext 时:
    生命周期管理:ASP.NET Core DI 容器自动处理 DbContext 的生命周期。通常,DbContext 是作为 Scoped 服务注册的,这意味着每个 HTTP 请求都会创建一个新的 DbContext 实例,并且在请求结束时自动释放。
    配置简化:AddDbContext 提供了一个地方来配置数据库连接和其他选项,使得配置更集中和一致。
    集成:这种方式与 ASP.NET Core 的其他功能(如中间件、过滤器、控制器等)紧密集成,允许在这些组件中通过构造函数注入轻松获取 DbContext 实例。
    连接池:对于某些数据库提供程序(如 SQL Server),AddDbContext 允许使用连接池(通过 AddDbContextPool 方法),这可以提高性能,因为它重用连接实例而不是每次都创建新的。
    例子:

    builder.Services.AddDbContext<NoteDbContext>(options =>
    options.UseMySql(
       builder.Configuration.GetConnectionString("YourConnectionStringName"), 
       new MySqlServerVersion(new Version())
    )
    );

    使用 DbContextFactory
    当手动创建 DbContextFactory 并使用它来创建 DbContext 实例时:
    控制:对 DbContext 的创建有更多的控制,可以在需要的时候创建和释放 DbContext,而不是依赖于请求的生命周期。
    灵活性:这种方法在某些特殊场景下很有用,比如在 Singleton 服务中需要使用 DbContext,或者在非 HTTP 请求的环境(如后台任务)中需要创建 DbContext。
    手动管理:需要手动管理 DbContext 的生命周期,包括创建、使用和释放。
    复杂性:相比于 AddDbContext,手动创建 DbContext 可能会增加代码的复杂性和出错的可能性。
    例子:

    public class DbContextFactory : IDbContextFactory
    {
    // ... 实现 DbContextFactory 的代码 ...
    }
    builder.Services.AddScoped<IDbContextFactory, DbContextFactory>();

    总结
    如果应用程序遵循标准的 ASP.NET Core 请求处理模式,并且希望利用框架提供的便利性和集成,那么使用 AddDbContext 是更好的选择。
    如果需要在不同的环境中创建 DbContext,或者需要更细粒度的控制 DbContext 的创建和销毁,那么使用 DbContextFactory 可能更合适。
    在大多数情况下,推荐使用 AddDbContext 方法,因为它简化了配置和管理,同时提供了与 ASP.NET Core 框架的紧密集成。只有在特定场景下,当标准方法不满足需求时,才考虑使用 DbContextFactory。
    */

AddDbContext 与DbContextFactory 区别说明

复制代码
 public class NoteDbContext : DbContext
 {
     public NoteDbContext(DbContextOptions<NoteDbContext> options)
         : base(options)
     {

     }
     public NoteDbContext(DbContextOptions<DbContext> options)
        : base(options)
     {

     }
     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
     {
         /*
         1.安装 Microsoft.EntityFrameworkCore.Proxies 包。
         2.在 OnConfiguring 方法或在设置 DbContextOptionsBuilder 时调用 UseLazyLoadingProxies()。
         3.导航属性必须是 virtual,这样代理才能重写它们。
         4.实体类不能是 sealed,因为代理需要派生自它们。*/

         /*
         延迟加载可以使初始查询更快,因为它不会加载所有相关的数据。
         然而,如果不当使用,它可能会导致 N+1 查询问题,这是指每次访问导航属性时都会执行一个新的数据库查询,
         这可能会在不经意间导致大量的数据库请求,从而影响应用程序的性能。

         因此,当使用延迟加载时,应该注意:
         确保了解何时会触发延迟加载。
         在性能敏感的代码路径中,可能需要显式地预加载(eager load)相关数据,以避免 N+1 查询问题。
         监控和优化数据库查询,以确保应用程序的性能。*/
         optionsBuilder.UseLazyLoadingProxies();
         //base.OnConfiguring(optionsBuilder);
     }
     public DbSet<PrincipalInfo> PrincipalInfoDbSet { get; set; }
}

DbContext的具体配置

相关推荐
我只吃饭不洗碗10 个月前
c# 代码操作ftp服务器文件
随手封装的工具类