分efcore

This commit is contained in:
xuejiaming 2022-11-22 17:52:34 +08:00
parent 436c902000
commit 28073bff13
9 changed files with 72 additions and 463 deletions

View File

@ -1,7 +1,7 @@
using System; using System;
namespace ShardingCore.Core.DbContextTypeAwares; namespace ShardingCore.Core.DbContextTypeAwares
{
public class DbContextTypeAware : IDbContextTypeAware public class DbContextTypeAware : IDbContextTypeAware
{ {
private readonly Type _dbContextType; private readonly Type _dbContextType;
@ -15,3 +15,4 @@ public class DbContextTypeAware:IDbContextTypeAware
return _dbContextType; return _dbContextType;
} }
} }
}

View File

@ -1,8 +1,9 @@
using System; using System;
namespace ShardingCore.Core.DbContextTypeAwares; namespace ShardingCore.Core.DbContextTypeAwares
{
public interface IDbContextTypeAware public interface IDbContextTypeAware
{ {
Type GetContextType(); Type GetContextType();
} }
}

View File

@ -1,8 +1,9 @@
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
namespace ShardingCore.Core.RuntimeContexts; namespace ShardingCore.Core.RuntimeContexts
{
public interface IShardingRuntimeContext<TDbContext> : IShardingRuntimeContext where TDbContext : IShardingDbContext public interface IShardingRuntimeContext<TDbContext> : IShardingRuntimeContext where TDbContext : IShardingDbContext
{ {
} }
}

View File

@ -1,5 +1,4 @@
#if SHARDINGCORE2_6 
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
@ -33,21 +32,21 @@ namespace ShardingCore.Extensions
/// <param name="dbContext"></param> /// <param name="dbContext"></param>
public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext) 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(); throw new NotImplementedException();
#endif #endif
#if EFCORE6 #if EFCORE6 ||EFCORE7
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ; var contextModel = dbContext.GetService<IDesignTimeModel>().Model;
#endif #endif
#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 || EFCORE5 || NETSTANDARD2_1 #if EFCORE2 || EFCORE3 || EFCORE5
var contextModel = dbContext.Model as Model; var contextModel = dbContext.Model as Model;
#endif #endif
var shardingRuntimeContext = dbContext.GetShardingRuntimeContext(); var shardingRuntimeContext = dbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager(); var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
#if EFCORE6 #if EFCORE6 || EFCORE7
var entityTypes = contextModel.GetEntityTypes(); var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes) foreach (var entityType in entityTypes)
{ {
@ -64,7 +63,7 @@ namespace ShardingCore.Extensions
contextModelRelationalModel.Tables.Remove(valueTuples[i]); contextModelRelationalModel.Tables.Remove(valueTuples[i]);
} }
#endif #endif
#if EFCORE5 || NETSTANDARD2_1 #if EFCORE5
var entityTypes = contextModel.GetEntityTypes(); var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes) foreach (var entityType in entityTypes)
{ {
@ -81,7 +80,7 @@ namespace ShardingCore.Extensions
contextModelRelationalModel.Tables.Remove(valueTuples[i]); contextModelRelationalModel.Tables.Remove(valueTuples[i]);
} }
#endif #endif
#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 #if EFCORE2 || EFCORE3
var entityTypes = var entityTypes =
contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>; contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>;
foreach (var entityType in entityTypes) foreach (var entityType in entityTypes)
@ -133,14 +132,14 @@ namespace ShardingCore.Extensions
/// <param name="dbContext"></param> /// <param name="dbContext"></param>
public static void RemoveDbContextAllRelationModelWithoutShardingDataSourceOnly(this DbContext dbContext) 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(); throw new NotImplementedException();
#endif #endif
#if EFCORE6 #if EFCORE6 || EFCORE7
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ; var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ;
#endif #endif
#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 || EFCORE5 || NETSTANDARD2_1 #if EFCORE2 || EFCORE3 || EFCORE5
var contextModel = dbContext.Model as Model; var contextModel = dbContext.Model as Model;
#endif #endif
@ -164,7 +163,7 @@ namespace ShardingCore.Extensions
contextModelRelationalModel.Tables.Remove(valueTuples[i]); contextModelRelationalModel.Tables.Remove(valueTuples[i]);
} }
#endif #endif
#if EFCORE5 || NETSTANDARD2_1 #if EFCORE5
var entityTypes = contextModel.GetEntityTypes(); var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes) foreach (var entityType in entityTypes)
{ {
@ -181,7 +180,7 @@ namespace ShardingCore.Extensions
contextModelRelationalModel.Tables.Remove(valueTuples[i]); contextModelRelationalModel.Tables.Remove(valueTuples[i]);
} }
#endif #endif
#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 #if EFCORE2 || EFCORE3
var entityTypes = var entityTypes =
contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>; contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>;
@ -205,14 +204,14 @@ namespace ShardingCore.Extensions
/// <param name="dbContext"></param> /// <param name="dbContext"></param>
public static void RemoveDbContextAllRelationModel(this DbContext dbContext) 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(); throw new NotImplementedException();
#endif #endif
#if EFCORE6 #if EFCORE6|| EFCORE7
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ; var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ;
#endif #endif
#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 || EFCORE5 || NETSTANDARD2_1 #if EFCORE2 || EFCORE3 || EFCORE5
var contextModel = dbContext.Model as Model; var contextModel = dbContext.Model as Model;
#endif #endif
@ -221,11 +220,11 @@ namespace ShardingCore.Extensions
var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel; var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel;
contextModelRelationalModel.Tables.Clear(); contextModelRelationalModel.Tables.Clear();
#endif #endif
#if EFCORE5 || NETSTANDARD2_1 #if EFCORE5
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel; var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
contextModelRelationalModel.Tables.Clear(); contextModelRelationalModel.Tables.Clear();
#endif #endif
#if EFCORE2 || EFCORE3 || NETSTANDARD2_0 #if EFCORE2 || EFCORE3
var entityTypes = var entityTypes =
contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>; contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>;
entityTypes.Clear(); entityTypes.Clear();
@ -240,14 +239,14 @@ namespace ShardingCore.Extensions
public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbContext dbContext, public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbContext dbContext,
Type shardingType) Type shardingType)
{ {
#if !EFCORE2 && !NETSTANDARD2_0 && !EFCORE3 && !NETSTANDARD2_1 && !EFCORE5 && !EFCORE6 #if !EFCORE2 && !EFCORE3 && !EFCORE5 && !EFCORE6&& !EFCORE7
1 1
#endif #endif
#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 ||EFCORE5 || NETSTANDARD2_1 #if EFCORE2 || EFCORE3 || EFCORE5
var contextModel = dbContext.Model as Model; var contextModel = dbContext.Model as Model;
#endif #endif
#if EFCORE6 #if EFCORE6 || EFCORE7
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; var contextModel = dbContext.GetService<IDesignTimeModel>().Model;
var entityTypes = contextModel.GetEntityTypes(); var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes) foreach (var entityType in entityTypes)
@ -268,7 +267,7 @@ namespace ShardingCore.Extensions
} }
#endif #endif
#if EFCORE5 || NETSTANDARD2_1 #if EFCORE5
var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel; var contextModelRelationalModel = contextModel.RelationalModel as RelationalModel;
var entityTypes = contextModel.GetEntityTypes(); var entityTypes = contextModel.GetEntityTypes();
@ -287,7 +286,7 @@ namespace ShardingCore.Extensions
contextModelRelationalModel.Tables.Remove(valueTuples[i]); contextModelRelationalModel.Tables.Remove(valueTuples[i]);
} }
#endif #endif
#if EFCORE2 || NETSTANDARD2_0 || EFCORE3 #if EFCORE2 || EFCORE3
var entityTypes = var entityTypes =
contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>; contextModel.GetFieldValue("_entityTypes") as SortedDictionary<string, EntityType>;
@ -318,10 +317,10 @@ namespace ShardingCore.Extensions
/// <param name="dbContext"></param> /// <param name="dbContext"></param>
public static void RemoveModelCache(this DbContext dbContext) 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(); throw new NotImplementedException();
#endif #endif
#if EFCORE6 #if EFCORE6 || EFCORE7
var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource; var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource;
var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory();
object key1 = modelCacheKeyFactory.Create(dbContext,true); object key1 = modelCacheKeyFactory.Create(dbContext,true);
@ -329,13 +328,13 @@ namespace ShardingCore.Extensions
object key2 = modelCacheKeyFactory.Create(dbContext,false); object key2 = modelCacheKeyFactory.Create(dbContext,false);
shardingModelSource.Remove(key2); shardingModelSource.Remove(key2);
#endif #endif
#if EFCORE5 || NETSTANDARD2_1 #if EFCORE5
var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource; var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource;
var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory();
object key1 = modelCacheKeyFactory.Create(dbContext); object key1 = modelCacheKeyFactory.Create(dbContext);
shardingModelSource.Remove(key1); shardingModelSource.Remove(key1);
#endif #endif
#if EFCORE3 || NETSTANDARD2_0 #if EFCORE3
var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource; var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource;
var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory(); var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory();
@ -415,4 +414,3 @@ namespace ShardingCore.Extensions
} }
} }
#endif

View File

@ -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
{
/// <summary>
/// 移除所有的分表关系的模型
/// </summary>
/// <param name="dbContext"></param>
public static void RemoveDbContextRelationModelThatIsShardingTable(this DbContext dbContext)
{
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ;
var shardingRuntimeContext = dbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes)
{
if (entityType.GetFieldValue("_data") is List<object> _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]);
}
}
/// <summary>
/// 移除所有除了仅分库的
/// </summary>
/// <param name="dbContext"></param>
public static void RemoveDbContextAllRelationModelWithoutShardingDataSourceOnly(this DbContext dbContext)
{
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ;
var shardingRuntimeContext = dbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes)
{
if (entityType.GetFieldValue("_data") is List<object> _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]);
}
}
/// <summary>
/// 移除所有的表
/// </summary>
/// <param name="dbContext"></param>
public static void RemoveDbContextAllRelationModel(this DbContext dbContext)
{
var contextModel = dbContext.GetService<IDesignTimeModel>().Model; ;
var contextModelRelationalModel = contextModel.GetRelationalModel() as RelationalModel;
contextModelRelationalModel.Tables.Clear();
}
/// <summary>
/// 移除所有的除了我指定的那个类型
/// </summary>
/// <param name="dbContext"></param>
/// <param name="shardingType"></param>
public static void RemoveDbContextRelationModelSaveOnlyThatIsNamedType(this DbContext dbContext,
Type shardingType)
{
var contextModel = dbContext.GetService<IDesignTimeModel>().Model;
var entityTypes = contextModel.GetEntityTypes();
foreach (var entityType in entityTypes)
{
if (entityType.GetFieldValue("_data") is List<object> _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<T>(this DbContext dbContext)
where T:class
{
RemoveDbContextRelationModelSaveOnlyThatIsNamedType(dbContext, typeof(T));
}
/// <summary>
/// 移除模型缓存
/// </summary>
/// <param name="dbContext"></param>
public static void RemoveModelCache(this DbContext dbContext)
{
var shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource;
var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory();
object key1 = modelCacheKeyFactory.Create(dbContext,true);
shardingModelSource.Remove(key1);
object key2 = modelCacheKeyFactory.Create(dbContext,false);
shardingModelSource.Remove(key2);
}
/// <summary>
/// 获取模型创建的锁
/// </summary>
/// <param name="dbContext"></param>
/// <returns></returns>
public static object GetModelCacheSyncObject(this DbContext dbContext)
{
IShardingModelSource shardingModelSource = dbContext.GetService<IModelSource>() as IShardingModelSource;
return shardingModelSource.GetSyncObject();
}
public static IEnumerable<object> GetPrimaryKeyValues<TEntity>(TEntity entity,IKey primaryKey) where TEntity : class
{
return primaryKey.Properties.Select(o =>entity.GetPropertyValue(o.Name));
}
public static TEntity GetAttachedEntity<TEntity>(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<TEntity>();
//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<IShardingRuntimeContext>();
if (shardingRuntimeContext == null)
{
throw new ShardingCoreInvalidOperationException($"cant resolve:[{typeof(IShardingRuntimeContext)}],dbcontext:[{dbContext}]");
}
return shardingRuntimeContext;
}
}
}
#endif

View File

@ -46,7 +46,7 @@ namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
} }
#endif #endif
#if EFCORE3 || NETSTANDARD2_0 || EFCORE5 || NETSTANDARD2_1 #if EFCORE3 || EFCORE5
public ValueTask DisposeAsync() public ValueTask DisposeAsync()
{ {
return new ValueTask(); return new ValueTask();

View File

@ -1,4 +1,3 @@
#if SHARDINGCORE2_6
using System; using System;
using System.Linq; using System.Linq;
using System.Linq.Expressions; 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 internal class DbContextReplaceQueryableVisitor : DbContextInnerMemberReferenceReplaceQueryableVisitor
{ {
private readonly DbContext _dbContext; private readonly DbContext _dbContext;
@ -174,7 +173,7 @@ namespace ShardingCore.Core.Internal.Visitors
} }
#endif #endif
#if EFCORE5 || NETSTANDARD2_1 || EFCORE6 #if EFCORE5 || EFCORE6 ||EFCORE7
internal class DbContextReplaceQueryableVisitor : DbContextInnerMemberReferenceReplaceQueryableVisitor internal class DbContextReplaceQueryableVisitor : DbContextInnerMemberReferenceReplaceQueryableVisitor
{ {
private readonly DbContext _dbContext; private readonly DbContext _dbContext;
@ -192,9 +191,17 @@ namespace ShardingCore.Core.Internal.Visitors
var dbContextDependencies = var dbContextDependencies =
typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as typeof(DbContext).GetTypePropertyValue(_dbContext, "DbContextDependencies") as
IDbContextDependencies; IDbContextDependencies;
#if !EFCORE7
var targetIQ = var targetIQ =
(IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource, (IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource,
queryRootExpression.EntityType.ClrType); queryRootExpression.EntityType.ClrType);
#endif
#if EFCORE7
var targetIQ =
(IQueryable)((IDbSetCache)_dbContext).GetOrAddSet(dbContextDependencies.SetSource,
queryRootExpression.ElementType);
#endif
var newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression); var newQueryable = targetIQ.Provider.CreateQuery(targetIQ.Expression);
if (Source == null) if (Source == null)
@ -202,10 +209,16 @@ namespace ShardingCore.Core.Internal.Visitors
RootIsVisit = true; RootIsVisit = true;
if (queryRootExpression is FromSqlQueryRootExpression fromSqlQueryRootExpression) if (queryRootExpression is FromSqlQueryRootExpression fromSqlQueryRootExpression)
{ {
#if !EFCORE7
var sqlQueryRootExpression = new FromSqlQueryRootExpression(newQueryable.Provider as IAsyncQueryProvider, var sqlQueryRootExpression = new FromSqlQueryRootExpression(newQueryable.Provider as IAsyncQueryProvider,
queryRootExpression.EntityType, fromSqlQueryRootExpression.Sql, queryRootExpression.EntityType, fromSqlQueryRootExpression.Sql,
fromSqlQueryRootExpression.Argument); fromSqlQueryRootExpression.Argument);
#endif
#if EFCORE7
var sqlQueryRootExpression = new FromSqlQueryRootExpression(newQueryable.Provider as IAsyncQueryProvider,
fromSqlQueryRootExpression.EntityType, fromSqlQueryRootExpression.Sql,
fromSqlQueryRootExpression.Argument);
#endif
return base.VisitExtension(sqlQueryRootExpression); return base.VisitExtension(sqlQueryRootExpression);
} }
else else
@ -239,4 +252,3 @@ namespace ShardingCore.Core.Internal.Visitors
#endif #endif
} }
#endif

View File

@ -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<object>.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<object>.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<T1>
{
public IQueryable<T1> Queryable { get; }
public TempVariable(IQueryable<T1> queryable)
{
Queryable = queryable;
}
public IQueryable<T1> GetQueryable()
{
return Queryable;
}
}
internal sealed class TempDbVariable<T1>
{
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

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net6;net7;</TargetFrameworks> <TargetFramework>net6.0</TargetFramework>
<Version>$(EFCORE7)</Version> <Version>$(EFCORE7)</Version>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo> <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<DefineConstants>TRACE;DEBUG;EFCORE7;</DefineConstants> <DefineConstants>TRACE;DEBUG;EFCORE7;</DefineConstants>