Connections Strings
Ramsha provides a flexible and powerful connection string management system that supports multiple databases, connection string aliases, and automatic resolution.
Overview
The connection string system in Ramsha allows you to:
- Define multiple database connections with names
- Use attributes to specify which connection a DbContext should use
- Create aliases for connection strings
- Replace DbContext implementations while maintaining proper connection resolution
Basic Configuration
1. Define Connection Strings in appsettings.json
{
"ConnectionStrings": {
"Default": "Server=(localdb)\\MSSQLLocalDB;Database=MyAppDb;Trusted_Connection=True;",
"MainDb": "Server=localhost;Database=MainDb;User=sa;Password=your_password;",
"LogDb": "Server=localhost;Database=LogDb;User=sa;Password=your_password;",
"ArchiveDb": "Server=localhost;Database=ArchiveDb;User=sa;Password=your_password;"
}
}
2. Specify Connection String for DbContext
Use the [ConnectionString] attribute to specify which connection string a DbContext should use:
[ConnectionString("MainDb")]
public class AppDbContext : RamshaEFDbContext<AppDbContext>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
// Your DbSets here
public DbSet<User> Users { get; set; }
public DbSet<Product> Products { get; set; }
}
3. Register DbContext in Module
public class AppModule : RamshaModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// Register DbContext with options
context.Services.AddRamshaDbContext<AppDbContext>(options =>
{
// Configure DbContext options here
});
}
}
Connection String Aliases
Why Use Aliases?
Aliases allow you to map multiple names to the same connection string. This is useful when:
- You have legacy code using different connection string names
- You want to provide backward compatibility
- You need to standardize connection string names across multiple applications
Configuring Aliases
Configure aliases in your module's ConfigureServices method:
public class AppModule : RamshaModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
// Configure connection string aliases
context.Services.Configure<ConnectionStringsOptions>(options =>
{
options.ConfigureAliases(builder =>
{
// Map "MainDb" and "Primary" to "Default" connection string
builder.Map("Default", ["MainDb", "Primary"]);
// Map "LoggingDb" to "LogDb" connection string
builder.Map("LogDb", "LoggingDb");
});
});
// Register your DbContext
context.Services.AddRamshaDbContext<AppDbContext>();
}
}
How Aliases Work
With the configuration above:
[ConnectionString("MainDb")]will use the "Default" connection string[ConnectionString("Primary")]will use the "Default" connection string[ConnectionString("LoggingDb")]will use the "LogDb" connection string
This means all these DbContext attributes will work with the same underlying connection strings:
// All these will use the "Default" connection string
[ConnectionString("Default")]
[ConnectionString("MainDb")]
[ConnectionString("Primary")]
public class AppDbContext : RamshaEFDbContext<AppDbContext>
{
// ...
}
// This will use the "LogDb" connection string
[ConnectionString("LogDb")]
[ConnectionString("LoggingDb")]
public class LogDbContext : RamshaEFDbContext<LogDbContext>
{
// ...
}
Advanced Scenarios
Multiple DbContexts with Different Connections
// Main application database
[ConnectionString("AppDb")]
public class AppDbContext : RamshaEFDbContext<AppDbContext>
{
public DbSet<User> Users { get; set; }
public DbSet<Product> Products { get; set; }
}
// Reporting database (read-only replica)
[ConnectionString("ReportDb")]
public class ReportDbContext : RamshaEFDbContext<ReportDbContext>
{
public DbSet<SalesReport> SalesReports { get; set; }
public DbSet<Analytics> Analytics { get; set; }
}
// Audit/logging database
[ConnectionString("AuditDb")]
public class AuditDbContext : RamshaEFDbContext<AuditDbContext>
{
public DbSet<AuditLog> AuditLogs { get; set; }
public DbSet<SystemLog> SystemLogs { get; set; }
}
Dynamic Connection String Resolution
You can implement custom connection string resolution logic:
public class TenantConnectionStringResolver : IConnectionStringResolver
{
private readonly IOptions<ConnectionStringsOptions> _options;
private readonly ITenantService _tenantService;
public TenantConnectionStringResolver(
IOptions<ConnectionStringsOptions> options,
ITenantService tenantService)
{
_options = options;
_tenantService = tenantService;
}
public async Task<string?> ResolveAsync(string? connectionStringName = null)
{
var tenant = await _tenantService.GetCurrentTenantAsync();
// Use tenant-specific connection string if available
var tenantSpecificName = $"{connectionStringName}_{tenant.Id}";
return _options.Value.Get(tenantSpecificName)
?? _options.Value.Get(connectionStringName ?? "Default");
}
}
// Register in module
context.Services.Replace<IConnectionStringResolver, TenantConnectionStringResolver>();
Summary
Ramsha's connection string management system provides:
- Attribute-based configuration using
[ConnectionString] - Alias support for backward compatibility and standardization
- handle DbContext replacement connection string with automatic connection string resolution
- Flexible resolution through
IConnectionStringResolver
This system allows you to manage complex multi-database scenarios while maintaining clean, maintainable code.