Skip to content

Commit ee0f6c1

Browse files
committed
1
1 parent 255398b commit ee0f6c1

File tree

23 files changed

+768
-192
lines changed

23 files changed

+768
-192
lines changed

README.md

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,44 @@ AbstractSimpleShardingYearKeyLongVirtualTableRoute |按时间戳 |yyyy | `>,>=,<
291291

292292
## 批量操作
293293

294-
批量操作将对应的dbcontext和数据进行分离由用户自己选择第三方框架比如zzz进行批量操作或者batchextension
294+
批量操作将对应的dbcontext和数据进行分离由用户自己选择第三方框架比如[`Z.EntityFramework.Plus.EFCore`](https://github.com/zzzprojects/EntityFramework-Plus) 进行批量操作或者 [`EFCore.BulkExtensions`](https://github.com/borisdj/EFCore.BulkExtensions) ,支持一切三方批量框架
295295
```c#
296-
后期支持
296+
var list = new List<SysUserMod>();
297+
///通过集合返回出对应的k-v归集通过事务开启
298+
var dbContexts = _defaultTableDbContext.BulkShardingEnumerable(list);
299+
300+
using (var tran = _defaultTableDbContext.Database.BeginTransaction())
301+
{
302+
dbContexts.ForEach(kv =>
303+
{
304+
kv.Key.BulkInsert(kv.Value);
305+
});
306+
dbContexts.ForEach(kv =>
307+
{
308+
kv.Key.BulkDelete(kv.Value);
309+
});
310+
dbContexts.ForEach(kv =>
311+
{
312+
kv.Key.BulkUpdate(kv.Value);
313+
});
314+
_defaultTableDbContext.SaveChanges();
315+
tran.Commit();
316+
}
317+
318+
319+
var dbContext2s = _defaultTableDbContext.BulkShardingExpression<SysUserMod>(o => o.Age > 100);
320+
using (var tran = _defaultTableDbContext.Database.BeginTransaction())
321+
{
322+
dbContext2s.ForEach(dbContext =>
323+
{
324+
dbContext.Set<SysUserMod>().Where(o => o.Age > 100).Update(o => new SysUserMod()
325+
{
326+
AgeGroup = 1000
327+
});
328+
});
329+
_defaultTableDbContext.SaveChanges();
330+
tran.Commit();
331+
}
297332
```
298333
## 手动路由
299334
```c#
@@ -327,10 +362,20 @@ ctor inject IShardingRouteManager shardingRouteManager
327362
[参考](https://github.com/xuejmnet/sharding-core/tree/main/samples/Samples.AutoByDate.SqlServer)
328363

329364
## 事务
330-
默认savechanges支持事务
365+
1.默认savechanges支持事务
331366
```c#
367+
332368
await _defaultShardingDbContext.SaveChangesAsync();
333-
369+
370+
```
371+
2.手动开启事务 [请参考微软](https://docs.microsoft.com/zh-cn/ef/core/saving/transactions)
372+
```c#
373+
using (var tran = _defaultTableDbContext.Database.BeginTransaction())
374+
{
375+
........
376+
_defaultTableDbContext.SaveChanges();
377+
tran.Commit();
378+
}
334379
```
335380
## 读写分离
336381
该框架目前已经支持单node的读写分离,后续框架将支持多node的读
@@ -398,7 +443,19 @@ var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserMod>().Ord
398443

399444

400445
# 注意事项
401-
该库的追踪是基于adonet的MARS(MultipleActiveResultSets=True;)所以基本不支持该特性的无法支持完美追踪
446+
使用该框架需要注意两点如果你的shardingdbcontext重写了以下服务可能无法使用 如果还想使用需要自己重写扩展[请参考](https://github.com/xuejmnet/sharding-core/blob/main/src/ShardingCore/DIExtension.cs)
447+
1.shardingdbcontext
448+
```c#
449+
return optionsBuilder.ReplaceService<IDbSetSource, ShardingDbSetSource>()
450+
.ReplaceService<IQueryCompiler, ShardingQueryCompiler>()
451+
.ReplaceService<IRelationalTransactionFactory, ShardingRelationalTransactionFactory>();
452+
```
453+
2.defaultdbcontext
454+
```c#
455+
return optionsBuilder.ReplaceService<IModelCacheKeyFactory, ShardingModelCacheKeyFactory>()
456+
.ReplaceService<IModelCustomizer, ShardingModelCustomizer<TShardingDbContext>>();
457+
458+
```
402459
,目前框架采用AppDomain.CurrentDomain.GetAssemblies();
403460
可能会导致程序集未被加载所以尽可能在api层加载所需要的dll
404461
使用时需要注意

nuget-publish.bat

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
:start
22
::定义版本
3-
set EFCORE2=2.2.0.17
4-
set EFCORE3=3.2.0.17
5-
set EFCORE5=5.2.0.17
3+
set EFCORE2=2.2.0.19
4+
set EFCORE3=3.2.0.19
5+
set EFCORE5=5.2.0.19
66

77
::删除所有bin与obj下的文件
88
@echo off

samples/Sample.SqlServer/Controllers/ValuesController.cs

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
using System.Threading.Tasks;
66
using Microsoft.AspNetCore.Mvc;
77
using Microsoft.EntityFrameworkCore;
8+
using Microsoft.EntityFrameworkCore.Storage;
89
using Microsoft.Extensions.Logging;
910
using Sample.SqlServer.DbContexts;
1011
using Sample.SqlServer.Domain.Entities;
1112
using ShardingCore.Core.QueryRouteManagers.Abstractions;
1213
using ShardingCore.DbContexts.VirtualDbContexts;
1314
using ShardingCore.Extensions;
15+
using Z.EntityFramework.Plus;
1416

1517
namespace Sample.SqlServer.Controllers
1618
{
@@ -26,7 +28,7 @@ public class ValuesController : ControllerBase
2628
private readonly DefaultShardingDbContext _defaultTableDbContext;
2729
private readonly IShardingRouteManager _shardingRouteManager;
2830

29-
public ValuesController(DefaultShardingDbContext defaultTableDbContext,IShardingRouteManager shardingRouteManager)
31+
public ValuesController(DefaultShardingDbContext defaultTableDbContext, IShardingRouteManager shardingRouteManager)
3032
{
3133
_defaultTableDbContext = defaultTableDbContext;
3234
_shardingRouteManager = shardingRouteManager;
@@ -36,17 +38,17 @@ public ValuesController(DefaultShardingDbContext defaultTableDbContext,ISharding
3638
public async Task<IActionResult> Get()
3739
{
3840
var sql = from ut in _defaultTableDbContext.Set<SysTest>()
39-
join u in _defaultTableDbContext.Set<SysUserMod>()
40-
on ut.UserId equals u.Id
41-
select new
42-
{
43-
ut.Id,
44-
userId=u.Id
45-
};
46-
var listAsync =await sql.ToListAsync();
41+
join u in _defaultTableDbContext.Set<SysUserMod>()
42+
on ut.UserId equals u.Id
43+
select new
44+
{
45+
ut.Id,
46+
userId = u.Id
47+
};
48+
var listAsync = await sql.ToListAsync();
4749
var resultx112331tt = await _defaultTableDbContext.Set<SysTest>().CountAsync();
4850
var resultx112331 = await _defaultTableDbContext.Set<SysUserMod>().CountAsync();
49-
var resultx11233411 = _defaultTableDbContext.Set<SysUserMod>().Count();
51+
var resultx11233411 = _defaultTableDbContext.Set<SysUserMod>().Count();
5052
var resultx11231 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Age == 198198).Select(o => o.Id).ContainsAsync("1981");
5153
var resultx1121 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").SumAsync(o => o.Age);
5254
var resultx111 = await _defaultTableDbContext.Set<SysUserMod>().FirstOrDefaultAsync(o => o.Id == "198");
@@ -88,11 +90,11 @@ on ut.UserId equals u.Id
8890
return Ok();
8991
}
9092
[HttpGet]
91-
public async Task<IActionResult> Get1([FromQuery] int p,[FromQuery]int s)
93+
public async Task<IActionResult> Get1([FromQuery] int p, [FromQuery] int s)
9294
{
9395
Stopwatch sp = new Stopwatch();
9496
sp.Start();
95-
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserMod>().OrderBy(o=>o.Age).ToShardingPageAsync(p, s);
97+
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToShardingPageAsync(p, s);
9698
sp.Stop();
9799
return Ok(new
98100
{
@@ -101,17 +103,59 @@ public async Task<IActionResult> Get1([FromQuery] int p,[FromQuery]int s)
101103
});
102104
}
103105
[HttpGet]
104-
public IActionResult Get2([FromQuery] int p,[FromQuery]int s)
106+
public IActionResult Get2([FromQuery] int p, [FromQuery] int s)
105107
{
106108
Stopwatch sp = new Stopwatch();
107109
sp.Start();
108-
var shardingPageResultAsync = _defaultTableDbContext.Set<SysUserMod>().OrderBy(o=>o.Age).ToShardingPage(p, s);
110+
var shardingPageResultAsync = _defaultTableDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToShardingPage(p, s);
109111
sp.Stop();
110112
return Ok(new
111113
{
112114
sp.ElapsedMilliseconds,
113115
shardingPageResultAsync
114116
});
115117
}
118+
[HttpGet]
119+
public IActionResult Get3()
120+
{
121+
122+
var dbContext2s = _defaultTableDbContext.BulkShardingExpression<SysUserMod>(o => o.Age > 100);
123+
using (var tran = _defaultTableDbContext.Database.BeginTransaction())
124+
{
125+
dbContext2s.ForEach(dbContext =>
126+
{
127+
dbContext.Set<SysUserMod>().Where(o => o.Age > 100).Update(o => new SysUserMod()
128+
{
129+
AgeGroup = 1000
130+
});
131+
});
132+
_defaultTableDbContext.SaveChanges();
133+
tran.Commit();
134+
}
135+
var list = new List<SysUserMod>();
136+
var dbContexts = _defaultTableDbContext.BulkShardingEnumerable(list);
137+
138+
using (var tran = _defaultTableDbContext.Database.BeginTransaction())
139+
{
140+
dbContexts.ForEach(kv =>
141+
{
142+
kv.Key.BulkInsert(kv.Value);
143+
});
144+
dbContexts.ForEach(kv =>
145+
{
146+
kv.Key.BulkDelete(kv.Value);
147+
});
148+
dbContexts.ForEach(kv =>
149+
{
150+
kv.Key.BulkUpdate(kv.Value);
151+
});
152+
_defaultTableDbContext.SaveChanges();
153+
tran.Commit();
154+
}
155+
156+
157+
return Ok();
158+
}
159+
116160
}
117-
}
161+
}

samples/Sample.SqlServer/Sample.SqlServer.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
</PropertyGroup>
77

88
<ItemGroup>
9+
<PackageReference Include="EFCore.BulkExtensions" Version="5.3.8" />
910
<PackageReference Include="EfCore.SqlServer2008Query" Version="1.0.4" />
1011
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.9" />
12+
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="5.2.9" />
1113
</ItemGroup>
1214

1315
<ItemGroup>

samples/Sample.SqlServer/Startup.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
using Microsoft.EntityFrameworkCore;
44
using Microsoft.EntityFrameworkCore.Query;
55
using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal;
6+
using Microsoft.EntityFrameworkCore.Storage;
67
using Microsoft.Extensions.DependencyInjection;
78
using Microsoft.Extensions.Hosting;
89
using Microsoft.Extensions.Logging;
910
using Sample.SqlServer.DbContexts;
1011
using Sample.SqlServer.Shardings;
1112
using ShardingCore;
13+
using ShardingCore.EFCores;
1214

1315
namespace Sample.SqlServer
1416
{
@@ -30,8 +32,8 @@ public void ConfigureServices(IServiceCollection services)
3032
o => o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDB;Integrated Security=True;")
3133
, op =>
3234
{
33-
op.EnsureCreatedWithOutShardingTable = false;
34-
op.CreateShardingTableOnStart = false;
35+
op.EnsureCreatedWithOutShardingTable = true;
36+
op.CreateShardingTableOnStart = true;
3537
op.UseShardingOptionsBuilder(
3638
(connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),//使用dbconnection创建dbcontext支持事务
3739
(conStr,builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)

samples/Samples.AbpSharding/AbstractShardingAbpDbContext.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
4+
using System.Data.Common;
45
using System.Linq;
6+
using System.Linq.Expressions;
57
using System.Threading;
68
using System.Threading.Tasks;
79
using Abp.EntityFrameworkCore;
@@ -21,7 +23,7 @@
2123

2224
namespace Samples.AbpSharding
2325
{
24-
public abstract class AbstractShardingAbpDbContext<T> : AbpDbContext, IShardingTableDbContext<T> where T : AbpDbContext, IShardingTableDbContext
26+
public abstract class AbstractShardingAbpDbContext<T> : AbpDbContext, IShardingDbContext<T> where T : AbpDbContext, IShardingTableDbContext
2527
{
2628

2729

@@ -127,6 +129,28 @@ public DbContext CreateGenericDbContext<T>(T entity) where T : class
127129

128130
return GetDbContext(true, _routeTailFactory.Create(tail));
129131
}
132+
133+
public IEnumerable<DbContext> CreateExpressionDbContext<TEntity>(Expression<Func<TEntity, bool>> where)
134+
where TEntity : class
135+
{
136+
if (typeof(TEntity).IsShardingTable())
137+
{
138+
var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, typeof(TEntity)).RouteTo(new TableRouteConfig(predicate:where));
139+
if (physicTable.IsEmpty())
140+
throw new ShardingCoreException($"{where.ShardingPrint()} cant found any physic table");
141+
return physicTable.Select(o => GetDbContext(true, _routeTailFactory.Create(o.Tail)));
142+
}
143+
else
144+
{
145+
return new[] {GetDbContext(true, _routeTailFactory.Create(string.Empty))};
146+
}
147+
}
148+
149+
public void UseShardingTransaction(DbTransaction transaction)
150+
{
151+
throw new NotImplementedException();
152+
}
153+
130154
public override EntityEntry Add(object entity)
131155
{
132156
return CreateGenericDbContext(entity).Add(entity);

src/ShardingCore/DIExtension.cs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using ShardingCore.Sharding.Abstractions;
1313
using ShardingCore.TableCreator;
1414
using System;
15+
using Microsoft.EntityFrameworkCore.Storage;
1516
using ShardingCore.Core.QueryRouteManagers;
1617
using ShardingCore.Core.QueryRouteManagers.Abstractions;
1718
using ShardingCore.Core.ShardingPage;
@@ -38,7 +39,7 @@ public static IServiceCollection AddShardingDbContext<TShardingDbContext, TActua
3839
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
3940
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
4041
where TActualDbContext : DbContext, IShardingTableDbContext
41-
where TShardingDbContext : DbContext, IShardingTableDbContext<TActualDbContext>
42+
where TShardingDbContext : DbContext, IShardingDbContext<TActualDbContext>
4243
{
4344
if (configure == null)
4445
throw new ArgumentNullException($"AddShardingDbContext params is null :{nameof(configure)}");
@@ -60,7 +61,13 @@ public static IServiceCollection AddShardingDbContext<TShardingDbContext, TActua
6061
Action<DbContextOptionsBuilder> shardingOptionAction = option =>
6162
{
6263
optionsAction?.Invoke(option);
64+
#if !EFCORE2
6365
option.UseSharding();
66+
67+
#endif
68+
#if EFCORE2
69+
option.UseSharding<TShardingDbContext>();
70+
#endif
6471
};
6572
services.AddDbContext<TShardingDbContext>(shardingOptionAction, contextLifetime, optionsLifetime);
6673
services.AddInternalShardingCore();
@@ -75,7 +82,7 @@ public static IServiceCollection AddShardingDbContext<TShardingDbContext, TActua
7582
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
7683
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
7784
where TActualDbContext : DbContext, IShardingTableDbContext
78-
where TShardingDbContext : DbContext, IShardingTableDbContext<TActualDbContext>
85+
where TShardingDbContext : DbContext, IShardingDbContext<TActualDbContext>
7986
{
8087
if (configure == null)
8188
throw new ArgumentNullException($"AddShardingDbContext params is null :{nameof(configure)}");
@@ -97,7 +104,13 @@ public static IServiceCollection AddShardingDbContext<TShardingDbContext, TActua
97104
Action<IServiceProvider, DbContextOptionsBuilder> shardingOptionAction = (sp, option) =>
98105
{
99106
optionsAction?.Invoke(sp,option);
107+
#if !EFCORE2
100108
option.UseSharding();
109+
110+
#endif
111+
#if EFCORE2
112+
option.UseSharding<TShardingDbContext>();
113+
#endif
101114
};
102115
services.AddDbContext<TShardingDbContext>(shardingOptionAction, contextLifetime, optionsLifetime);
103116
services.AddInternalShardingCore();
@@ -132,12 +145,25 @@ internal static IServiceCollection AddInternalShardingCore(this IServiceCollecti
132145
services.AddSingleton<IShardingBootstrapper, ShardingBootstrapper>();
133146
return services;
134147
}
135-
148+
#if !EFCORE2
136149
internal static DbContextOptionsBuilder UseSharding(this DbContextOptionsBuilder optionsBuilder)
137150
{
138151
return optionsBuilder.ReplaceService<IDbSetSource, ShardingDbSetSource>()
139-
.ReplaceService<IQueryCompiler, ShardingQueryCompiler>();
152+
.ReplaceService<IQueryCompiler, ShardingQueryCompiler>()
153+
.ReplaceService<IRelationalTransactionFactory, ShardingRelationalTransactionFactory>();
154+
}
155+
156+
#endif
157+
#if EFCORE2
158+
internal static DbContextOptionsBuilder UseSharding<TShardingDbContext>(this DbContextOptionsBuilder optionsBuilder) where TShardingDbContext : DbContext, IShardingDbContext
159+
{
160+
return optionsBuilder.ReplaceService<IDbSetSource, ShardingDbSetSource>()
161+
.ReplaceService<IQueryCompiler, ShardingQueryCompiler>()
162+
.ReplaceService<IRelationalTransactionFactory, ShardingRelationalTransactionFactory<TShardingDbContext>>();
140163
}
164+
165+
#endif
166+
141167
internal static DbContextOptionsBuilder UseInnerDbContextSharding<TShardingDbContext>(this DbContextOptionsBuilder optionsBuilder) where TShardingDbContext:DbContext,IShardingDbContext
142168
{
143169
return optionsBuilder.ReplaceService<IModelCacheKeyFactory, ShardingModelCacheKeyFactory>()

0 commit comments

Comments
 (0)