### Install ShardingCore and EF Core Packages Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-aspnetcore Install the ShardingCore NuGet package and the appropriate Entity Framework Core database provider for your project. Use `Install-Package ShardingCore` for the core library and `Microsoft.EntityFrameworkCore.SqlServer` for SQL Server. ```powershell # Please install the version you need PM> Install-Package ShardingCore # use sqlserver PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer # use mysql #PM> Install-Package Pomelo.EntityFrameworkCore.MySql # use other database driver,if efcore support ``` -------------------------------- ### Install ShardingCore Packages Source: https://xuejmnet.github.io/sharding-core-doc/sharding-all/init Install the ShardingCore package and the appropriate Entity Framework Core provider for your database. ```csharp PM> Install-Package ShardingCore # Please install the corresponding database version PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer ``` -------------------------------- ### Install ShardingCore Dependencies Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-console Install the ShardingCore package and the appropriate Entity Framework Core database driver for your needs. Ensure version compatibility between EF Core and ShardingCore. ```powershell PM> Install-Package ShardingCore # use sqlserver PM> Install-Package Pomelo.EntityFrameworkCore.MySql # use mysql #PM> Install-Package Pomelo.EntityFrameworkCore.MySql # use other database driver,if efcore support ``` -------------------------------- ### Initialize ShardingCore and Seed Data Source: https://xuejmnet.github.io/sharding-core-doc/sharding-table/init Extension methods to start ShardingCore and initialize seed data for the application. Ensure MyDbContext is not registered as a singleton. ```csharp public static class StartupExtension { public static void UseShardingCore(this IApplicationBuilder app) { app.ApplicationServices.GetRequiredService().Start(); } public static void InitSeed(this IApplicationBuilder app) { using (var serviceScope = app.ApplicationServices.CreateScope()) { var myDbContext = serviceScope.ServiceProvider.GetRequiredService(); if (!myDbContext.Set().Any()) { List settings = new List(3); settings.Add(new Setting() { Code = "Admin", Name = "AdminName" }); settings.Add(new Setting() { Code = "User", Name = "UserName" }); settings.Add(new Setting() { Code = "SuperAdmin", Name = "SuperAdminName" }); List users = new List(10); for (int i = 0; i < 10; i++) { var uer=new SysUser() { Id = i.ToString(), Name = $"MyName{i}", SettingCode = settings[i % 3].Code }; users.Add(uer); } List orders = new List(300); var begin = new DateTime(2021, 1, 1, 3, 3, 3); for (int i = 0; i < 300; i++) { var order = new Order() { Id = i.ToString(), Payer = $"{i % 10}", Money = 100+new Random().Next(100,3000), OrderStatus = (OrderStatusEnum)(i % 4 + 1), CreationTime = begin.AddDays(i) }; orders.Add(order); } myDbContext.AddRange(settings); myDbContext.AddRange(users); myDbContext.AddRange(orders); myDbContext.SaveChanges(); } } } } ``` -------------------------------- ### Original Pagination Query Source: https://xuejmnet.github.io/sharding-core-doc/adv/connection-mode Example of a standard SQL query with pagination using LIMIT and OFFSET. ```sql select * from order limit 10,10 ``` -------------------------------- ### Sharding Core Startup Extension Source: https://xuejmnet.github.io/sharding-core-doc/sharding-all/init Provides extension methods for IApplicationBuilder to start the Sharding Core bootstrap service and initialize seed data for MyDbContext. ```csharp public static class StartupExtension { public static void UseShardingCore(this IApplicationBuilder app) { app.ApplicationServices.GetRequiredService().Start(); } public static void InitSeed(this IApplicationBuilder app) { using (var serviceScope = app.ApplicationServices.CreateScope()) { var myDbContext = serviceScope.ServiceProvider.GetRequiredService(); if (!myDbContext.Set().Any()) { string[] areas = new string[] {"A","B","C" }; List users = new List(10); for (int i = 0; i < 100; i++) { var uer=new SysUser() { Id = i.ToString(), Name = $"MyName{i}", Area = areas[new Random().Next(0,3)] }; users.Add(uer); } List orders = new List(300); var begin = new DateTime(2021, 1, 1, 3, 3, 3); for (int i = 0; i < 300; i++) { var sysUser = users[i % 100]; var order = new Order() { Id = i.ToString(), Payer = sysUser.Id, Money = 100+new Random().Next(100,3000), OrderStatus = (OrderStatusEnum)(i % 4 + 1), Area = sysUser.Area, CreationTime = begin.AddDays(i) }; orders.Add(order); } myDbContext.AddRange(users); myDbContext.AddRange(orders); myDbContext.SaveChanges(); } } } } ``` -------------------------------- ### Start a Transaction Source: https://xuejmnet.github.io/sharding-core-doc/adv/transaction Initiates a new database transaction. Usage is consistent with native EF Core. ```csharp var tran = _defaultTableDbContext.Database.BeginTransaction() ``` -------------------------------- ### Add EF Core Tools Package Source: https://xuejmnet.github.io/sharding-core-doc/adv/code-first Install the EF Core Tools package for managing migrations. Ensure the version matches your EF Core version. ```bash dotnet add package Microsoft.EntityFrameworkCore.Tools ``` -------------------------------- ### Usage Example of ToShardingPageAsync Source: https://xuejmnet.github.io/sharding-core-doc/adv/pagination Demonstrates how to call the `ToShardingPageAsync` extension method on an `Order` DbSet to retrieve paginated results, ordered by `CreateTime`. ```csharp var shardingPageResult = await _defaultTableDbContext.Set().OrderBy(o => o.CreateTime).ToShardingPageAsync(pageIndex, pageSize); ``` -------------------------------- ### Simple Consistent Hashing Example Source: https://xuejmnet.github.io/sharding-core-doc/sharding-route/customer-route Demonstrates a basic consistent hashing logic by dividing a hash code into segments to determine a table suffix. This approach aims to minimize data migration when adding new tables. ```csharp var stringHashCode = ShardingCoreHelper.GetStringHashCode("123"); var hashCode = stringHashCode % 10000; if (hashCode >= 0 && hashCode <= 3000) { return "A"; } else if (hashCode >= 3001 && hashCode <= 6000) { return "B"; } else if (hashCode >= 6001 && hashCode < 10000) { return "C"; } else throw new InvalidOperationException($"cant calc hash route hash code:[{stringHashCode}]"); ``` -------------------------------- ### ShardingCore Additional Configuration with DI Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-console Demonstrates an alternative configuration method where the base DbContext is added first, followed by ShardingCore's specific configuration using `AddShardingConfigure`. This provides more control over the setup. ```csharp //原来的dbcontext配置 services.AddDbContext(ShardingCoreExtension.UseDefaultSharding); //额外添加分片配置 services.AddShardingConfigure() ``` -------------------------------- ### AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute Implementation Source: https://xuejmnet.github.io/sharding-core-doc/adv/dynamic-table This abstract class provides a base implementation for monthly time-based sharding. It defines `GetBeginTime` to specify the starting point for table suffix generation and `GetAllTails` to calculate all existing table suffixes based on the begin time and current month. `GetAllTails` is called once at startup. ```csharp public abstract class AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute : AbstractShardingTimeKeyDateTimeVirtualTableRoute where TEntity : class { public abstract DateTime GetBeginTime(); public override List GetAllTails() { var beginTime = ShardingCoreHelper.GetCurrentMonthFirstDay(GetBeginTime()); var tails=new List(); //提前创建表 var nowTimeStamp =ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now); if (beginTime > nowTimeStamp) throw new ArgumentException("begin time error"); var currentTimeStamp = beginTime; while (currentTimeStamp <= nowTimeStamp) { var tail = ShardingKeyToTail(currentTimeStamp); tails.Add(tail); currentTimeStamp = ShardingCoreHelper.GetNextMonthFirstDay(currentTimeStamp); } return tails; } } ``` -------------------------------- ### Configure Sharding Route Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-aspnetcore Define a virtual table route using `AbstractSimpleShardingModKeyStringVirtualTableRoute`. Specify the sharding property (e.g., `Id`), whether to auto-create tables, and the table separator. This example uses a modulo-based sharding strategy. ```csharp /// /// 创建虚拟路由 /// public class OrderVirtualTableRoute:AbstractSimpleShardingModKeyStringVirtualTableRoute { public OrderVirtualTableRoute() : base(2, 3) { } public override void Configure(EntityMetadataTableBuilder builder) { builder.ShardingProperty(o => o.Id); builder.AutoCreateTable(null); builder.TableSeparator("_"); } } ``` -------------------------------- ### Configure Entity Relationships and Mappings Source: https://xuejmnet.github.io/sharding-core-doc/adv/code-first Implement IEntityTypeConfiguration to define primary keys, properties, and table mappings for your entities. This example shows configurations for NoShardingTable, ShardingWithDateTime, and ShardingWithMod. ```csharp public class NoShardingTableMap : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.HasKey(o => o.Id); builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(128); builder.Property(o => o.Name).HasMaxLength(128); builder.ToTable(nameof(NoShardingTable)); } } public class ShardingWithDateTimeMap : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.HasKey(o => o.Id); builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(128); builder.Property(o => o.Name).HasMaxLength(128); builder.ToTable(nameof(ShardingWithDateTime)); } } public class ShardingWithModMap : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.HasKey(o => o.Id); builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(128); builder.Property(o => o.Name).HasMaxLength(128); builder.Property(o => o.Name).HasMaxLength(128); builder.Property(o => o.TextStr).IsRequired().HasMaxLength(128).HasDefaultValue(""); builder.Property(o => o.TextStr1).IsRequired().HasMaxLength(128).HasDefaultValue("123"); builder.Property(o => o.TextStr2).IsRequired().HasMaxLength(128).HasDefaultValue("123"); builder.ToTable(nameof(ShardingWithMod)); } } ``` -------------------------------- ### Start Sharding Core Tasks Source: https://xuejmnet.github.io/sharding-core-doc/guide-upgrade-5-6 Initiate Sharding Core's automatic table creation and compensation tasks. These are essential for the sharding functionality to operate correctly. ```csharp //启动ShardingCore创建表任务(不调用也可以使用ShardingCore) //不调用会导致定时任务不会开启 app.ApplictaionServices.UseAutoShardingCreate(); //启动进行表补偿(不调用也可以使用ShardingCore) app.ApplictaionServices.UseAutoTryCompensateTable(); ``` -------------------------------- ### ShardingSphere Pagination Rewriting Example Source: https://xuejmnet.github.io/sharding-core-doc/adv/connection-mode Illustrates how ShardingSphere might rewrite a pagination query (limit 10, 10) to (limit 0, 20) for each node, potentially leading to excessive data loading. ```sql select * from order limit 0,20 ``` -------------------------------- ### Route Data Source Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Demonstrates how to get and use the IDataSourceRouteManager to route operations to the correct data source. For sharded databases, entities must implement IVirtualDataSourceRoute to define their routing logic. ```csharp //首先获取IDataSourceRouteManager IDataSourceRouteManager dataSourceRouteManager=.....; //获取路由 dataSourceRouteManager.GetRoute(EntityType); //直接路由 dataSourceRouteManager.RouteTo(.....) ``` -------------------------------- ### Configure ShardingCore Startup Source: https://xuejmnet.github.io/sharding-core-doc/adv/multi-sharding-property-2 This snippet shows the complete configuration for ShardingCore, including setting up the database context, sharding table routes, and data seeding. It demonstrates how to begin and end the sharding configuration process. ```csharp ILoggerFactory efLogger = LoggerFactory.Create(builder => { builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole(); }); var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddShardingDbContext((conStr,builder)=>builder .UseSqlServer(conStr) .UseLoggerFactory(efLogger) ) .Begin(o => { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; }).AddShardingTransaction((connection, builder) => { builder.UseSqlServer(connection).UseLoggerFactory(efLogger); }).AddDefaultDataSource("ds0","Data Source=localhost;Initial Catalog=ShardingMultiProperties;Integrated Security=True;")//如果你是sqlserve只需要修改这边的链接字符串即可 .AddShardingTableRoute(op => { op.AddShardingTableRoute(); }) .AddTableEnsureManager(sp=>new SqlServerTableEnsureManager())//告诉ShardingCore启动时有哪些表 .End(); var app = builder.Build(); // Configure the HTTP request pipeline. app.Services.GetRequiredService().Start(); app.UseAuthorization(); app.MapControllers(); //额外添加一些种子数据 using (var serviceScope = app.Services.CreateScope()) { var defaultDbContext = serviceScope.ServiceProvider.GetService(); if (!defaultDbContext.Set().Any()) { var orders = new List(8); var beginTime = new DateTime(2021, 9, 5); for (int i = 0; i < 8; i++) { var orderNo = beginTime.ToString("yyyyMMddHHmmss") + i.ToString().PadLeft(4, '0'); orders.Add(new Order() { Id = Guid.NewGuid().ToString("n"), CreateTime = beginTime, Name = $"Order" + i, OrderNo = orderNo }); beginTime = beginTime.AddDays(1); if (i % 2 == 1) { beginTime = beginTime.AddMonths(1); } } defaultDbContext.AddRange(orders); defaultDbContext.SaveChanges(); } } app.Run(); ``` -------------------------------- ### Get IVirtualTableRoute using ITableRouteManager Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology First, obtain the ITableRouteManager. Then, use it to get the specific IVirtualTableRoute for managing table sharding logic. ```java ITableRouteManager tableRouteManager=...; tableRouteManager.GetRoute(EntityType); ``` -------------------------------- ### Original Startup Configuration (x.3.x.x) Source: https://xuejmnet.github.io/sharding-core-doc/guide-upgrade-3-4 This code demonstrates the typical startup configuration for Sharding Core version x.3.x.x, including setting up data sources, routing, and table configurations. ```csharp services.AddShardingDbContext((conn, o) => o.UseSqlServer(conn).UseLoggerFactory(efLogger)) .Begin(o => { o.CreateShardingTableOnStart = true; o.EnsureCreatedWithOutShardingTable = true; o.ThrowIfQueryRouteNotMatch = false; //o.AddParallelTables(typeof(SysUserMod), typeof(SysUserSalary)); }) .AddShardingTransaction((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger)) .AddDefaultDataSource("A", "Data Source=localhost;Initial Catalog=ShardingCoreDBA;Integrated Security=True;") .AddShardingDataSource(sp => { return new Dictionary() { { "B", "Data Source=localhost;Initial Catalog=ShardingCoreDBB;Integrated Security=True;" }, { "C", "Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;" }, }; }) .AddShardingDataSourceRoute(o => { o.AddShardingDatabaseRoute(); }) .AddShardingTableRoute(op => { op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); }).AddReadWriteSeparation(sp => { return new Dictionary>() { { "A", new HashSet() { "Data Source=localhost;Initial Catalog=ShardingCoreDBB;Integrated Security=True;" } } }; },ReadStrategyEnum.Loop,defaultEnable: false, readConnStringGetStrategy:ReadConnStringGetStrategyEnum.LatestEveryTime) .AddTableEnsureManager(sp=>new SqlServerTableEnsureManager()) .End(); ``` -------------------------------- ### Initialize and Use ShardingCore in Console App Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-console Demonstrates how to initialize ShardingCore's runtime context and use the configured DbContext to perform database operations like adding and saving data. This is the typical usage pattern after configuration. ```csharp using Microsoft.EntityFrameworkCore; using Sample.ShardingConsole; using ShardingCore; using ShardingCore.Extensions; ShardingProvider.ShardingRuntimeContext.UseAutoTryCompensateTable(); var dbContextOptionsBuilder = new DbContextOptionsBuilder(); dbContextOptionsBuilder.UseDefaultSharding(ShardingProvider.ShardingRuntimeContext); using (var dbcontext = new MyDbContext(dbContextOptionsBuilder.Options)) { dbcontext.Add(new Order() { Id = Guid.NewGuid().ToString("n"), Payer = "111", Area = "123", OrderStatus = OrderStatusEnum.Payed, Money = 100, CreationTime = DateTime.Now }); dbcontext.SaveChanges(); } Console.WriteLine("Hello, World!"); ``` -------------------------------- ### Custom Sharding Comparer for Nullable GUIDs in SQL Server Source: https://xuejmnet.github.io/sharding-core-doc/important Implement a custom comparer to ensure correct sorting of Nullable types in SQL Server when using ShardingCore, maintaining consistency with database sorting. ```csharp /// /// like this example /// /// public class SqlServerNullableGuidCSharpLanguageShardingComparer:CSharpLanguageShardingComparer { public override int Compare(IComparable x, IComparable y, bool asc) { if (x is XXType xg && y is XXType yg) { return new XXFixedType(xg).SafeCompareToWith(new XXFixedType(yg), asc); } return base.Compare(x, y, asc); } } //configure .ReplaceService() ``` -------------------------------- ### Configure ShardingCore for Multi-Tenancy Source: https://xuejmnet.github.io/sharding-core-doc/tenant This snippet shows the `Startup` configuration for enabling multi-tenancy with ShardingCore. It includes setting up the `TenantDbContext`, JWT authentication, and ShardingCore's data source and query/transaction configurations. ```csharp var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddAuthentication(); #region 用户系统配置 builder.Services.AddDbContext(o => o.UseSqlServer("Data Source=localhost;Initial Catalog=IdDb;Integrated Security=True;")); //生成密钥 var keyByteArray = Encoding.ASCII.GetBytes("123123!@#!@#123123"); var signingKey = new SymmetricSecurityKey(keyByteArray); //认证参数 builder.Services.AddAuthentication("Bearer") .AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = signingKey, ValidateIssuer = true, ValidIssuer = "https://localhost:5000", ValidateAudience = true, ValidAudience = "api", ValidateLifetime = true, ClockSkew = TimeSpan.Zero, RequireExpirationTime = true, }; }); #endregion #region 配置ShardingCore builder.Services.AddShardingDbContext() .AddEntityConfig(op => { op.CreateShardingTableOnStart = true; op.EnsureCreatedWithOutShardingTable = true; op.AddShardingTableRoute(); }) .AddConfig(op => { //默认配置一个 op.ConfigId = $"test_{Guid.NewGuid():n}"; op.Priority = 99999; op.AddDefaultDataSource("ds0", "Data Source=localhost;Initial Catalog=TestTenantDb;Integrated Security=True;"); op.UseShardingQuery((conStr, b) => { b.UseSqlServer(conStr); }); op.UseShardingTransaction((conn, b) => { b.UseSqlServer(conn); }); }).EnsureMultiConfig(ShardingConfigurationStrategyEnum.ThrowIfNull); #endregion var app = builder.Build(); // Configure the HTTP request pipeline. app.Services.GetRequiredService().Start(); //初始化启动配置租户信息 app.Services.InitTenant(); app.UseAuthorization(); app.UseAuthorization(); //在认证后启用租户选择中间件 app.UseMiddleware(); app.MapControllers(); app.Run(); ``` -------------------------------- ### Sharded Join Query Example Source: https://xuejmnet.github.io/sharding-core-doc/sharding-all/query This example shows a C# LINQ query that performs a join between two sharded entities, SysUser and Order. The query is translated into SQL that queries multiple tables based on sharding configurations. ```csharp public async Task QueryJoin2() { var begin = new DateTime(2021, 3, 2); var end = new DateTime(2021, 4, 3); var sql1 = from user in _myDbContext.Set().Where(o => (o.Id == "1" || o.Id == "6")&&o.Area=="A") join order in _myDbContext.Set().Where(o => o.CreationTime >= begin && o.CreationTime <= end) on user.Id equals order.Payer select new { user.Id, user.Name, user.Area, OrderId = order.Id, order.Payer, order.CreationTime }; return Ok(await sql1.ToListAsync()); } ``` -------------------------------- ### Get Table Route Manager Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the ITableRouteManager from the ShardingRuntimeContext, which manages table routing logic for sharded tables. ```csharp shardingRuntimeContext.GetTableRouteManager(); ``` -------------------------------- ### 安装ShardingCore和EFCore.SqlServer依赖 Source: https://xuejmnet.github.io/sharding-core-doc/adv/multi-sharding-property-2 在项目中安装ShardingCore和EFCore.SqlServer的NuGet包,以启用分片功能和SQL Server支持。请确保安装与EFCore版本兼容的ShardingCore最新版本(例如x.3.2.x+)。 ```powershell //请安装最新版本目前x.3.2.x+,第一个版本号6代表efcore的版本号 Install-Package ShardingCore -Version 6.3.2 Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 6.0.1 ``` -------------------------------- ### Get Sharding Route Config Options Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the IShardingRouteConfigOptions from the ShardingRuntimeContext, which holds the startup configuration for table routing. ```csharp shardingRuntimeContext.GetShardingRouteConfigOptions(); ``` -------------------------------- ### Get ITableRouteManager and Route Entity Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Obtain the ITableRouteManager to manage table routing. Use GetRoute to retrieve routing information for a given EntityType. ```java ITableRouteManager tableRouteManager=.... tableRouteManager.GetRoute(EntityType); ``` -------------------------------- ### Get Virtual Data Source Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the IVirtualDataSource from the ShardingRuntimeContext, which contains connection information for virtual data sources beyond the default one. ```csharp shardingRuntimeContext.GetVirtualDataSource(); ``` -------------------------------- ### ShardingCore String Configuration with DI Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-console Presents a configuration approach suitable for single-configuration scenarios, using a connection string directly with `UseSqlServer` and then adding ShardingCore configuration. Ensure the connection string matches the default data source. ```csharp //原来的 dbcontext配置 services.AddDbContext(options=>options.UseSqlServer("连接字符串必须和AddConfig的DefaultDataSource一样").UseSharding());//UseSharding()必须要配置 //额外添加分片配置 services.AddShardingConfigure() ``` -------------------------------- ### User Registration and Tenant Configuration API Source: https://xuejmnet.github.io/sharding-core-doc/tenant Handles user registration, creates a new user and tenant configuration, and dynamically appends virtual data source configuration. Ensure `IdentityDbContext` and `ShardingTenantOptions` are correctly configured. ```csharp [Route("api/[controller]/[action]")] [ApiController] [AllowAnonymous] public class PassportController:ControllerBase { private readonly IdentityDbContext _identityDbContext; public PassportController(IdentityDbContext identityDbContext) { _identityDbContext = identityDbContext; } [HttpPost] public async Task Register(RegisterRequest request) { if (await _identityDbContext.Set().AnyAsync(o => o.Name == request.Name)) return BadRequest("user not exists"); var sysUser = new SysUser() { Id = Guid.NewGuid().ToString("n"), Name = request.Name, Password = request.Password, CreationTime=DateTime.Now }; var shardingTenantOptions = new ShardingTenantOptions() { ConfigId = sysUser.Id, Priority = new Random().Next(1,10), DbType = request.DbType, DefaultDataSourceName = "ds0", DefaultConnectionString = GetDefaultString(request.DbType,sysUser.Id) }; var sysUserTenantConfig = new SysUserTenantConfig() { Id = Guid.NewGuid().ToString("n"), UserId = sysUser.Id, CreationTime = DateTime.Now, ConfigJson = JsonConvert.SerializeObject(shardingTenantOptions) }; await _identityDbContext.AddAsync(sysUser); await _identityDbContext.AddAsync(sysUserTenantConfig); await _identityDbContext.SaveChangesAsync(); //注册完成后进行配置生成 DynamicShardingHelper.DynamicAppendVirtualDataSourceConfig(new SqlShardingConfiguration(shardingTenantOptions)); return Ok(); } [HttpPost] public async Task Login(LoginRequest request) { var sysUser = await _identityDbContext.Set().FirstOrDefaultAsync(o=>o.Name==request.Name&&o.Password==request.Password); if (sysUser == null) return BadRequest("name or password error"); //秘钥,就是标头,这里用Hmacsha256算法,需要256bit的密钥 var securityKey = new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes("123123!@#!@#123123")), SecurityAlgorithms.HmacSha256); //Claim,JwtRegisteredClaimNames中预定义了好多种默认的参数名,也可以像下面的Guid一样自己定义键名. //ClaimTypes也预定义了好多类型如role、email、name。Role用于赋予权限,不同的角色可以访问不同的接口 //相当于有效载荷 var claims = new Claim[] { new Claim(JwtRegisteredClaimNames.Iss,"https://localhost:5000"), new Claim(JwtRegisteredClaimNames.Aud,"api"), new Claim("id",Guid.NewGuid().ToString("n")), new Claim("uid",sysUser.Id), }; SecurityToken securityToken = new JwtSecurityToken( signingCredentials: securityKey, expires: DateTime.Now.AddHours(2),//过期时间 claims: claims ); var token = new JwtSecurityTokenHandler().WriteToken(securityToken); return Ok(token); } private string GetDefaultString(DbTypeEnum dbType, string userId) { switch (dbType) { case DbTypeEnum.MSSQL: return $"Data Source=localhost;Initial Catalog=DB{userId};Integrated Security=True;"; case DbTypeEnum.MYSQL: return $"server=127.0.0.1;port=3306;database=DB{userId};userid=root;password=L6yBtV6qNENrwBy7;"; default: throw new NotImplementedException(); } } } public class RegisterRequest { public string Name { get; set; } public string Password { get; set; } public DbTypeEnum DbType { get; set; } } public class LoginRequest { public string Name { get; set; } public string Password { get; set; } } ``` -------------------------------- ### Get Data Source Route Manager Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the IDataSourceRouteManager from the ShardingRuntimeContext, which is responsible for managing and selecting data source routes based on the entity type. ```csharp shardingRuntimeContext.GetDataSourceRouteManager(); ``` -------------------------------- ### Define Entity Objects for Sharding Source: https://xuejmnet.github.io/sharding-core-doc/adv/code-first Define C# classes representing your database entities. Includes examples for no sharding, time-based sharding, and modulo-based sharding. ```csharp public class NoShardingTable { public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } } public class ShardingWithDateTime { public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } public DateTime CreateTime { get; set; } } public class ShardingWithMod { public string Id { get; set; } public string Name { get; set; } public int Age { get; set; } public string TextStr { get; set; } public string TextStr1 { get; set; } public string TextStr2 { get; set; } } ``` -------------------------------- ### Initialize Tenant Extension Data Source: https://xuejmnet.github.io/sharding-core-doc/tenant An extension method to initialize tenant data at application startup. It ensures the database is created and dynamically appends virtual data source configurations based on existing tenant configurations. ```csharp public static class TenantExtension { public static void InitTenant(this IServiceProvider serviceProvider) { using (var scope = serviceProvider.CreateScope()) { var identityDbContext = scope.ServiceProvider.GetRequiredService(); identityDbContext.Database.EnsureCreated(); var sysUserTenantConfigs = identityDbContext.Set().ToList(); if (sysUserTenantConfigs.Any()) { foreach (var sysUserTenantConfig in sysUserTenantConfigs) { var shardingTenantOptions = JsonConvert.DeserializeObject(sysUserTenantConfig.ConfigJson); DynamicShardingHelper.DynamicAppendVirtualDataSourceConfig( new SqlShardingConfiguration(shardingTenantOptions)); } } } } } ``` -------------------------------- ### Get Sharding Table Creator Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Obtains an instance of IShardingTableCreator for a specific sharding DbContext. This service is used to create sharded tables, typically by specifying the table suffix. ```csharp //直接获取 ShardingContainer.GetService>(); //通过非泛型方法获取 (IShardingTableCreator)ShardingContainer.GetService(typeof(IShardingTableCreator<>).GetGenericType0(shardingDbContext.GetType())); ``` -------------------------------- ### Using ShardingRouteManager with CreateScope Source: https://xuejmnet.github.io/sharding-core-doc/sharding-route/manual-route Demonstrates how to use `IShardingRouteManager` within a `CreateScope` to apply hint routes for specific queries. Queries within the scope will only target the specified tables. ```csharp private readonly DefaultShardingDbContext _defaultTableDbContext; private readonly IShardingRouteManager _shardingRouteManager; public ValuesController(DefaultShardingDbContext defaultTableDbContext, IShardingRouteManager shardingRouteManager) { _defaultTableDbContext = defaultTableDbContext; _shardingRouteManager = shardingRouteManager; } using (_shardingRouteManager.CreateScope()) { _shardingRouteManager.Current.TryCreateOrAddMustTail("00","01"); //_shardingRouteManager.Current.TryCreateOrAddHintTail("00", "01"); //_shardingRouteManager.Current.TryCreateOrAddAssertTail(); var mod00s = await _defaultTableDbContext.Set().Skip(10).Take(11).ToListAsync(); } ``` -------------------------------- ### Get Entity Metadata Manager Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the IEntityMetadataManager from the ShardingRuntimeContext. This manager handles metadata for sharded and non-sharded objects, determining if an object is sharded and providing access to its metadata. ```csharp shardingRuntimeContext.GetEntityMetadataManager(); ``` -------------------------------- ### Enable Hint and Assert Routing for Virtual Tables Source: https://xuejmnet.github.io/sharding-core-doc/sharding-route/manual-route Configure a virtual table route to enable hint routing and assert routing. Hint routing must be enabled for assert routing to function. ```csharp public class SysUserModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute { /// /// 开启提示路由 /// protected override bool EnableHintRoute => true; /// /// 开启断言路由 如果不需要断言那么可以选择不开启提示路由[EnableHintRoute]必须开启 /// protected override bool EnableAssertRoute => true; public SysUserModVirtualTableRoute() : base(2, 3) { } } ``` -------------------------------- ### Get DbContext Creator Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the IDbContextCreator from the ShardingRuntimeContext. This is typically managed automatically if ShardingCore and DbContext are used via dependency injection; otherwise, it may need to be overridden. ```csharp shardingRuntimeContext.GetDbContextCreator(); ``` -------------------------------- ### Order Object Initialization with Time Discrepancy Source: https://xuejmnet.github.io/sharding-core-doc/adv/multi-sharding-property-2 Illustrates a scenario where an order's ID is generated at one point, and its creation time is assigned later, potentially leading to time discrepancies. This highlights the need for critical point compatibility algorithms when sharding by creation time. ```csharp var order=new Order() //执行这边生成出来的id是2021-11-30 23:59:59.999.999 order.Id="xxx"; //business code //具体执行时间不确定,哪怕没有business code也没有办法保证两者生成的时间一致,当然如果你可以做到一致完全不需要这么复杂的编写 ............ //执行这边生成出来的时间是2021-12-01 00:00:00.000.000 order.CreateTime=DateTime.Now; ``` -------------------------------- ### Get Sharding Provider Source: https://xuejmnet.github.io/sharding-core-doc/guide/terminology Retrieves the IShardingProvider from the ShardingRuntimeContext, which provides access to sharding configuration information. If an IServiceProvider was provided during configuration, application services can also be accessed through this provider. ```csharp shardingRuntimeContext.GetShardingProvider(); ``` -------------------------------- ### User Registration Source: https://xuejmnet.github.io/sharding-core-doc/tenant Allows new users to register. Upon successful registration, a new user record, tenant configuration, and associated database/tables are created. ```APIDOC ## POST api/Passport/Register ### Description Registers a new user and sets up their tenant configuration. ### Method POST ### Endpoint /api/Passport/Register ### Request Body - **request** (RegisterRequest) - Required - User registration details. - **Name** (string) - Required - The username. - **Password** (string) - Required - The user's password. - **DbType** (DbTypeEnum) - Required - The type of database to be used. ### Response #### Success Response (200) Indicates successful registration. #### Error Response (400) - **BadRequest** - If the user already exists or if there's an issue with the request. ``` -------------------------------- ### Configure Sharding Core Services Source: https://xuejmnet.github.io/sharding-core-doc/guide-upgrade-5-6 Configure Sharding Core services, including database sharding routes, table routes, and various operational settings. This snippet demonstrates how to set up data sources, connection modes, and migration configurations. ```csharp services.AddShardingDbContext() .UseRouteConfig(op => { op.AddShardingDataSourceRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); op.AddShardingTableRoute(); }) .UseConfig(op => { //当无法获取路由时会返回默认值而不是报错 op.ThrowIfQueryRouteNotMatch = false; //忽略建表错误compensate table和table creator op.IgnoreCreateTableError = true; //迁移时使用的并行线程数(分库有效)defaultShardingDbContext.Database.Migrate() op.MigrationParallelCount = Environment.ProcessorCount; //补偿表创建并行线程数 调用UseAutoTryCompensateTable有效 op.CompensateTableParallelCount = Environment.ProcessorCount; //最大连接数限制 op.MaxQueryConnectionsLimit = Environment.ProcessorCount; //链接模式系统默认 op.ConnectionMode = ConnectionModeEnum.SYSTEM_AUTO; //如何通过字符串查询创建DbContext op.UseShardingQuery((conStr, builder) => { builder.UseSqlServer(conStr).UseLoggerFactory(efLogger); }); //如何通过事务创建DbContext op.UseShardingTransaction((connection, builder) => { builder.UseSqlServer(connection).UseLoggerFactory(efLogger); }); //添加默认数据源 op.AddDefaultDataSource("A", "Data Source=localhost;Initial Catalog=ShardingCoreDBA;Integrated Security=True;"); //添加额外数据源 op.AddExtraDataSource(sp => { return new Dictionary() { { "B", "Data Source=localhost;Initial Catalog=ShardingCoreDBB;Integrated Security=True;" }, { "C", "Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;" }, }; }); //如果需要迁移code-first必须要自行处理 o.UseShardingMigrationConfigure(b => { b.ReplaceService(); }); //添加读写分离 op.AddReadWriteSeparation(sp => { return new Dictionary>() { { "A", new HashSet() { "Data Source=localhost;Initial Catalog=ShardingCoreDBB;Integrated Security=True;" } } }; }, ReadStrategyEnum.Loop, defaultEnable: false, readConnStringGetStrategy: ReadConnStringGetStrategyEnum.LatestEveryTime); }) .ReplaceService() .AddShardingCore(); ``` -------------------------------- ### String-Based Sharding Core Configuration Source: https://xuejmnet.github.io/sharding-core-doc/guide/quick-start-aspnetcore Configure sharding using a connection string directly within the DbContext options. This method is suitable for simpler setups where a single configuration is sufficient. ```csharp //原来的dbcontext配置 services.AddDbContext(options=>options.UseSqlServer("连接字符串必须和AddConfig的DefaultDataSource一样").UseSharding());//UseSharding()必须要配置 //额外添加分片配置 services.AddShardingConfigure() ```