分efcore
This commit is contained in:
parent
436c902000
commit
28073bff13
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
|
||||
namespace ShardingCore.Core.DbContextTypeAwares;
|
||||
|
||||
namespace ShardingCore.Core.DbContextTypeAwares
|
||||
{
|
||||
public class DbContextTypeAware : IDbContextTypeAware
|
||||
{
|
||||
private readonly Type _dbContextType;
|
||||
|
@ -15,3 +15,4 @@ public class DbContextTypeAware:IDbContextTypeAware
|
|||
return _dbContextType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System;
|
||||
|
||||
namespace ShardingCore.Core.DbContextTypeAwares;
|
||||
|
||||
namespace ShardingCore.Core.DbContextTypeAwares
|
||||
{
|
||||
public interface IDbContextTypeAware
|
||||
{
|
||||
Type GetContextType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.RuntimeContexts;
|
||||
|
||||
namespace ShardingCore.Core.RuntimeContexts
|
||||
{
|
||||
public interface IShardingRuntimeContext<TDbContext> : IShardingRuntimeContext where TDbContext : IShardingDbContext
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#if SHARDINGCORE2_6
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
|
@ -33,21 +32,21 @@ namespace ShardingCore.Extensions
|
|||
/// <param name="dbContext"></param>
|
||||
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<IDesignTimeModel>().Model; ;
|
||||
var contextModel = dbContext.GetService<IDesignTimeModel>().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<string, EntityType>;
|
||||
foreach (var entityType in entityTypes)
|
||||
|
@ -133,14 +132,14 @@ namespace ShardingCore.Extensions
|
|||
/// <param name="dbContext"></param>
|
||||
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<IDesignTimeModel>().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<string, EntityType>;
|
||||
|
@ -205,14 +204,14 @@ namespace ShardingCore.Extensions
|
|||
/// <param name="dbContext"></param>
|
||||
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<IDesignTimeModel>().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<string, EntityType>;
|
||||
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<IDesignTimeModel>().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<string, EntityType>;
|
||||
|
||||
|
@ -318,10 +317,10 @@ namespace ShardingCore.Extensions
|
|||
/// <param name="dbContext"></param>
|
||||
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<IModelSource>() 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<IModelSource>() 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<IModelSource>() as IShardingModelSource;
|
||||
var modelCacheKeyFactory = shardingModelSource.GetModelCacheKeyFactory();
|
||||
|
@ -415,4 +414,3 @@ namespace ShardingCore.Extensions
|
|||
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -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
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
@ -239,4 +252,3 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6;net7;</TargetFrameworks>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<Version>$(EFCORE7)</Version>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<DefineConstants>TRACE;DEBUG;EFCORE7;</DefineConstants>
|
||||
|
|
Loading…
Reference in New Issue