2

I tried to use Multiple DbContext to migrate each domain of my project to deferent database like this:

public class AppDbContext: DbContext
.
.
public class UserAccessDbContext: DbContext
.
.
public class AdministrationDbContext: DbContext
.
.
Etc

but it's look like I make something wrong so I get all Tables in each DbContext, I don't have any FK that linking the domains.

My connection string for each DbContext like this:

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 UserAccessDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<UserAccessDbContext>(options => options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 27))));
  
  public static void AdministrationDbContext(this IServiceCollection services, string connectionString) =>
   services.AddDbContext<AdministrationDbContext>(options => options.UseMySql(connectionString, new MySqlServerVersion(new Version(8, 0, 27))));

And my Repository like this:

public class AppRepository<T> : RepositoryBase<T>, IReadRepository<T>, IRepository<T> where T : class, IAggregateRoot
{
  public AppRepository(AppDbContext appDbContext) : base(appDbContext)
  {
  }
}
.
.
.
public class AdministrationRepository<T> : RepositoryBase<T>, IReadRepository<T>, IRepository<T> where T : class, IAggregateRoot
{
    public AdministrationRepository(AdministrationDbContext administrationdbContext) : base(administrationdbContext)
    {
    }
}
.
.
.
public class UserAccessRepository<T> : RepositoryBase<T>, IReadRepository<T>, IRepository<T> where T : class, IAggregateRoot
{
    public UserAccessRepository(UserAccessDbContext userAccessdbContext) : base(userAccessdbContext)
    {

    }
}

I also registered the repo like this:

public class DefaultInfrastructureModule : Module
{
  private readonly bool _isDevelopment = false;
  private readonly List<Assembly> _assemblies = new List<Assembly>();

  public DefaultInfrastructureModule(bool isDevelopment, Assembly? callingAssembly = null)
  {
    _isDevelopment = isDevelopment;
    var coreAssembly = Assembly.GetAssembly(typeof(User)); // TODO: Replace "Project" with any type from your Core project
    var infrastructureAssembly = Assembly.GetAssembly(typeof(StartupSetup));
    if (coreAssembly != null)
    {
      _assemblies.Add(coreAssembly);
    }
    if (infrastructureAssembly != null)
    {
      _assemblies.Add(infrastructureAssembly);
    }
    if (callingAssembly != null)
    {
      _assemblies.Add(callingAssembly);
    }
  }

  protected override void Load(ContainerBuilder builder)
  {
    if (_isDevelopment)
    {
      RegisterDevelopmentOnlyDependencies(builder);
    }
    else
    {
      RegisterProductionOnlyDependencies(builder);
    }
    RegisterCommonDependencies(builder);
  }

  private void RegisterCommonDependencies(ContainerBuilder builder)
  {
    //Start Repository Reg
    builder.RegisterGeneric(typeof(AppRepository<>))
        .As(typeof(IRepository<>))
        .As(typeof(IReadRepository<>))
        .InstancePerLifetimeScope();

    builder.RegisterGeneric(typeof(AdministrationRepository<>))
        .As(typeof(IRepository<>))
        .As(typeof(IReadRepository<>))
        .InstancePerLifetimeScope();

    builder.RegisterGeneric(typeof(UserAccessRepository<>))
        .As(typeof(IRepository<>))
        .As(typeof(IReadRepository<>))
        .InstancePerLifetimeScope();
    //End Repository Reg

    builder
        .RegisterType<Mediator>()
        .As<IMediator>()
        .InstancePerLifetimeScope();

    builder.Register<ServiceFactory>(context =>
    {
      var c = context.Resolve<IComponentContext>();
      return t => c.Resolve(t);
    });

    var mediatrOpenTypes = new[]
    {
      typeof(IRequestHandler<,>),
      typeof(IRequestExceptionHandler<,,>),
      typeof(IRequestExceptionAction<,>),
      typeof(INotificationHandler<>),
    };

    foreach (var mediatrOpenType in mediatrOpenTypes)
    {
      builder
      .RegisterAssemblyTypes(_assemblies.ToArray())
      .AsClosedTypesOf(mediatrOpenType)
      .AsImplementedInterfaces();
    }

    builder.RegisterType<EmailSender>().As<IEmailSender>()
      .InstancePerLifetimeScope();
  }

  private void RegisterDevelopmentOnlyDependencies(ContainerBuilder builder)
  {
    // TODO: Add development only services
  }

  private void RegisterProductionOnlyDependencies(ContainerBuilder builder)
  {
    // TODO: Add production only services
  }

}

What I miss in my code to fix it !

Any help how can I do it.

6
  • Take in consideration you can't have context with tables with the same name because crash classes between them, even if they are in different entitymodels. Commented Nov 26, 2021 at 22:02
  • "so I get all Tables in each DbContext" can you please elaborate? Commented Nov 26, 2021 at 22:54
  • Dear @LeandroBardelli I update my question with more details. Commented Nov 27, 2021 at 0:15
  • Dear @GuruStron may you check my update too. Commented Nov 27, 2021 at 0:19
  • Sorry @sumer5020 but we don't work in that way, we need specific question or code to help you. Please read the tutorial and guidelines on how to ask Commented Nov 27, 2021 at 0:22

1 Answer 1

1

If I get the question right, the case might be you're currently working on a monolith and trying to separate things out to surround each business context for further separate them out,... might be like microservices ?

I don't know about the specific reason why you would want to do that, but if the reason doesn't worth it, I suggest you avoid to doing that.

I assume you read above recommendation, and if it's the case we really need to do that, then understand these things first:

Each DbContext can config their own entity

Let assume we have 10 entities for 3 DbContext, we can separate them out 2 entities for ADbContext, 5 for BDbContext and 3 for CDbContext. Manage the configuration like FK, between them wisely, otherwise, that would turn to be chaos. Here is how to doing this, using 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...
       });
    }
}

Like that, we config and register only entities correspondingly with each DbContext.

We need to register each DbContext separately to whatever kind of DI

You does this above in the question, then I'll skip this part.

Organize Migration operation for each DbContext

I usually organize them in folder like this:

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

Each context have their own Migrations and snapshot.

Doing this by specify separate DbContext when using EF migration tool

dotnet ef migrations add [MigrationName] --context [DbContextName] --output-dir [Path to desire place to store migration]

then apply them separately by

dotnet ef database update [MigrationName] --context [DbContextName]

That's it. Of course we can do it, but I still suggest we should avoid this approach if there was no specific reason.

Sign up to request clarification or add additional context in comments.

9 Comments

Dear @Gordon, my reason to work this eay is that my project dealing with big data and i need to crate one place to manage my dayly work and my other features that need huge power from Database, so i think that if i handeld my data separately between each side i can done it in perfict way👍
And in the other hand i need to use the principal that say "handle you data before it handled you".
If the solution was large, I strongly recommend to separate the process pipelines into smaller projects. They can be in the same folder for easier version control and deployment. And If the solution not tend to go as big as we consider it "complex", then I think we should be fine. Just a remind, If we built the solution from scratch, it would be easy for us(as we fully control the domains and context), but it might not for new comers afterward.
Dear @Gordon I think I miss something when I used IEntityTypeConfiguration
After hard time I catch my issue with DbContext, at first I used modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); to config my entities but my Assembly always take all configrations for the context for some reason, I tried to use modelBuilder.ApplyConfiguration(new AccGeneralJournalConfiguration()); of OnModelCreating in each DbContext and it's work successfully, but that make me confuse a little bit.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.