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.
CodePudding user response:
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.