Как работать с базой данных с несколькими источниками с помощью DbContext

#c# #entity-framework #asp.net-core #domain-driven-design #ardalis-cleanarchitecture

Вопрос:

Я использовал шаги clean arch для создания проекта, но проблема в том, что у меня более трех агрегатов, которые мне нужно поместить в базу данных референтов.

Я попытался использовать DbContext для каждого агрегата следующим образом:

 public class AppDbContext : DbContext
{
  private readonly IMediator? _mediator;

  public AppDbContext(DbContextOptions<AppDbContext> options, IMediator? mediator)
      : base(options)
  {
    _mediator = mediator;
  }
.
.
.
public class AnalyzeDbContext : DbContext
{
  private readonly IMediator? _mediator;

  public AnalyzeDbContext(DbContextOptions<AnalyzeDbContext> options, IMediator? mediator)
      : base(options)
  {
    _mediator = mediator;
  }
.
.
.
public class ProviderMgrDbContext : DbContext
{
  private readonly IMediator? _mediator;


  public ProviderMgrDbContext(DbContextOptions<ProviderMgrDbContext> options, IMediator? mediator)
      : base(options)
  {
    _mediator = mediator;
  }
 

И я отправляю строку подключения для каждого DbContext следующим образом:

 //#Update 1
 public static void AppDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<AppDbContext>(options => options.UseMySQL(connectionString));

 public static void ProviderMgrDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<ProviderMgrDbContext>(options => options.UseMySQL(connectionString));

  public static void AnalyzeDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<AnalyzeDbContext>(options => options.UseMySQL(connectionString));

//#After
public static void AppDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<AppDbContext>(options => options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 27))));

 public static void ProviderMgrDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<ProviderMgrDbContext>(options => options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 27))));
  
  public static void AnalyzeDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<AnalyzeDbContext>(options => options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 27))));
.
.
.

 

Но когда я пытаюсь перенести их, это показывает ошибку освобождения, подобную этой:

 PM> Add-Migration init_1 -context AppDbContext
Build started...
Build succeeded.
Autofac.Core.DependencyResolutionException: An exception was thrown while activating WetaPayment.Infrastructure.Data.DataContext.AppDbContext.
 ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor(Microsoft.EntityFrameworkCore.DbContextOptions`1[WetaPayment.Infrastructure.Data.DataContext.AppDbContext], MediatR.IMediator)' on type 'AppDbContext'.
 ---> System.TypeLoadException: Method 'AppendIdentityWhereCondition' in type 'MySql.EntityFrameworkCore.MySQLUpdateSqlGenerator' from assembly 'MySql.EntityFrameworkCore, Version=5.0.8.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d' does not have an implementation.
 

Наконец, я исправил часть проблемы с MySql.EntityFrameworkCore пакетом изменений, который не был совместим с net6.0, поэтому я использовал Pomelo.EntityFrameworkCore.MySql его, и он успешно работал.

Но все же у меня есть еще одна проблема, которая заключается в том, что все мои агрегаты облысели во всех контекстах, и мне нужно, чтобы каждый DbContext создавал только свою совокупность, так как это исправить ?

Комментарии:

1. 9 из 10 раз я вижу a TypeLoadException в EF Core это потому, что я использую несовместимые версии пакетов EF Core, убедитесь, что все ваши ссылки на EF Core во всех ваших проектах ссылаются на одни и те же версии

2. Уважаемый MindSwipe, я проверил свои версии EF, и это все последние версии, я использовал net6.0.

3. MindSwipe uoy правы, наконец-то я нахожу проблему с моей MySql.EntityFrameworkCore поддержкой, которая не была совместима с net6.0, поэтому я использовал Pomelo.EntityFrameworkCore.MySql , и это сработало.

4. Теперь у меня другая проблема, вся моя совокупность облысела во всех контекстах, и мне нужно, чтобы каждый DbContext создавал только свою совокупность.

Ответ №1:

Каждый DbContext может настроить свою собственную сущность

Предположим , что у нас есть 10 сущностей для 3 DbContext , мы можем разделить их на 2 сущности для ADbContext , 5 для BDbContext и 3 для CDbContext . Управляйте конфигурацией так FK , чтобы между ними было разумно, иначе это превратилось бы в хаос. Вот как это сделать, используя fluent API

 public class MyAppDbContext : DbContext
{
    public DbSet<OurEntity> OurEntity { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<OurEntity>(builder => 
       {
            // Our implementation goes here...
       });
    }
}
 

Таким образом, мы настраиваем и регистрируем только сущности соответственно с каждой DbContext из них .

Нам нужно зарегистрировать каждого DbContext отдельно в любом типе DI

Организуйте операцию миграции для каждого DbContext

Я обычно упорядочиваю их в папке вот так:

 Data/Migrations/ContextA
Data/Migrations/ContextB
Data/Migrations/ContextC
 

У каждого контекста есть свои собственные миграции и моментальный снимок.

Для этого укажите отдельно DbContext при использовании EF инструмента миграции

 add-migration add [MigrationName] -context [DbContextName] -o [Path to desire place to store migration]
 

затем примените их отдельно,

 update-database -context [DbContextName]