diff --git a/src/ShardingCore/Core/DbContextTypeAwares/DbContextTypeAware.cs b/src/ShardingCore/Core/DbContextTypeAwares/DbContextTypeAware.cs index 68c57171..6847cb3d 100644 --- a/src/ShardingCore/Core/DbContextTypeAwares/DbContextTypeAware.cs +++ b/src/ShardingCore/Core/DbContextTypeAwares/DbContextTypeAware.cs @@ -1,17 +1,18 @@ using System; -namespace ShardingCore.Core.DbContextTypeAwares; - -public class DbContextTypeAware:IDbContextTypeAware +namespace ShardingCore.Core.DbContextTypeAwares { - private readonly Type _dbContextType; + public class DbContextTypeAware : IDbContextTypeAware + { + private readonly Type _dbContextType; - public DbContextTypeAware(Type dbContextType) - { - _dbContextType = dbContextType; + public DbContextTypeAware(Type dbContextType) + { + _dbContextType = dbContextType; + } + public Type GetContextType() + { + return _dbContextType; + } } - public Type GetContextType() - { - return _dbContextType; - } -} \ No newline at end of file +} diff --git a/src/ShardingCore/Core/DbContextTypeAwares/IDbContextTypeAware.cs b/src/ShardingCore/Core/DbContextTypeAwares/IDbContextTypeAware.cs index 3030e59a..a3936b24 100644 --- a/src/ShardingCore/Core/DbContextTypeAwares/IDbContextTypeAware.cs +++ b/src/ShardingCore/Core/DbContextTypeAwares/IDbContextTypeAware.cs @@ -1,8 +1,9 @@ using System; -namespace ShardingCore.Core.DbContextTypeAwares; - -public interface IDbContextTypeAware +namespace ShardingCore.Core.DbContextTypeAwares { - Type GetContextType(); -} \ No newline at end of file + public interface IDbContextTypeAware + { + Type GetContextType(); + } +} diff --git a/src/ShardingCore/Core/RuntimeContexts/IShardingRuntimeContext`1.cs b/src/ShardingCore/Core/RuntimeContexts/IShardingRuntimeContext`1.cs index 84afd23a..cea95d58 100644 --- a/src/ShardingCore/Core/RuntimeContexts/IShardingRuntimeContext`1.cs +++ b/src/ShardingCore/Core/RuntimeContexts/IShardingRuntimeContext`1.cs @@ -1,8 +1,9 @@ using ShardingCore.Sharding.Abstractions; -namespace ShardingCore.Core.RuntimeContexts; - -public interface IShardingRuntimeContext:IShardingRuntimeContext where TDbContext:IShardingDbContext +namespace ShardingCore.Core.RuntimeContexts { - -} \ No newline at end of file + public interface IShardingRuntimeContext : IShardingRuntimeContext where TDbContext : IShardingDbContext + { + + } +} diff --git a/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore2_6.cs b/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs similarity index 93% rename from src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore2_6.cs rename to src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs index 5b00eb16..c5ebfbb1 100644 --- a/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore2_6.cs +++ b/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore.cs @@ -1,5 +1,4 @@ -#if SHARDINGCORE2_6 - + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -33,21 +32,21 @@ namespace ShardingCore.Extensions /// public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext) { -#if !EFCORE2 && !NETSTANDARD2_0 && !EFCORE3 && !NETSTANDARD2_1 && !EFCORE5 && !EFCORE6 +#if !EFCORE2 && !EFCORE3 && !EFCORE5 && !EFCORE6 && !EFCORE7 throw new NotImplementedException(); #endif -#if EFCORE6 +#if EFCORE6 ||EFCORE7 - var contextModel = dbContext.GetService().Model; ; + var contextModel = dbContext.GetService().Model; #endif -#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 || EFCORE5 || NETSTANDARD2_1 +#if EFCORE2 || EFCORE3 || EFCORE5 var contextModel = dbContext.Model as Model; #endif var shardingRuntimeContext = dbContext.GetShardingRuntimeContext(); var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager(); -#if EFCORE6 +#if EFCORE6 || EFCORE7 var entityTypes = contextModel.GetEntityTypes(); foreach (var entityType in entityTypes) { @@ -64,7 +63,7 @@ namespace ShardingCore.Extensions contextModelRelationalModel.Tables.Remove(valueTuples[i]); } #endif -#if EFCORE5 || NETSTANDARD2_1 +#if EFCORE5 var entityTypes = contextModel.GetEntityTypes(); foreach (var entityType in entityTypes) { @@ -81,7 +80,7 @@ namespace ShardingCore.Extensions contextModelRelationalModel.Tables.Remove(valueTuples[i]); } #endif -#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 +#if EFCORE2 || EFCORE3 var entityTypes = contextModel.GetFieldValue("_entityTypes") as SortedDictionary; foreach (var entityType in entityTypes) @@ -133,14 +132,14 @@ namespace ShardingCore.Extensions /// public static void RemoveDbContextAllRelationModelWithoutShardingDataSourceOnly(this DbContext dbContext) { -#if !EFCORE2 && !NETSTANDARD2_0 && !EFCORE3 && !NETSTANDARD2_1 && !EFCORE5 && !EFCORE6 +#if !EFCORE2&& !EFCORE3 && !EFCORE5 && !EFCORE6 && !EFCORE7 throw new NotImplementedException(); #endif -#if EFCORE6 +#if EFCORE6 || EFCORE7 var contextModel = dbContext.GetService().Model; ; #endif -#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 || EFCORE5 || NETSTANDARD2_1 +#if EFCORE2 || EFCORE3 || EFCORE5 var contextModel = dbContext.Model as Model; #endif @@ -164,7 +163,7 @@ namespace ShardingCore.Extensions contextModelRelationalModel.Tables.Remove(valueTuples[i]); } #endif -#if EFCORE5 || NETSTANDARD2_1 +#if EFCORE5 var entityTypes = contextModel.GetEntityTypes(); foreach (var entityType in entityTypes) { @@ -181,7 +180,7 @@ namespace ShardingCore.Extensions contextModelRelationalModel.Tables.Remove(valueTuples[i]); } #endif -#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 +#if EFCORE2 || EFCORE3 var entityTypes = contextModel.GetFieldValue("_entityTypes") as SortedDictionary; @@ -205,14 +204,14 @@ namespace ShardingCore.Extensions /// public static void RemoveDbContextAllRelationModel(this DbContext dbContext) { -#if !EFCORE2 && !NETSTANDARD2_0 && !EFCORE3 && !NETSTANDARD2_1 && !EFCORE5 && !EFCORE6 +#if !EFCORE2 && !EFCORE3 && !EFCORE5 && !EFCORE6&& !EFCORE7 throw new NotImplementedException(); #endif -#if EFCORE6 +#if EFCORE6|| EFCORE7 var contextModel = dbContext.GetService().Model; ; #endif -#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 || EFCORE5 || NETSTANDARD2_1 +#if EFCORE2 || EFCORE3 || EFCORE5 var contextModel = dbContext.Model as Model; #endif @@ -221,11 +220,11 @@ namespace ShardingCore.Extensions var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; contextModelRelationalModel.Tables.Clear(); #endif -#if EFCORE5 || NETSTANDARD2_1 +#if EFCORE5 var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel; contextModelRelationalModel.Tables.Clear(); #endif -#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 +#if EFCORE2 || EFCORE3 var entityTypes = contextModel.GetFieldValue("_entityTypes") as SortedDictionary; entityTypes.Clear(); @@ -240,14 +239,14 @@ namespace ShardingCore.Extensions public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbContext dbContext, Type shardingType) { -#if !EFCORE2 && !NETSTANDARD2_0 && !EFCORE3 && !NETSTANDARD2_1 && !EFCORE5 && !EFCORE6 +#if !EFCORE2 && !EFCORE3 && !EFCORE5 && !EFCORE6&& !EFCORE7 1 #endif -#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 ||EFCORE5 || NETSTANDARD2_1 +#if EFCORE2 || EFCORE3 || EFCORE5 var contextModel = dbContext.Model as Model; #endif -#if EFCORE6 +#if EFCORE6 || EFCORE7 var contextModel = dbContext.GetService().Model; var entityTypes = contextModel.GetEntityTypes(); foreach (var entityType in entityTypes) @@ -268,7 +267,7 @@ namespace ShardingCore.Extensions } #endif -#if EFCORE5 || NETSTANDARD2_1 +#if EFCORE5 var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel; var entityTypes = contextModel.GetEntityTypes(); @@ -287,7 +286,7 @@ namespace ShardingCore.Extensions contextModelRelationalModel.Tables.Remove(valueTuples[i]); } #endif -#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 +#if EFCORE2 || EFCORE3 var entityTypes = contextModel.GetFieldValue("_entityTypes") as SortedDictionary; @@ -318,10 +317,10 @@ namespace ShardingCore.Extensions /// public static void RemoveModelCache(this DbContext dbContext) { -#if !EFCORE2 && !NETSTANDARD2_0 && !EFCORE3 && !NETSTANDARD2_1 && !EFCORE5 && !EFCORE6 +#if !EFCORE2 && !EFCORE3 && !EFCORE5 && !EFCORE6 && !EFCORE7 throw new NotImplementedException(); #endif -#if EFCORE6 +#if EFCORE6 || EFCORE7 var shardingModelSource = dbContext.GetService() as IShardingModelSource; var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); object key1 = modelCacheKeyFactory.Create(dbContext,true); @@ -329,13 +328,13 @@ namespace ShardingCore.Extensions object key2 = modelCacheKeyFactory.Create(dbContext,false); shardingModelSource.Remove(key2); #endif -#if EFCORE5 || NETSTANDARD2_1 +#if EFCORE5 var shardingModelSource = dbContext.GetService() as IShardingModelSource; var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); object key1 = modelCacheKeyFactory.Create(dbContext); shardingModelSource.Remove(key1); #endif -#if EFCORE3 || NETSTANDARD2_0 +#if EFCORE3 var shardingModelSource = dbContext.GetService() as IShardingModelSource; var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); @@ -415,4 +414,3 @@ namespace ShardingCore.Extensions } } -#endif \ No newline at end of file diff --git a/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore7.cs b/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore7.cs deleted file mode 100644 index 0c75f395..00000000 --- a/src/ShardingCore/Extensions/DbContextExtensions/DbContextExtensionShardingCore7.cs +++ /dev/null @@ -1,203 +0,0 @@ -#if EFCORE7 -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.EFCores; -using ShardingCore.Exceptions; - -namespace ShardingCore.Extensions -{ - [ExcludeFromCodeCoverage] - public static class DbContextExtension - { - /// - /// 移除所有的分表关系的模型 - /// - /// - public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext) - { - - var contextModel = dbContext.GetService().Model; ; - var shardingRuntimeContext = dbContext.GetShardingRuntimeContext(); - var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager(); - - var entityTypes = contextModel.GetEntityTypes(); - foreach (var entityType in entityTypes) - { - if (entityType.GetFieldValue("_data") is List _data) - { - _data.Clear(); - } - } - var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; - var valueTuples = - contextModelRelationalModel.Tables.Where(o =>o.Value.EntityTypeMappings.Any(m => entityMetadataManager.IsShardingTable(m.EntityType.ClrType))).Select(o => o.Key).ToList(); - for (int i = 0; i < valueTuples.Count; i++) - { - contextModelRelationalModel.Tables.Remove(valueTuples[i]); - } - } - /// - /// 移除所有除了仅分库的 - /// - /// - public static void RemoveDbContextAllRelationModelWithoutShardingDataSourceOnly(this DbContext dbContext) - { - - var contextModel = dbContext.GetService().Model; ; - - var shardingRuntimeContext = dbContext.GetShardingRuntimeContext(); - var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager(); - - var entityTypes = contextModel.GetEntityTypes(); - foreach (var entityType in entityTypes) - { - if (entityType.GetFieldValue("_data") is List _data) - { - _data.Clear(); - } - } - var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; - var valueTuples = - contextModelRelationalModel.Tables.Where(o => o.Value.EntityTypeMappings.Any(m => !entityMetadataManager.IsShardingDataSource(m.EntityType.ClrType) ||entityMetadataManager.TryGet(m.EntityType.ClrType)==null)).Select(o => o.Key).ToList(); - for (int i = 0; i < valueTuples.Count; i++) - { - contextModelRelationalModel.Tables.Remove(valueTuples[i]); - } - - } - /// - /// 移除所有的表 - /// - /// - public static void RemoveDbContextAllRelationModel(this DbContext dbContext) - { - - var contextModel = dbContext.GetService().Model; ; - - var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; - contextModelRelationalModel.Tables.Clear(); - } - - /// - /// 移除所有的除了我指定的那个类型 - /// - /// - /// - public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbContext dbContext, - Type shardingType) - { - var contextModel = dbContext.GetService().Model; - var entityTypes = contextModel.GetEntityTypes(); - foreach (var entityType in entityTypes) - { - if (entityType.GetFieldValue("_data") is List _data) - { - _data.Clear(); - } - } - var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; - var valueTuples = - contextModelRelationalModel.Tables - .Where(o => o.Value.EntityTypeMappings.All(m => m.EntityType.ClrType != shardingType)) - .Select(o => o.Key).ToList(); - for (int i = 0; i < valueTuples.Count; i++) - { - contextModelRelationalModel.Tables.Remove(valueTuples[i]); - } - - } - - public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbContext dbContext) - where T:class - { - RemoveDbContextRelationModelSaveOnlyThatIsNamedType(dbContext, typeof(T)); - } - - /// - /// 移除模型缓存 - /// - /// - public static void RemoveModelCache(this DbContext dbContext) - { - var shardingModelSource = dbContext.GetService() as IShardingModelSource; - var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); - object key1 = modelCacheKeyFactory.Create(dbContext,true); - shardingModelSource.Remove(key1); - object key2 = modelCacheKeyFactory.Create(dbContext,false); - shardingModelSource.Remove(key2); - - } - - /// - /// 获取模型创建的锁 - /// - /// - /// - public static object GetModelCacheSyncObject(this DbContext dbContext) - { - IShardingModelSource shardingModelSource = dbContext.GetService() as IShardingModelSource; - return shardingModelSource.GetSyncObject(); - } - - - public static IEnumerable GetPrimaryKeyValues(TEntity entity,IKey primaryKey) where TEntity : class - { - return primaryKey.Properties.Select(o =>entity.GetPropertyValue(o.Name)); - } - - public static TEntity GetAttachedEntity(this DbContext context, TEntity entity) where TEntity:class - { - if (entity == null) { throw new ArgumentNullException(nameof(entity)); } - var entityPrimaryKey = context.Model.FindRuntimeEntityType(entity.GetType()).FindPrimaryKey(); - if (entityPrimaryKey == null) - { - return entity; - } - var primaryKeyValue = GetPrimaryKeyValues(entity, entityPrimaryKey).ToArray(); - if (primaryKeyValue.IsEmpty()) - return null; - var dbContextDependencies = (IDbContextDependencies)typeof(DbContext).GetTypePropertyValue(context, "DbContextDependencies"); - var stateManager = dbContextDependencies.StateManager; - - //var entityIKey = ShardingKeyUtil.GetEntityIKey(entity); - var internalEntityEntry = stateManager.TryGetEntry(entityPrimaryKey, primaryKeyValue); - - if (internalEntityEntry == null) - return null; - return (TEntity)internalEntityEntry.Entity; - //sp.Restart(); - - //var entityEntries = context.ChangeTracker.Entries(); - //sp.Stop(); - //Console.WriteLine($"ChangeTracker.Entries:{sp.ElapsedMilliseconds}毫秒"); - //sp.Restart(); - //var entry = entityEntries.Where(e => e.State != EntityState.Detached && primaryKeyValue.SequenceEqual(ShardingKeyUtil.GetPrimaryKeyValues(e.Entity))).FirstOrDefault(); - //sp.Stop(); - //Console.WriteLine($"ChangeTracker.FirstOrDefault:{sp.ElapsedMilliseconds}毫秒"); - //return entry?.Entity; - } - - public static IShardingRuntimeContext GetShardingRuntimeContext(this DbContext dbContext) - { - var shardingRuntimeContext = dbContext.GetService(); - - if (shardingRuntimeContext == null) - { - throw new ShardingCoreInvalidOperationException($"cant resolve:[{typeof(IShardingRuntimeContext)}],dbcontext:[{dbContext}]"); - } - - return shardingRuntimeContext; - } - - } -} - -#endif \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/OneAtMostElementStreamMergeAsyncEnumerator.cs b/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/OneAtMostElementStreamMergeAsyncEnumerator.cs index 180ccec6..2c3ea8d1 100644 --- a/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/OneAtMostElementStreamMergeAsyncEnumerator.cs +++ b/src/ShardingCore/Sharding/Enumerators/StreamMergeAsync/OneAtMostElementStreamMergeAsyncEnumerator.cs @@ -46,7 +46,7 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync } #endif -#if EFCORE3 || NETSTANDARD2_0 || EFCORE5 || NETSTANDARD2_1 +#if EFCORE3 || EFCORE5 public ValueTask DisposeAsync() { return new ValueTask(); diff --git a/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor2_6.cs b/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs similarity index 93% rename from src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor2_6.cs rename to src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs index 01cc2e55..db76e0ce 100644 --- a/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor2_6.cs +++ b/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor.cs @@ -1,4 +1,3 @@ -#if SHARDINGCORE2_6 using System; using System.Linq; using System.Linq.Expressions; @@ -134,7 +133,7 @@ namespace ShardingCore.Core.Internal.Visitors } } -#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 +#if EFCORE2 || EFCORE3 internal class DbContextReplaceQueryableVisitor : DbContextInnerMemberReferenceReplaceQueryableVisitor { private readonly DbContext _dbContext; @@ -174,7 +173,7 @@ namespace ShardingCore.Core.Internal.Visitors } #endif -#if EFCORE5 || NETSTANDARD2_1 || EFCORE6 +#if EFCORE5 || EFCORE6 ||EFCORE7 internal class DbContextReplaceQueryableVisitor : DbContextInnerMemberReferenceReplaceQueryableVisitor { private readonly DbContext _dbContext; @@ -192,9 +191,17 @@ namespace ShardingCore.Core.Internal.Visitors var dbContextDependencies = typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as IDbContextDependencies; +#if !EFCORE7 var targetIQ = (IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, queryRootExpression.EntityType.ClrType); +#endif +#if EFCORE7 + + var targetIQ = + (IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, + queryRootExpression.ElementType); +#endif var newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); if (Source == null) @@ -202,10 +209,16 @@ namespace ShardingCore.Core.Internal.Visitors RootIsVisit = true; if (queryRootExpression is FromSqlQueryRootExpression fromSqlQueryRootExpression) { +#if !EFCORE7 var sqlQueryRootExpression = new FromSqlQueryRootExpression(newQueryable.Provider as IAsyncQueryProvider, queryRootExpression.EntityType, fromSqlQueryRootExpression.Sql, fromSqlQueryRootExpression.Argument); - +#endif +#if EFCORE7 + var sqlQueryRootExpression = new FromSqlQueryRootExpression(newQueryable.Provider as IAsyncQueryProvider, + fromSqlQueryRootExpression.EntityType, fromSqlQueryRootExpression.Sql, + fromSqlQueryRootExpression.Argument); +#endif return base.VisitExtension(sqlQueryRootExpression); } else @@ -237,6 +250,5 @@ namespace ShardingCore.Core.Internal.Visitors } } #endif -} + } -#endif \ No newline at end of file diff --git a/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor7.cs b/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor7.cs deleted file mode 100644 index 99225c99..00000000 --- a/src/ShardingCore/Sharding/Visitors/DbContextReplaceQueryableVisitor7.cs +++ /dev/null @@ -1,201 +0,0 @@ -#if EFCORE7 -using System; -using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Internal; -using Microsoft.EntityFrameworkCore.Query; -using Microsoft.EntityFrameworkCore.Query.Internal; -using ShardingCore.Core.Internal.Visitors; -using ShardingCore.Exceptions; -using ShardingCore.Extensions; - -namespace ShardingCore.Core.Internal.Visitors -{ - /* - * @Author: xjm - * @Description: - * @Date: Wednesday, 13 January 2021 16:32:27 - * @Email: 326308290@qq.com - */ - - internal class DbContextInnerMemberReferenceReplaceQueryableVisitor : ShardingExpressionVisitor - { - private readonly DbContext _dbContext; - protected bool RootIsVisit = false; - - public DbContextInnerMemberReferenceReplaceQueryableVisitor(DbContext dbContext) - { - _dbContext = dbContext; - } - - // public override Expression Visit(Expression node) - // { - // Console.WriteLine("1"); - // return base.Visit(node); - // } - - protected override Expression VisitMember - (MemberExpression memberExpression) - { - // Recurse down to see if we can simplify... - if (memberExpression.IsMemberQueryable()) //2x,3x 路由 单元测试 分表和不分表 - { - var expressionValue = GetExpressionValue(memberExpression); - if (expressionValue is IQueryable queryable) - { - return ReplaceMemberExpression(queryable); - } - - if (expressionValue is DbContext dbContext) - { - return ReplaceMemberExpression(dbContext); - } - } - - return base.VisitMember(memberExpression); - } - - private MemberExpression ReplaceMemberExpression(IQueryable queryable) - { - var dbContextReplaceQueryableVisitor = new DbContextReplaceQueryableVisitor(_dbContext); - var newExpression = dbContextReplaceQueryableVisitor.Visit(queryable.Expression); - var newQueryable = dbContextReplaceQueryableVisitor.Source.Provider.CreateQuery(newExpression); - var tempVariableGenericType = typeof(TempVariable<>).GetGenericType0(queryable.ElementType); - var tempVariable = Activator.CreateInstance(tempVariableGenericType, newQueryable); - MemberExpression queryableMemberReplaceExpression = - Expression.Property(ConstantExpression.Constant(tempVariable), nameof(TempVariable.Queryable)); - return queryableMemberReplaceExpression; - } - - private MemberExpression ReplaceMemberExpression(DbContext dbContext) - { - var tempVariableGenericType = typeof(TempDbVariable<>).GetGenericType0(dbContext.GetType()); - var tempVariable = Activator.CreateInstance(tempVariableGenericType, _dbContext); - MemberExpression dbContextMemberReplaceExpression = - Expression.Property(ConstantExpression.Constant(tempVariable), - nameof(TempDbVariable.DbContext)); - return dbContextMemberReplaceExpression; - } - protected override Expression VisitMethodCall(MethodCallExpression node) - { - if (RootIsVisit&&node.Method.ReturnType.IsMethodReturnTypeQueryableType()&&node.Method.ReturnType.IsGenericType) - { - var notRoot = node.Arguments.IsEmpty(); - - if (notRoot) - { - var entityType = node.Method.ReturnType.GenericTypeArguments[0]; - - var whereCallExpression = ReplaceMethodCallExpression(node, entityType); - return whereCallExpression; - } - } - - return base.VisitMethodCall(node); - } - - private MethodCallExpression ReplaceMethodCallExpression(MethodCallExpression methodCallExpression, - Type entityType) - { - MethodCallExpression whereCallExpression = Expression.Call( - typeof(IShardingQueryableExtension), - nameof(IShardingQueryableExtension.ReplaceDbContextQueryableWithType), - new Type[] { entityType }, - methodCallExpression, Expression.Constant(_dbContext) - ); - return whereCallExpression; - } - - internal sealed class TempVariable - { - public IQueryable Queryable { get; } - - public TempVariable(IQueryable queryable) - { - Queryable = queryable; - } - - public IQueryable GetQueryable() - { - return Queryable; - } - } - - internal sealed class TempDbVariable - { - public T1 DbContext { get; } - - public TempDbVariable(T1 dbContext) - { - DbContext = dbContext; - } - } - } - internal class DbContextReplaceQueryableVisitor : DbContextInnerMemberReferenceReplaceQueryableVisitor - { - private readonly DbContext _dbContext; - public IQueryable Source; - - public DbContextReplaceQueryableVisitor(DbContext dbContext) : base(dbContext) - { - _dbContext = dbContext; - } - - protected override Expression VisitExtension(Expression node) - { - if (node is QueryRootExpression queryRootExpression) - { - var dbContextDependencies = - typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as - IDbContextDependencies; - var targetIQ = - (IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, - queryRootExpression.ElementType); - - var newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); - if (Source == null) - Source = newQueryable; - RootIsVisit = true; - - if (queryRootExpression is FromSqlQueryRootExpression fromSqlQueryRootExpression) - { - var sqlQueryRootExpression = new FromSqlQueryRootExpression(newQueryable.Provider as IAsyncQueryProvider, - fromSqlQueryRootExpression.EntityType, fromSqlQueryRootExpression.Sql, - fromSqlQueryRootExpression.Argument); - - return base.VisitExtension(sqlQueryRootExpression); - } - else - { - //如何替换ef5的set - var replaceQueryRoot = new ReplaceSingleQueryRootExpressionVisitor(); - replaceQueryRoot.Visit(newQueryable.Expression); - return base.VisitExtension(replaceQueryRoot.QueryRootExpression); - } - } - - return base.VisitExtension(node); - } - - internal sealed class ReplaceSingleQueryRootExpressionVisitor : ExpressionVisitor - { - public QueryRootExpression QueryRootExpression { get; set; } - - protected override Expression VisitExtension(Expression node) - { - if (node is QueryRootExpression queryRootExpression) - { - if (QueryRootExpression != null) - throw new ShardingCoreException("replace query root more than one query root"); - QueryRootExpression = queryRootExpression; - } - - return base.VisitExtension(node); - } - } - } -} - -#endif \ No newline at end of file diff --git a/src/ShardingCore/ShardingCore.csproj b/src/ShardingCore/ShardingCore.csproj index 0ca38e00..c3fbd452 100644 --- a/src/ShardingCore/ShardingCore.csproj +++ b/src/ShardingCore/ShardingCore.csproj @@ -1,6 +1,6 @@  - net6;net7; + net6.0 $(EFCORE7) true TRACE;DEBUG;EFCORE7;