> For the complete documentation index, see [llms.txt](https://monksoul.gitbook.io/hoa/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://monksoul.gitbook.io/hoa/shujukucaozuoshinan/duoshangxiawen_duxiefenli.md).

# 9.11、多上下文、读写分离

## 多上下文

默认情况下，Hoa Framework 只有一个默认的数据库上下文：`Hoa.EntityFramewok.Core.HoaDbContext`，也就是默认只能操作一个数据库。

在 Hoa Framework **1.2.0** 版本中，新增了多数据库上下文的支持。通过配置数据库多上下文可以同时操作多个数据库、并将数据库包裹在同一个事务中。

## 多上下文配置使用

### 第一步

在 `appsetting.json` 中新增新的数据库连接字符串。

```javascript
{
  "ConnectionStrings": {
    "HoaDatabase": "Server=localhost;Database=Hoa;User=sa;Password=000000;",
    "OtherDatabase": "Server=localhost;Database=Hoa;User=sa;Password=000000;"
  }
}
```

### 第二步

在 `Hoa.EntityFramework.Core` 层创建新的 `DbContext`，如 `OtherDbContext`：

```csharp
using Microsoft.EntityFrameworkCore;

namespace Hoa.EntityFrameworkCore
{
    public partial class OtherDbContext : DbContext
    {
        public OtherDbContext(DbContextOptions<OtherDbContext> options)
            : base(options)
        {
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer("Name=OtherDatabase");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
}
```

### 第三步

在 `Hoa.Web.Core.ServiceExtensions.HoaDbContextConfigureExtension` 中配置新的 `DbContext` 信息：

```csharp
using Hoa.EntityFrameworkCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace Hoa.Web.Core.ServiceExtensions
{
    public static class HoaDbContextConfigureExtension
    {
        public static IServiceCollection AddHoaDbContext(this IServiceCollection services, IWebHostEnvironment env)
        {
            services.AddDbContextPool<HoaDbContext>(options =>
            {
                options.UseSqlServer(AppGlobal.Configuration.GetConnectionString("HoaDatabase"));
                if (env.IsDevelopment())
                {
                    options/*.UseLazyLoadingProxies()*/
                                .EnableDetailedErrors()
                                .ConfigureWarnings(c => c.Log((RelationalEventId.CommandExecuting, LogLevel.Debug)));
                }
            }
            , poolSize: 128);
            
            // 配置 OtherDbContext
            services.AddDbContextPool<OtherDbContext>(options =>
            {
                options.UseSqlServer(AppGlobal.Configuration.GetConnectionString("OtherDatabase"));
                if (env.IsDevelopment())
                {
                    options/*.UseLazyLoadingProxies()*/
                                .EnableDetailedErrors()
                                .ConfigureWarnings(c => c.Log((RelationalEventId.CommandExecuting, LogLevel.Debug)));
                }
            }
            , poolSize: 128);

            return services;
        }
    }
}
```

### 第四步

在 `Hoa.Core` 层创建 `OtherDbContextIdentifier` 数据库上下文标识类，**注意：必须以 `Identifier` 结尾！！！并继承 `DbContextIdentifier` 类。**

```csharp
using Hoa.DbManager.Identifiers;

namespace Hoa.Core
{
    public class OtherDbContextIdentifier : DbContextIdentifier
    {
        public OtherDbContextIdentifier() : base(nameof(OtherDbContextIdentifier))
        {
        }
    }
}

```

### 第五步

在 `Hoa.EntityFrameworkCore.HoaEntityFrameworkCoreModule` 中新增配置代码：

```csharp
using Autofac;
using Hoa.DbManager.Identifiers;
using Microsoft.EntityFrameworkCore;

namespace Hoa.EntityFrameworkCore
{
    public class HoaEntityFrameworkCoreModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<HoaDbContext>()
                .As<DbContext>()
                .InstancePerLifetimeScope();

            builder.RegisterType<HoaDbContext>()
                .Named<DbContext>(nameof(HoaDbContextIdentifier))
                .InstancePerLifetimeScope();
            
            // 配置 OtherDbContext
            builder.RegisterType<OtherDbContext>()
                .Named<DbContext>(nameof(OtherDbContextIdentifier))
                .InstancePerLifetimeScope();
        }
    }
}
```

### 第六步

上述配置好后，可以通过 `IDynamicRepository<TEntity,TDbContextIdentifier>` 初始化了：

```csharp
using Hoa.Core.Test.Entities;
using Hoa.Dependencies;
using Hoa.ServiceController.Attributes;
using Hoa.UnitOfWork.Repositories;
using System.ComponentModel.DataAnnotations;

namespace Hoa.Application.Test
{
    [HoaServiceController]
    public class TestAppService : ITestAppService, IAppServiceDependency
    {
        private readonly IRepository<TestEntity> _testRepository;
        
        // 初始化 OtherDbContext
        private readonly IDynamicRepository<TestEntity,OtherDbContextIdentifier> _testOtherRepository;
        
        public TestAppService(
            IRepository<TestEntity> testRepository
            // 在构造函数中注入
            , IDynamicRepository<TestEntity,OtherDbContextIdentifier> testOtherRepository;
            )
        {
            _testRepository = testRepository;
            
            // 使用
            _testOtherRepository = testOtherRepository;
        }

        // ... Other Codes
    }
}
```

关键代码

```csharp
private readonly IDynamicRepository<TestEntity,OtherDbContextIdentifier> _testOtherRepository;
```

## 读写分离配置

文档整理中......

## 关于分布式事务

在多数据库操作上下文操作数据库中，默认开启了分布式事务（同一个服务器内的不同数据库），如果数据库操作上下文不在同一个服务器上将报错：

```
System.PlatformNotSupportedException: This platform does not support distributed transactions.
```

那是因为 .NET Core 3.x 还[不支持跨平台的分布式事务](https://docs.microsoft.com/zh-cn/ef/core/saving/transactions#using-systemtransactions)，需要在 .NET 5.x 版本才支持。

目前提供的解决方案是：在方法上面关闭分布式事务即可。

```csharp
[UnitOfWork(false)]
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://monksoul.gitbook.io/hoa/shujukucaozuoshinan/duoshangxiawen_duxiefenli.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
