Skip to content

Commit a66a19d

Browse files
committed
#11 support auto track while select entity is dbcontext model
1 parent 97d2a76 commit a66a19d

23 files changed

+464
-130
lines changed

samples/Sample.BulkConsole/Program.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
using Sample.BulkConsole.DbContexts;
1010
using Sample.BulkConsole.Entities;
1111
using ShardingCore;
12+
using ShardingCore.Core.PhysicTables;
13+
using ShardingCore.Core.VirtualDatabase.VirtualTables;
1214
using ShardingCore.Extensions;
15+
using ShardingCore.TableCreator;
1316

1417
namespace Sample.BulkConsole
1518
{
@@ -41,6 +44,25 @@ static void Main(string[] args)
4144
using (var serviceScope = serviceProvider.CreateScope())
4245
{
4346
var myShardingDbContext = serviceScope.ServiceProvider.GetService<MyShardingDbContext>();
47+
48+
var virtualTableManager = serviceScope.ServiceProvider.GetService<IVirtualTableManager<MyShardingDbContext>>();
49+
var virtualTable = virtualTableManager.GetVirtualTable(typeof(Order));
50+
if (virtualTable == null)
51+
{
52+
return;
53+
}
54+
var now1 = DateTime.Now.Date.AddDays(2);
55+
var tail = virtualTable.GetVirtualRoute().ShardingKeyToTail(now1);
56+
try
57+
{
58+
virtualTableManager.AddPhysicTable(virtualTable, new DefaultPhysicTable(virtualTable, tail));
59+
var tableCreator = serviceProvider.GetService< IShardingTableCreator < MyShardingDbContext >> ();
60+
tableCreator.CreateTable("ds0", typeof(Order), tail);
61+
}
62+
catch (Exception e)
63+
{
64+
//ignore
65+
}
4466
if (!myShardingDbContext.Set<Order>().Any())
4567
{
4668
var begin = DateTime.Now.Date.AddDays(-3);
@@ -62,16 +84,13 @@ static void Main(string[] args)
6284
}
6385

6486
var startNew = Stopwatch.StartNew();
65-
var bulkShardingEnumerable = myShardingDbContext.BulkShardingEnumerable(orders);
87+
var bulkShardingEnumerable = myShardingDbContext.BulkShardingTableEnumerable(orders);
6688
startNew.Stop();
6789
Console.WriteLine($"订单总数:{i}条,myShardingDbContext.BulkShardingEnumerable(orders)用时:{startNew.ElapsedMilliseconds}毫秒");
6890
startNew.Restart();
6991
foreach (var dataSourceMap in bulkShardingEnumerable)
7092
{
71-
foreach (var tailMap in dataSourceMap.Value)
72-
{
73-
tailMap.Key.BulkInsert(tailMap.Value.ToList());
74-
}
93+
dataSourceMap.Key.BulkInsert(dataSourceMap.Value.ToList());
7594
}
7695
startNew.Stop();
7796
Console.WriteLine($"订单总数:{i}条,myShardingDbContext.BulkInsert(orders)用时:{startNew.ElapsedMilliseconds}毫秒");
@@ -84,7 +103,7 @@ static void Main(string[] args)
84103
var startNew1 = Stopwatch.StartNew();
85104

86105
int skip = 0, take = 10;
87-
for (int i = 1000; i < 20000; i++)
106+
for (int i = 20000; i < 30000; i++)
88107
{
89108
skip = take * i;
90109
startNew1.Restart();

samples/Sample.SqlServer/Controllers/ValuesController.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ on ut.UserId equals u.Id
7171
var sresult = _defaultTableDbContext.Set<SysUserMod>().ToList();
7272

7373
var sysUserMod98 = result.FirstOrDefault(o => o.Id == "98");
74-
_defaultTableDbContext.Attach(sysUserMod98);
7574
sysUserMod98.Name = "name_update" + new Random().Next(1, 99) + "_98";
76-
_defaultTableDbContext.Attach(sysUserMod98);
7775
await _defaultTableDbContext.SaveChangesAsync();
7876
var stu = new STU() { Id = "198" };
7977
var sresultx111x = _defaultTableDbContext.Set<SysUserMod>().FirstOrDefault(o => o.Id == stu.Id);

samples/Sample.SqlServer/Startup.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public void ConfigureServices(IServiceCollection services)
3737
{
3838
o.CreateShardingTableOnStart = true;
3939
o.EnsureCreatedWithOutShardingTable = true;
40+
o.AutoTrackEntity = true;
41+
//o.AutoTrackEntity = true;
4042
})
4143
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)
4244
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Text;
4+
using Microsoft.EntityFrameworkCore;
5+
using ShardingCore.Sharding.Abstractions;
6+
7+
namespace ShardingCore.Core.TrackerManagers
8+
{
9+
/*
10+
* @Author: xjm
11+
* @Description:
12+
* @Date: 2021/9/23 22:34:16
13+
* @Ver: 1.0
14+
15+
*/
16+
public interface ITrackerManager<TShardingDbContext> where TShardingDbContext:DbContext,IShardingDbContext
17+
{
18+
bool AddDbContextModel(Type entityType);
19+
bool EntityUseTrack(Type entityType);
20+
}
21+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using Microsoft.EntityFrameworkCore;
6+
using ShardingCore.Sharding.Abstractions;
7+
8+
namespace ShardingCore.Core.TrackerManagers
9+
{
10+
/*
11+
* @Author: xjm
12+
* @Description:
13+
* @Date: 2021/9/23 22:37:59
14+
* @Ver: 1.0
15+
16+
*/
17+
public class TrackerManager<TShardingDbContext>: ITrackerManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
18+
{
19+
private readonly IShardingConfigOption _shardingConfigOption;
20+
private readonly ISet<Type> _dbContextModels = new HashSet<Type>();
21+
22+
public TrackerManager(IEnumerable<IShardingConfigOption> shardingConfigOptions)
23+
{
24+
_shardingConfigOption = shardingConfigOptions.FirstOrDefault(o=>o.ShardingDbContextType==typeof(TShardingDbContext));
25+
}
26+
public bool AddDbContextModel(Type entityType)
27+
{
28+
return _dbContextModels.Add(entityType);
29+
}
30+
31+
public bool EntityUseTrack(Type entityType)
32+
{
33+
if (!_shardingConfigOption.AutoTrackEntity)
34+
return false;
35+
return _dbContextModels.Contains(entityType);
36+
}
37+
}
38+
}

src/ShardingCore/DIExtension.cs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,27 @@
33
using Microsoft.EntityFrameworkCore.Internal;
44
using Microsoft.EntityFrameworkCore.Query.Internal;
55
using Microsoft.Extensions.DependencyInjection;
6-
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
7-
using ShardingCore.Core.VirtualTables;
8-
using ShardingCore.DbContexts;
9-
using ShardingCore.EFCores;
10-
using ShardingCore.Helpers;
11-
using ShardingCore.Sharding;
12-
using ShardingCore.Sharding.Abstractions;
13-
using ShardingCore.TableCreator;
14-
using System;
15-
using Microsoft.EntityFrameworkCore.Storage;
166
using Microsoft.Extensions.DependencyInjection.Extensions;
177
using ShardingCore.Core.QueryRouteManagers;
188
using ShardingCore.Core.QueryRouteManagers.Abstractions;
199
using ShardingCore.Core.ShardingPage;
2010
using ShardingCore.Core.ShardingPage.Abstractions;
11+
using ShardingCore.Core.TrackerManagers;
2112
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
2213
using ShardingCore.Core.VirtualDatabase.VirtualTables;
2314
using ShardingCore.Core.VirtualRoutes;
2415
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
2516
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
17+
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
18+
using ShardingCore.DbContexts;
2619
using ShardingCore.DIExtensions;
27-
using ShardingCore.Sharding.ReadWriteConfigurations;
28-
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
20+
using ShardingCore.EFCores;
21+
using ShardingCore.Helpers;
22+
using ShardingCore.Sharding;
23+
using ShardingCore.Sharding.Abstractions;
2924
using ShardingCore.Sharding.ShardingQueryExecutors;
25+
using ShardingCore.TableCreator;
26+
using System;
3027

3128
namespace ShardingCore
3229
{
@@ -186,6 +183,7 @@ public static ShardingCoreConfigBuilder<TShardingDbContext, TActualDbContext> Ad
186183

187184
internal static IServiceCollection AddInternalShardingCore(this IServiceCollection services)
188185
{
186+
services.TryAddSingleton(typeof(ITrackerManager<>),typeof(TrackerManager<>));
189187
services.TryAddSingleton(typeof(IStreamMergeContextFactory<>),typeof(StreamMergeContextFactory<>));
190188
services.TryAddSingleton(typeof(IShardingTableCreator<>),typeof(ShardingTableCreator<>));
191189
//虚拟数据源管理

src/ShardingCore/DIExtensions/ShardingCoreConfigBuilder.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public ShardingQueryBuilder<TShardingDbContext, TActualDbContext> Begin(Action<S
3636
var shardingCoreBeginOptions = new ShardingCoreBeginOptions();
3737
shardingCoreBeginOptionsConfigure?.Invoke(shardingCoreBeginOptions);
3838
ShardingConfigOption.EnsureCreatedWithOutShardingTable = shardingCoreBeginOptions.EnsureCreatedWithOutShardingTable;
39+
ShardingConfigOption.AutoTrackEntity = shardingCoreBeginOptions.AutoTrackEntity;
3940
ShardingConfigOption.CreateShardingTableOnStart = shardingCoreBeginOptions.CreateShardingTableOnStart;
4041
ShardingConfigOption.IgnoreCreateTableError = shardingCoreBeginOptions.IgnoreCreateTableError;
4142
return new ShardingQueryBuilder<TShardingDbContext, TActualDbContext>(this);
@@ -69,6 +70,10 @@ public class ShardingCoreBeginOptions
6970
/// 是否需要在启动时创建分表
7071
/// </summary>
7172
public bool? CreateShardingTableOnStart { get; set; }
73+
/// <summary>
74+
/// 是否自动追踪实体
75+
/// </summary>
76+
public bool AutoTrackEntity { get; set; }
7277

7378
/// <summary>
7479
/// 忽略建表时的错误

src/ShardingCore/EFCores/ShardingQueryCompiler.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
using Microsoft.EntityFrameworkCore.Infrastructure;
2+
using Microsoft.EntityFrameworkCore.Internal;
23
using Microsoft.EntityFrameworkCore.Query;
34
using Microsoft.EntityFrameworkCore.Query.Internal;
4-
using ShardingCore.Exceptions;
5-
using ShardingCore.Extensions;
65
using ShardingCore.Sharding.Abstractions;
7-
using ShardingCore.Sharding.StreamMergeEngines;
8-
using ShardingCore.Sharding.StreamMergeEngines.Abstractions;
9-
using ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines;
106
using System;
117
using System.Collections.Generic;
12-
using System.Linq;
138
using System.Linq.Expressions;
149
using System.Threading;
1510
using System.Threading.Tasks;
16-
using Microsoft.EntityFrameworkCore.Internal;
1711

1812

1913
namespace ShardingCore.EFCores

src/ShardingCore/Extensions/DbContextExtension.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using Microsoft.Extensions.Caching.Memory;
1212
using Microsoft.Extensions.DependencyInjection;
1313
using ShardingCore.Core;
14+
using ShardingCore.Utils;
1415

1516
namespace ShardingCore.Extensions
1617
{
@@ -25,9 +26,9 @@ public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContex
2526
var contextModel = dbContext.Model as Model;
2627

2728
#if EFCORE5
28-
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
29+
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
2930
var valueTuples =
30-
contextModelRelationalModel.Tables.Where(o=>o.Value.EntityTypeMappings.Any(m=>m.EntityType.ClrType.IsShardingTable())).Select(o=>o.Key).ToList();
31+
contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => m.EntityType.ClrType.IsShardingTable())).Select(o => o.Key).ToList();
3132
for (int i = 0; i < valueTuples.Count; i++)
3233
{
3334
contextModelRelationalModel.Tables.Remove(valueTuples[i]);
@@ -53,7 +54,7 @@ public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbCo
5354
Type shardingType)
5455
{
5556
var contextModel = dbContext.Model as Model;
56-
57+
5758
#if EFCORE5
5859
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
5960
var valueTuples = contextModelRelationalModel.Tables
@@ -154,5 +155,24 @@ public static object GetModelCacheSyncObject(this DbContext dbContext)
154155

155156
private static object sLock = new object();
156157

158+
public static TEntity GetAttachedEntity<TEntity>(this DbContext context, TEntity entity) where TEntity:class
159+
{
160+
if (entity == null) { throw new ArgumentNullException(nameof(entity)); }
161+
162+
var primaryKeyValue = ShardingKeyUtil.GetPrimaryKeyValue(entity);
163+
if (primaryKeyValue == null)
164+
return null;
165+
var entry = context.ChangeTracker.Entries<TEntity>().FirstOrDefault(e => primaryKeyValue.Equals(ShardingKeyUtil.GetPrimaryKeyValue(e.Entity)));
166+
if (entry != null)
167+
{
168+
if (entry.State != EntityState.Detached)
169+
{
170+
return entry.Entity;
171+
}
172+
}
173+
174+
return null;
175+
}
176+
157177
}
158178
}

src/ShardingCore/Extensions/IShardingQueryableExtension.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ internal static IQueryable<T> RemoveAnyOrderBy<T>(this IQueryable<T> source)
6262
return (IQueryable<T>) source.Provider.CreateQuery(expression);
6363
}
6464

65+
internal static bool? GetIsNoTracking<T>(this IQueryable<T> source)
66+
{
67+
var queryableTrackingDiscoverVisitor = new QueryableTrackingDiscoverVisitor();
68+
queryableTrackingDiscoverVisitor.Visit(source.Expression);
69+
return queryableTrackingDiscoverVisitor.IsNoTracking;
70+
}
71+
6572
/// <summary>
6673
/// 切换数据源,保留原数据源中的Expression
6774
/// </summary>

0 commit comments

Comments
 (0)