Skip to content

在单个应用程序中使用多个EF Core DbContext

Published: at 12:00 AM

摘录

Entity Framework Core(EF Core)是.NET中一个流行的ORM,允许您处理SQL数据库。EF Core使用DbContext,它代表了与数据库的会话,并负责跟踪变更、执行数据库操作以及管理数据库连接。

原文 在单个应用程序中使用多个EF Core DbContext


Entity Framework Core (EF Core) 是.NET中一个流行的ORM,允许您操作SQL数据库。EF Core使用DbContext,它代表了与数据库的会话,并负责跟踪变更、执行数据库操作以及管理数据库连接。

通常情况下,整个应用程序只会有一个DbContext

但是如果您需要使用多个DbContext该怎么办?

在本周的通讯中,我们将探讨:

让我们深入了解!

为什么使用多个DbContext?

有几种情况下使用多个DbContext可能是有用的。

多数据库
您的应用程序需要操作多个SQL数据库吗?然后您被迫使用多个DbContext,每一个都专用于特定的SQL数据库。

分离关注点
如果您构建的应用程序有一个复杂的领域模型,通过在几个DbContext之间分离关注点,您可能会看到改进,每一个都负责领域模型的一个特定区域。

模块化单体
当您构建一个模块化单体时,使用多个DbContext是实用的,因为您可以为每个DbContext配置不同的数据库架构,在数据库级别提供逻辑分离。

读副本
您可以配置一个单独的DbContext实例来访问数据库的读副本,并使用该DbContext进行只读查询。您还可以在DbContext级别配置QueryTrackingBehavior.NoTracking以提高查询性能。

在单个应用程序中创建多个DbContext

下面是如何轻松配置多个DbContext。假设我们的应用程序中有一个CatalogDbContext和一个OrderDbContext。我们想使用以下限制来配置它们:

public class CatalogDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public DbSet<Category> Categories { get; set; }
}

public class OrderDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }

    public DbSet<LineItem> LineItems { get; set; }
}

首先我们需要使用DI容器配置CatalogDbContextOrderDbContext。您可以通过调用AddDbContext方法并指定正在配置的DbContext,然后使用SQL提供者特定方法传递连接字符串来实现。在这个例子中,我使用UseSqlServer方法连接到SQL Server。

using Microsoft.EntityFrameworkCore;

services.AddDbContext<CatalogDbContext>(options =>
    options.UseSqlServer("CONNECTION_STRING"));

services.AddDbContext<OrderDbContext>(options =>
    options.UseSqlServer("CONNECTION_STRING"));

如果您只是想在同一个架构中使用两个DbContext,那么这就是您需要的所有配置。您现在可以在应用程序中注入DbContext实例并使用它们。

然而,如果您想为每个DbContext配置不同的架构,那么您还需要重写OnModelCreating方法并使用HasDefaultSchema指定自定义架构。

public class CatalogDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public DbSet<Category> Categories { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("catalog");
    }
}

public class OrderDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }

    public DbSet<LineItem> LineItems { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("order");
    }
}

使用多个DbContext的限制:

  1. 因为EF Core不知道它们是否使用相同的数据库,所以不可能在不同的DbContext实例之间进行连接操作。
  2. 如果DbContexts使用同一个数据库,那么事务才会起作用。您必须创建一个新的事务并通过调用UseTransaction方法在DbContexts之间共享它。

迁移历史表

如果您决定为每个DbContext使用不同的架构,您会不愉快地发现默认架构不适用于迁移历史表。

您需要通过调用MigrationsHistoryTable方法并指定迁移历史将存储的表名和架构来配置这一点。在这个例子中,我使用了HistoryRepository.DefaultTableName常量,但如果您想要,也可以指定自定义表名。

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;

services.AddDbContext<CatalogDbContext>(options =>
    options.UseSqlServer(
        "CONNECTION_STRING",
        o => o.MigrationsHistoryTable(
            tableName: HistoryRepository.DefaultTableName,
            schema: "catalog")));

services.AddDbContext<OrderDbContext>(options =>
    options.UseSqlServer(
        "CONNECTION_STRING",
        o => o.MigrationsHistoryTable(
            tableName: HistoryRepository.DefaultTableName,
            schema: "order")));

使用多个DbContext的好处

使用多个DbContext可以为您的应用程序提供几个好处:

每个DbContext可以负责应用程序数据的一个特定子集,这有助于组织代码并使其更加模块化。

当您将数据访问分离到多个DbContext时,应用程序可以减少争用风险并提高并发性,这可以提高性能。

如果您使用多个DbContext,您可以配置更细粒度的访问控制来提高应用程序的安全性。您还可以优化性能和资源使用。

总结

在单个应用程序中使用多个EF Core DbContext是直接的,并且有许多好处。

对于读取密集型应用程序,您可以配置一个单独的DbContext以默认关闭查询跟踪并获得改善的性能。

此外,如果您正在构建一个模块化单体,使用多个DbContext是实用的。您可以将DbContexts配置为不同的数据库架构,在数据库级别提供逻辑分离。