public void ConfigureServices(IServiceCollection services)
{services.AddEFCoreSharding(config =>{单表//config.UseDatabase(Config.CONSTRING1, DatabaseType.SqlServer);使用多个数据库//config.UseDatabase<IMyDbAccessor>(Config.CONSTRING1, DatabaseType.SqlServer);//DateTime startTime = DateTime.Now.AddMinutes(-5);//DateTime endTime = DateTime.MaxValue;分表//config.AddAbsDb(DatabaseType.SqlServer)//添加抽象数据库// .AddPhysicDbGroup()//添加物理数据库组// .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.CONSTRING1)//添加物理数据库1// .SetDateShardingRule<Base_UnitTest>(nameof(Base_UnitTest.CreateTime))//设置分表规则// .AutoExpandByDate<Base_UnitTest>(//设置为按时间自动分表// ExpandByDateMode.PerMinute,// (startTime, endTime, ShardingConfig.DefaultDbGourpName)// );//获取配置文件的连接字符串string conName = Configuration["ConnectionName"];//判断是否启用逻辑删除if (Configuration["LogicDelete"].ToBool())config.UseLogicDelete();//连接数据库config.UseDatabase(Configuration.GetConnectionString(conName), Configuration["DatabaseType"].ToEnum<DatabaseType>());//设置启用程序集的名称config.SetEntityAssembly(GlobalData.FXASSEMBLY_PATTERN);});
}
appsettings.json
{"LogicDelete": false, //是否开启逻辑删除,默认为物理删除"DatabaseType": "SqlServer", //默认数据库类型,定义详见EFCore.Sharding.DatabaseType"ConnectionName": "BaseDb", //默认连接字符串名"ConnectionStrings": {//SQLServer"BaseDb": "Data Source=.;Initial Catalog=Colder.Admin.AntdVue;Integrated Security=True;Pooling=true;"//PostgreSQL//"BaseDb": "SERVER=localhost;PORT=5432;DATABASE=Colder.Admin.AntdVue;USER ID=postgres;PASSWORD=postgres"//MySQl//"BaseDb": "server=127.0.0.1;user id=root;password=root;persistsecurityinfo=True;database=Colder.Admin.AntdVue;SslMode=none"//Oracle//"BaseDb": "Data Source=127.0.0.1/ORCL;User ID=COLDER.ADMIN.ANTDVUE;Password=123456;Connect Timeout=3"}
}
普通的使用方式
ShardingConfig.Init(config =>
{config.AddAbsDb(DatabaseType.SQLite).AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, "DataSource=db.db").AddPhysicDbGroup().SetHashModShardingRule<Base_UnitTest>(nameof(Base_UnitTest.Id), 3);
});
using(IShardingDbAccessor _db = DbFactory.GetShardingDbAccessor())
{Base_UnitTest _newData = new Base_UnitTest{Id = Guid.NewGuid().ToString(),UserId = "Admin",UserName = "超级管理员",Age = 22};List<Base_UnitTest> _insertList = new List<Base_UnitTest>{new Base_UnitTest{Id = Guid.NewGuid().ToString(),UserId = "Admin1",UserName = "超级管理员1",Age = 22},new Base_UnitTest{Id = Guid.NewGuid().ToString(),UserId = "Admin2",UserName = "超级管理员2",Age = 22}};//添加单条数据_db.Insert(_newData);//添加多条数据_db.Insert(_insertList);//清空表_db.DeleteAll<Base_UnitTest>();//删除单条数据_db.Delete(_newData);//删除多条数据_db.Delete(_insertList);//删除指定数据_db.Delete<Base_UnitTest>(x => x.UserId == "Admin2");//更新单条数据_db.Update(_newData);//更新多条数据_db.Update(_insertList);//更新单条数据指定属性_db.UpdateAny(_newData, new List<string> { "UserName", "Age" });//更新多条数据指定属性_db.UpdateAny(_insertList, new List<string> { "UserName", "Age" });//更新指定条件数据_db.UpdateWhere<Base_UnitTest>(x => x.UserId == "Admin", x =>{x.UserId = "Admin2";});//GetList获取表的所有数据var list=_db.GetList<Base_UnitTest>();//GetIQPagination获取分页后的数据var list=_db.GetIShardingQueryable<Base_UnitTest>().GetPagination(pagination);//Maxvar max=_db.GetIShardingQueryable<Base_UnitTest>().Max(x => x.Age);//Minvar min=_db.GetIShardingQueryable<Base_UnitTest>().Min(x => x.Age);//Averagevar min=_db.GetIShardingQueryable<Base_UnitTest>().Average(x => x.Age);//Countvar min=_db.GetIShardingQueryable<Base_UnitTest>().Count();//事务,使用方式与普通事务一致bool succcess = _db.RunTransaction(() =>{_db.Insert(_newData);var newData2 = _newData.DeepClone();_db.Insert(newData2);}).Success;Assert.AreEqual(succcess, false);}
按时间分表
var db = DbFactory.GetShardingDbAccessor();
while (true)
{try{db.Insert(new Base_UnitTest{Id = Guid.NewGuid().ToString(),Age = 1,UserName = Guid.NewGuid().ToString(),CreateTime = DateTime.Now});DateTime time = DateTime.Now.AddMinutes(-2);var count = db.GetIShardingQueryable<Base_UnitTest>().Where(x => x.CreateTime >= time).Count();Console.WriteLine($"当前数据量:{count}");Stopwatch watch = new Stopwatch();var q = db.GetIQueryable<Base_UnitTest>().Where(x => x.UserName.Contains("00001C22-8DD2-4D47-B500-407554B099AB")).OrderByDescending(x => x.Id).Skip(0).Take(30);q.ToList();q.ToSharding().ToList();watch.Restart();var list1 = q.ToList();watch.Stop();Console.WriteLine($"未分表耗时:{watch.ElapsedMilliseconds}ms");//7800mswatch.Restart();var list2 = q.ToSharding().ToList();watch.Stop();Console.WriteLine($"分表后耗时:{watch.ElapsedMilliseconds}ms");//2400ms}catch (Exception ex){Console.WriteLine(ex.Message);}Thread.Sleep(50);
}
备注
/// <summary>
/// 单元测试表
/// </summary>
[Table("Base_UnitTest")]
[Index(false, nameof(CreateTime))]//建表自动创建索引
[Index(false, nameof(Age))]//建表自动创建索引
[Keys(nameof(Id), nameof(UserName))]//自动建表时会自动创建主键(多主键支持)
public class Base_UnitTest
{/// <summary>/// 代理主键/// </summary>[Key, StringLength(50)]public String Id { get; set; }/// <summary>/// 创建时间/// </summary>public DateTime CreateTime { get; set; }/// <summary>/// 用户名/// </summary>public String UserName { get; set; }/// <summary>/// Age/// </summary>public Int32? Age { get; set; }
}
多数据库插入
class Program{static void Main(string[] args){Host.CreateDefaultBuilder(args).ConfigureLogging(config =>{}).ConfigureServices((host, services) =>{services.AddHostedService<DbTest>();services.UseEFCoreSharding(config =>{//单表config.UseDatabase(Config.CONSTRING1, DatabaseType.SqlServer);//使用多个数据库config.UseDatabase<IMyDbAccessor>(Config.CONSTRING1, DatabaseType.SqlServer);DateTime startTime = DateTime.Now.AddMinutes(-5);DateTime endTime = DateTime.MaxValue;//分表config.AddAbsDb(DatabaseType.SqlServer)//添加抽象数据库.AddPhysicDbGroup()//添加物理数据库组.AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.CONSTRING1)//添加物理数据库1.SetDateShardingRule<Base_UnitTest>(nameof(Base_UnitTest.CreateTime))//设置分表规则.AutoExpandByDate<Base_UnitTest>(//设置为按时间自动分表ExpandByDateMode.PerMinute,(startTime, endTime, ShardingConfig.DefaultDbGourpName));});}).Build().Run();}}
public interface IMyDbAccessor : IDbAccessor{}
class DbTest : BackgroundService{readonly IServiceProvider _serviceProvider;readonly ILogger _logger;public DbTest(IServiceProvider serviceProvider, ILogger<DbTest> logger){_serviceProvider = serviceProvider;_logger = logger;}protected override async Task ExecuteAsync(CancellationToken stoppingToken){Task.Factory.StartNew(async () =>{while (true){try{using (var scop = _serviceProvider.CreateScope()){//单表var db = scop.ServiceProvider.GetService<IMyDbAccessor>();List<Base_UnitTest> insertList = new List<Base_UnitTest>();for (int i = 0; i < 100; i++){insertList.Add(new Base_UnitTest{Id = Guid.NewGuid().ToString(),Age = i,CreateTime = DateTime.Now,UserName = Guid.NewGuid().ToString()});}var single = new Base_UnitTest{Id = Guid.NewGuid().ToString(),Age = 100,CreateTime = DateTime.Now,UserName = Guid.NewGuid().ToString()};await db.InsertAsync(single);await db.InsertAsync(insertList);int count = await db.GetIQueryable<Base_UnitTest>().CountAsync();_logger.LogInformation("单表插入数据成功 当前数据量:{Count}", count);//分表var shardingDb = scop.ServiceProvider.GetService<IShardingDbAccessor>();await shardingDb.InsertAsync(single);await shardingDb.InsertAsync(insertList);count = await shardingDb.GetIShardingQueryable<Base_UnitTest>().CountAsync();_logger.LogInformation("分表插入数据成功 当前数据量:{Count}", count);}}catch (Exception ex){_logger.LogError(ex, "");}await Task.Delay(2000);}}, TaskCreationOptions.LongRunning);await Task.CompletedTask;}}
webapi的使用
[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{readonly IShardingDbAccessor _shardingDbAccessor;public TestController(IShardingDbAccessor shardingDbAccessor){_shardingDbAccessor = shardingDbAccessor;}[HttpGet]public async Task<string> Get(){List<Base_UnitTest> insertList = new List<Base_UnitTest>();for (int i = 0; i < 100; i++){insertList.Add(new Base_UnitTest{Id = Guid.NewGuid().ToString(),Age = i,CreateTime = DateTime.Now,UserName = Guid.NewGuid().ToString()});}await _shardingDbAccessor.InsertAsync(insertList);return "成功";}
}
备注:非分表用IDbAccessor,分表用IShardingDbAccessor