ShardingCore documentation: AspNetCore Implementation Guide
Install via NuGet package manager. The ShardingCore package already includes:
- Microsoft.EntityFrameworkCore
- Microsoft.EntityFrameworkCore.Relational
Developers only need to inherit from the base class AbstractShardingDbContext and implement IShardingTableDbContext for sharding operations.
Time-Based Virtual Routing Implementation
Use AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute for monthly partitioning.
Entity Model Definition
public class OrderRecord
{
[Key]
public string OrderId { get; set; }
public string CustomerName { get; set; }
public long Amount { get; set; }
public string Region { get; set; }
public PaymentStatus Status { get; set; }
public string CustomerId { get; set; }
public DateTime OrderDate { get; set; }
}
public enum PaymentStatus
{
Pending = 1,
Processing = 2,
Completed = 3,
Failed = 4
}
DbContext Configuration
public class OrderDbContext : AbstractShardingDbContext, IShardingTableDbContext
{
public OrderDbContext(DbContextOptions options) : base(options) {}
public DbSet<OrderRecord> OrderRecords { get; set; }
public IRouteTail RouteTail { get; set; }
}
Time-Based Sharding Route
public class MonthlyOrderShardingRoute : AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute<OrderRecord>
{
public override DateTime GetStartDate()
{
return new DateTime(2023, 1, 1);
}
public override void Configure(EntityMetadataTableBuilder<OrderRecord> builder)
{
builder.ShardingProperty(o => o.OrderDate);
}
public override bool AutoCreatePartitions()
{
return true;
}
}
Migration Customization
public class CustomMySqlMigrator : MySqlMigrationsSqlGenerator
{
private readonly IShardingRuntimeContext _shardingContext;
public CustomMySqlMigrator(
IShardingRuntimeContext shardingContext,
MigrationsSqlGeneratorDependencies dependencies,
ICommandBatchPreparer commandBatcher,
IMySqlOptions options)
: base(dependencies, commandBatcher, options)
{
_shardingContext = shardingContext;
}
protected override void Generate(
MigrationOperation operation,
IModel model,
MigrationCommandListBuilder builder)
{
var originalCommands = builder.GetCommandList().ToList();
base.Generate(operation, model, builder);
var newCommands = builder.GetCommandList().ToList();
var addedCommands = newCommands.Except(originalCommands).ToList();
MigrationHelper.Generate(
_shardingContext,
operation,
builder,
Dependencies.SqlGenerationHelper,
addedCommands);
}
}
Database Initialization
public static class DatabaseSeeder
{
public static void SeedDatabase(this IApplicationBuilder app)
{
using var scope = app.ApplicationServices.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<OrderDbContext>();
if (!context.OrderRecords.Any())
{
var orders = new List<OrderRecord>(20);
var startDate = new DateTime(2023, 1, 15);
for (int i = 0; i < 20; i++)
{
orders.Add(new OrderRecord
{
OrderId = $"ORD{i:D5}",
CustomerName = $"User{(i % 5)}",
Region = $"Zone{(char)('A' + i % 3)}",
CustomerId = $"CUST{i % 10}",
Amount = 500 + new Random().Next(100, 5000),
Status = (PaymentStatus)(i % 4 + 1),
OrderDate = startDate.AddDays(i)
});
}
context.AddRange(orders);
context.SaveChanges();
}
}
}
Service Configuration
builder.Services.AddShardingDbContext<OrderDbContext>().UseRouteConfig(config =>
{
config.AddShardingTableRoute<MonthlyOrderShardingRoute>();
}).UseConfig(options =>
{
var loggerFactory = LoggerFactory.Create(logging =>
{
logging.AddConsole();
});
options.UseShardingMigrationConfigure(migrationConfig =>
{
migrationConfig.ReplaceService();
});
options.ThrowIfQueryRouteNotMatch = false;
options.UseShardingQuery((connectionString, builder) =>
{
builder.UseMySql(connectionString, MySqlServerVersion.AutoDetect(connectionString))
.UseLoggerFactory(loggerFactory);
});
options.UseShardingTransaction((connection, builder) =>
{
builder.UseMySql(connection, MySqlServerVersion.AutoDetect(connection.ConnectionString))
.UseLoggerFactory(loggerFactory);
});
options.AddDefaultDataSource("main",
"Data Source=127.0.0.1;Initial Catalog=sharding_db;uid=root;pwd=SecurePass123!");
options.AddReadWriteSeparation(sp =>
{
return new Dictionary{
{
"main", new List<string>
{
"Data Source=127.0.0.1;Initial Catalog=sharding_db;uid=root;pwd=SecurePass123!"
}
}
};
}, ReadStrategyEnum.Loop, defaultEnable: true);
}).AddShardingCore();
Middleware Setup
using (var scope = app.Services.CreateScope())
{
var dbContext = scope.ServiceProvider.GetService<OrderDbContext>();
dbContext.Database.Migrate();
}
app.Services.UseAutoTryCompensateTable();
app.SeedDatabase();