parent
6d68bcf1db
commit
134cbcc7fd
|
@ -1,9 +1,9 @@
|
|||
:start
|
||||
::定义版本
|
||||
set EFCORE2=2.4.2.13
|
||||
set EFCORE3=3.4.2.13
|
||||
set EFCORE5=5.4.2.13
|
||||
set EFCORE6=6.4.2.13
|
||||
set EFCORE2=2.4.2.14
|
||||
set EFCORE3=3.4.2.14
|
||||
set EFCORE5=5.4.2.14
|
||||
set EFCORE6=6.4.2.14
|
||||
|
||||
::删除所有bin与obj下的文件
|
||||
@echo off
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -23,6 +24,20 @@ namespace Sample.SqlServerShardingTable.Controllers
|
|||
_myDbContext = myDbContext;
|
||||
_virtualDataSourceManager = virtualDataSourceManager;
|
||||
}
|
||||
public async Task<IActionResult> Testa()
|
||||
{
|
||||
Stopwatch sp=Stopwatch.StartNew();
|
||||
var listAsync = await _myDbContext.Set<SysUser>().AsTracking().ToListAsync();
|
||||
sp.Stop();
|
||||
return Ok(sp.ElapsedMilliseconds);
|
||||
}
|
||||
public async Task<IActionResult> Testb()
|
||||
{
|
||||
Stopwatch sp = Stopwatch.StartNew();
|
||||
var listAsync = await _myDbContext.Set<SysUser>().AsNoTracking().ToListAsync();
|
||||
sp.Stop();
|
||||
return Ok(sp.ElapsedMilliseconds);
|
||||
}
|
||||
public async Task<IActionResult> Query()
|
||||
{
|
||||
Console.WriteLine("123123");
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.24" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src3x\ShardingCore.3x\ShardingCore.3x.csproj" />
|
||||
<ProjectReference Include="..\..\src\ShardingCore\ShardingCore.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class DataSourceRouteResult:IPrint
|
||||
public class DataSourceRouteResult
|
||||
{
|
||||
public DataSourceRouteResult(ISet<string> intersectDataSources)
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
/// </summary>
|
||||
public ISet<string> IntersectDataSources { get; }
|
||||
|
||||
public string GetPrintInfo()
|
||||
public override string ToString()
|
||||
{
|
||||
return $"data source route result:{string.Join(",", IntersectDataSources)}";
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources;
|
||||
using ShardingCore.Extensions;
|
||||
|
@ -21,14 +22,14 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
/// <typeparam name="T"></typeparam>
|
||||
public class DataSourceRouteRuleContext
|
||||
{
|
||||
public DataSourceRouteRuleContext(IQueryable queryable,IShardingDbContext shardingDbContext)
|
||||
public DataSourceRouteRuleContext(IQueryable queryable,IShardingDbContext shardingDbContext, Dictionary<Type, IQueryable> queryEntities)
|
||||
{
|
||||
Queryable = queryable;
|
||||
ShardingDbContext = shardingDbContext;
|
||||
VirtualDataSource = shardingDbContext.GetVirtualDataSource();
|
||||
QueryEntities = queryable.ParseQueryableEntities(shardingDbContext.GetType());
|
||||
QueryEntities = queryEntities;
|
||||
}
|
||||
public ISet<Type> QueryEntities { get; }
|
||||
public Dictionary<Type, IQueryable> QueryEntities { get; }
|
||||
/// <summary>
|
||||
/// 查询条件
|
||||
/// </summary>
|
||||
|
|
|
@ -31,21 +31,16 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
{
|
||||
var virtualDataSource = routeRuleContext.VirtualDataSource;
|
||||
var dataSourceMaps = new Dictionary<Type, ISet<string>>();
|
||||
var notShardingDataSourceEntityType = routeRuleContext.QueryEntities.FirstOrDefault(o => !_entityMetadataManager.IsShardingDataSource(o));
|
||||
//存在不分库的
|
||||
if (notShardingDataSourceEntityType != null)
|
||||
dataSourceMaps.Add(notShardingDataSourceEntityType, new HashSet<string>() { virtualDataSource.DefaultDataSourceName });
|
||||
|
||||
|
||||
//if (queryEntities.Count > 1)
|
||||
// throw new ShardingCoreNotSupportedException($"{routeRuleContext.Queryable.ShardingPrint()}");
|
||||
foreach (var queryEntity in routeRuleContext.QueryEntities)
|
||||
foreach (var queryEntityKv in routeRuleContext.QueryEntities)
|
||||
{
|
||||
var queryEntity = queryEntityKv.Key;
|
||||
if (!_entityMetadataManager.IsShardingDataSource(queryEntity))
|
||||
{
|
||||
dataSourceMaps.Add(queryEntity, new HashSet<string>() { virtualDataSource.DefaultDataSourceName });
|
||||
continue;
|
||||
}
|
||||
var dataSourceConfigs = virtualDataSource.RouteTo(queryEntity,new ShardingDataSourceRouteConfig(routeRuleContext.Queryable));
|
||||
var dataSourceConfigs = virtualDataSource.RouteTo(queryEntity, new ShardingDataSourceRouteConfig(queryEntityKv.Value??routeRuleContext.Queryable));
|
||||
if (!dataSourceMaps.ContainsKey(queryEntity))
|
||||
{
|
||||
dataSourceMaps.Add(queryEntity, dataSourceConfigs.ToHashSet());
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
@ -31,13 +32,13 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
/// <summary>
|
||||
/// 通过表达式创建分库路由上下文
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="queryable"></param>
|
||||
/// <param name="shardingDbContext"></param>
|
||||
/// <param name="queryEntities"></param>
|
||||
/// <returns></returns>
|
||||
public DataSourceRouteRuleContext CreateContext(IQueryable queryable,IShardingDbContext shardingDbContext)
|
||||
private DataSourceRouteRuleContext CreateContext(IQueryable queryable,IShardingDbContext shardingDbContext,Dictionary<Type,IQueryable> queryEntities)
|
||||
{
|
||||
return new DataSourceRouteRuleContext(queryable, shardingDbContext);
|
||||
return new DataSourceRouteRuleContext(queryable, shardingDbContext, queryEntities);
|
||||
}
|
||||
/// <summary>
|
||||
/// 路由到具体的物理数据源
|
||||
|
@ -45,21 +46,22 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="queryable"></param>
|
||||
/// <param name="shardingDbContext"></param>
|
||||
/// <param name="queryEntities"></param>
|
||||
/// <returns></returns>
|
||||
public DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext)
|
||||
{
|
||||
var ruleContext = CreateContext(queryable, shardingDbContext);
|
||||
return _dataSourceRouteRuleEngine.Route(ruleContext);
|
||||
}
|
||||
/// <summary>
|
||||
/// 路由到具体的物理数据源
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="ruleContext"></param>
|
||||
/// <returns></returns>
|
||||
public DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext)
|
||||
public DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext, Dictionary<Type, IQueryable> queryEntities)
|
||||
{
|
||||
var ruleContext = CreateContext(queryable, shardingDbContext,queryEntities);
|
||||
return _dataSourceRouteRuleEngine.Route(ruleContext);
|
||||
}
|
||||
///// <summary>
|
||||
///// 路由到具体的物理数据源
|
||||
///// </summary>
|
||||
///// <typeparam name="T"></typeparam>
|
||||
///// <param name="ruleContext"></param>
|
||||
///// <returns></returns>
|
||||
//public DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext)
|
||||
//{
|
||||
// return _dataSourceRouteRuleEngine.Route(ruleContext);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
@ -16,9 +17,8 @@ namespace ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine
|
|||
*/
|
||||
public interface IDataSourceRouteRuleEngineFactory
|
||||
{
|
||||
DataSourceRouteRuleContext CreateContext(IQueryable queryable, IShardingDbContext shardingDbContext);
|
||||
DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext);
|
||||
DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext);
|
||||
DataSourceRouteResult Route(IQueryable queryable, IShardingDbContext shardingDbContext, Dictionary<Type, IQueryable> queryEntities);
|
||||
//DataSourceRouteResult Route(DataSourceRouteRuleContext ruleContext);
|
||||
}
|
||||
public interface IDataSourceRouteRuleEngineFactory<TShardingDbContext> : IDataSourceRouteRuleEngineFactory
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
|
|||
*/
|
||||
public interface ITableRouteRuleEngineFactory
|
||||
{
|
||||
TableRouteRuleContext CreateContext(IQueryable queryable);
|
||||
IEnumerable<TableRouteResult> Route(IQueryable queryable);
|
||||
IEnumerable<TableRouteResult> Route(TableRouteRuleContext ruleContext);
|
||||
//TableRouteRuleContext CreateContext(IQueryable queryable);
|
||||
IEnumerable<TableRouteResult> Route(IQueryable queryable,Dictionary<Type,IQueryable> queryEntities);
|
||||
//IEnumerable<TableRouteResult> Route(TableRouteRuleContext ruleContext);
|
||||
}
|
||||
public interface ITableRouteRuleEngineFactory<TShardingDbContext> : ITableRouteRuleEngineFactory
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
|
@ -13,12 +15,13 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
|
|||
public class TableRouteRuleContext
|
||||
{
|
||||
|
||||
public TableRouteRuleContext(IQueryable queryable)
|
||||
public TableRouteRuleContext(IQueryable queryable, Dictionary<Type, IQueryable> queryEntities)
|
||||
{
|
||||
Queryable = queryable;
|
||||
QueryEntities = queryEntities;
|
||||
}
|
||||
|
||||
public IQueryable Queryable { get; }
|
||||
|
||||
public Dictionary<Type, IQueryable> QueryEntities { get; }
|
||||
}
|
||||
}
|
|
@ -33,16 +33,17 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
|
|||
public IEnumerable<TableRouteResult> Route(TableRouteRuleContext tableRouteRuleContext)
|
||||
{
|
||||
Dictionary<IVirtualTable, ISet<IPhysicTable>> routeMaps = new Dictionary<IVirtualTable, ISet<IPhysicTable>>();
|
||||
var queryEntities = tableRouteRuleContext.Queryable.ParseQueryableEntities(typeof(TShardingDbContext));
|
||||
var queryEntities = tableRouteRuleContext.QueryEntities;
|
||||
|
||||
|
||||
foreach (var shardingEntity in queryEntities)
|
||||
foreach (var shardingEntityKv in queryEntities)
|
||||
{
|
||||
if(!_entityMetadataManager.IsShardingTable(shardingEntity))
|
||||
var shardingEntity = shardingEntityKv.Key;
|
||||
if (!_entityMetadataManager.IsShardingTable(shardingEntity))
|
||||
continue;
|
||||
var virtualTable = _virtualTableManager.GetVirtualTable(shardingEntity);
|
||||
|
||||
var physicTables = virtualTable.RouteTo(new ShardingTableRouteConfig(queryable: tableRouteRuleContext.Queryable));
|
||||
var physicTables = virtualTable.RouteTo(new ShardingTableRouteConfig(shardingEntityKv.Value ?? tableRouteRuleContext.Queryable));
|
||||
if (!routeMaps.ContainsKey(virtualTable))
|
||||
{
|
||||
routeMaps.Add(virtualTable, physicTables.ToHashSet());
|
||||
|
|
|
@ -31,18 +31,18 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
|
|||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="queryable"></param>
|
||||
/// <returns></returns>
|
||||
public TableRouteRuleContext CreateContext(IQueryable queryable)
|
||||
private TableRouteRuleContext CreateContext(IQueryable queryable, Dictionary<Type, IQueryable> queryEntities)
|
||||
{
|
||||
return new TableRouteRuleContext(queryable);
|
||||
return new TableRouteRuleContext(queryable,queryEntities);
|
||||
}
|
||||
|
||||
public IEnumerable<TableRouteResult> Route(IQueryable queryable)
|
||||
public IEnumerable<TableRouteResult> Route(IQueryable queryable,Dictionary<Type,IQueryable> queryEntities)
|
||||
{
|
||||
var ruleContext = CreateContext(queryable);
|
||||
var ruleContext = CreateContext(queryable, queryEntities);
|
||||
return Route(ruleContext);
|
||||
}
|
||||
|
||||
public IEnumerable<TableRouteResult> Route(TableRouteRuleContext ruleContext)
|
||||
private IEnumerable<TableRouteResult> Route(TableRouteRuleContext ruleContext)
|
||||
{
|
||||
return _tableRouteRuleEngine.Route(ruleContext);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
|
|||
using ShardingCore.DynamicDataSources;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.ParallelTables;
|
||||
using ShardingCore.Sharding.Parsers;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors;
|
||||
|
@ -127,6 +129,7 @@ namespace ShardingCore
|
|||
services.TryAddSingleton<IReadWriteConnectorFactory, ReadWriteConnectorFactory>();
|
||||
|
||||
//
|
||||
services.TryAddSingleton<IPrepareParser, DefaultPrepareParser>();
|
||||
services.TryAddSingleton<IQueryableParseEngine, QueryableParseEngine>();
|
||||
services.TryAddSingleton<IQueryableRewriteEngine, QueryableRewriteEngine>();
|
||||
services.TryAddSingleton<IQueryableOptimizeEngine, QueryableOptimizeEngine>();
|
||||
|
|
|
@ -156,10 +156,10 @@ namespace ShardingCore.Extensions
|
|||
return nameof(string.CompareTo).Equals(express.Method.Name) || nameof(string.Compare).Equals(express.Method.Name);
|
||||
}
|
||||
|
||||
public static ISet<Type> ParseQueryableEntities(this IQueryable queryable, Type dbContextType)
|
||||
{
|
||||
return ShardingUtil.GetQueryEntitiesFilter(queryable, dbContextType);
|
||||
}
|
||||
//public static ISet<Type> ParseQueryableEntities(this IQueryable queryable, Type dbContextType)
|
||||
//{
|
||||
// return ShardingUtil.GetQueryEntitiesFilter(queryable, dbContextType);
|
||||
//}
|
||||
|
||||
public static bool IsMemberQueryable(this MemberExpression memberExpression)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
/*
|
||||
|
@ -9,17 +10,17 @@ using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
|||
*/
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
public static class CompileParameterExtension
|
||||
public static class CompileExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// 是否存在自定义查询
|
||||
/// </summary>
|
||||
/// <param name="compileParameter"></param>
|
||||
/// <param name="prepareParseResult"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasCustomerQuery(this ICompileParameter compileParameter)
|
||||
public static bool HasCustomerQuery(this IPrepareParseResult prepareParseResult)
|
||||
{
|
||||
//compileParameter.ReadOnly().HasValue || compileParameter.GetAsRoute() != null;
|
||||
return compileParameter.GetAsRoute() != null;
|
||||
return prepareParseResult.GetAsRoute() != null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace ShardingCore.Extensions.InternalExtensions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/4/30 21:44:22
|
||||
/// Email: 326308290@qq.com
|
||||
internal static class InternalLogExtension
|
||||
{
|
||||
public static void LogLazyDebug(this ILogger logger, Func<string> msgCreator)
|
||||
{
|
||||
if (logger.IsEnabled(LogLevel.Debug))
|
||||
{
|
||||
logger.LogDebug(msgCreator());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,13 +4,13 @@ using ShardingCore.Core.QueryRouteManagers;
|
|||
namespace ShardingCore.Extensions.ShardingQueryableExtensions
|
||||
{
|
||||
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 31 January 2022 00:15:37
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
internal class ShardingQueryableAsRouteOptions
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 31 January 2022 00:15:37
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingQueryableAsRouteOptions
|
||||
{
|
||||
public Action<ShardingRouteContext> RouteConfigure { get; }
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace ShardingCore.Extensions.ShardingQueryableExtensions
|
||||
{
|
||||
internal class ShardingQueryableAsSequenceOptions
|
||||
public class ShardingQueryableAsSequenceOptions
|
||||
{
|
||||
public bool SameWithShardingComparer { get; }
|
||||
public bool AsSequence { get; }
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
namespace ShardingCore.Extensions.ShardingQueryableExtensions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Tuesday, 01 February 2022 16:48:17
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
internal class ShardingQueryableReadWriteSeparationOptions
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Tuesday, 01 February 2022 16:48:17
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingQueryableReadWriteSeparationOptions
|
||||
{
|
||||
public bool RouteReadConnect { get; }
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ using ShardingCore.Core;
|
|||
namespace ShardingCore.Extensions.ShardingQueryableExtensions
|
||||
{
|
||||
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 31 January 2022 22:51:56
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
internal class ShardingQueryableUseConnectionModeOptions
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: Monday, 31 January 2022 22:51:56
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class ShardingQueryableUseConnectionModeOptions
|
||||
{
|
||||
public ShardingQueryableUseConnectionModeOptions(int maxQueryConnectionsLimit, ConnectionModeEnum connectionMode)
|
||||
{
|
||||
|
|
|
@ -4,12 +4,13 @@ using System.Linq;
|
|||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.Abstractions
|
||||
{
|
||||
public interface IQueryCompilerContextFactory
|
||||
{
|
||||
IQueryCompilerContext Create(ICompileParameter compileParameter);
|
||||
IQueryCompilerContext Create(IPrepareParseResult prepareParseResult);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.QueryRouteManagers;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.Parsers.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/5/1 17:37:10
|
||||
/// Email: 326308290@qq.com
|
||||
public interface IPrepareParseResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取当前分片上下文
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IShardingDbContext GetShardingDbContext();
|
||||
/// <summary>
|
||||
/// 获取原始的查询表达式
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Expression GetNativeQueryExpression();
|
||||
/// <summary>
|
||||
/// 是否使用union all 聚合
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool UseUnionAllMerge();
|
||||
/// <summary>
|
||||
/// 当前查询的连接数限制
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int? GetMaxQueryConnectionsLimit();
|
||||
/// <summary>
|
||||
/// 当前查询的连接模式
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
ConnectionModeEnum? GetConnectionMode();
|
||||
/// <summary>
|
||||
/// 在启用读写分离后如果设置了readonly那么就走readonly否则为null
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool? ReadOnly();
|
||||
|
||||
/// <summary>
|
||||
/// 自定义路由
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
Action<ShardingRouteContext> GetAsRoute();
|
||||
|
||||
bool? IsSequence();
|
||||
bool? SameWithShardingComparer();
|
||||
Dictionary<Type/* 查询对象类型 */, IQueryable/* 查询对象对应的表达式 */> GetQueryEntities();
|
||||
bool? IsNotracking();
|
||||
bool IsIgnoreFilter();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.Parsers.Abstractions
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/5/1 16:02:57
|
||||
/// Email: 326308290@qq.com
|
||||
public interface IPrepareParser
|
||||
{
|
||||
IPrepareParseResult Parse(IShardingDbContext shardingDbContext, Expression query);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.Parsers.Visitors;
|
||||
|
||||
namespace ShardingCore.Sharding.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/5/1 21:37:25
|
||||
/// Email: 326308290@qq.com
|
||||
public class DefaultPrepareParser:IPrepareParser
|
||||
{
|
||||
public IPrepareParseResult Parse(IShardingDbContext shardingDbContext, Expression query)
|
||||
{
|
||||
var shardingQueryPrepareVisitor = new ShardingQueryPrepareVisitor(shardingDbContext);
|
||||
var expression = shardingQueryPrepareVisitor.Visit(query);
|
||||
var shardingPrepareResult = shardingQueryPrepareVisitor.GetShardingPrepareResult();
|
||||
return new PrepareParseResult(shardingDbContext, expression, shardingPrepareResult);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.QueryRouteManagers;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.Visitors.Querys;
|
||||
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
|
||||
|
||||
namespace ShardingCore.Sharding.Parsers
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/5/1 16:03:25
|
||||
/// Email: 326308290@qq.com
|
||||
public class PrepareParseResult: IPrepareParseResult
|
||||
{
|
||||
private readonly IShardingDbContext _shardingDbContext;
|
||||
private readonly Expression _nativeQueryExpression;
|
||||
private readonly bool _useUnionAllMerge;
|
||||
private readonly int? _maxQueryConnectionsLimit;
|
||||
private readonly ConnectionModeEnum? _connectionMode;
|
||||
private readonly bool? _readOnly;
|
||||
private readonly Action<ShardingRouteContext> _shardingRouteConfigure;
|
||||
private readonly bool? _isSequence;
|
||||
private readonly bool? _isNoTracking;
|
||||
private readonly bool _isIgnoreFilter;
|
||||
private readonly bool? _sameWithShardingComparer;
|
||||
private readonly Dictionary<Type, IQueryable> _queryEntities;
|
||||
|
||||
public PrepareParseResult(IShardingDbContext shardingDbContext,Expression nativeQueryExpression, ShardingPrepareResult shardingPrepareResult)
|
||||
{
|
||||
_shardingDbContext = shardingDbContext;
|
||||
_nativeQueryExpression = nativeQueryExpression;
|
||||
_shardingRouteConfigure = shardingPrepareResult.ShardingQueryableAsRouteOptions?.RouteConfigure;
|
||||
_useUnionAllMerge = shardingPrepareResult.UseUnionAllMerge;
|
||||
_maxQueryConnectionsLimit = shardingPrepareResult.ShardingQueryableUseConnectionModeOptions?.MaxQueryConnectionsLimit;
|
||||
_connectionMode = shardingPrepareResult.ShardingQueryableUseConnectionModeOptions?.ConnectionMode;
|
||||
if (shardingDbContext.IsUseReadWriteSeparation())
|
||||
{
|
||||
_readOnly = shardingPrepareResult?.ShardingQueryableReadWriteSeparationOptions?.RouteReadConnect ?? shardingDbContext.CurrentIsReadWriteSeparation();
|
||||
}
|
||||
|
||||
_isSequence = shardingPrepareResult.ShardingQueryableAsSequenceOptions?.AsSequence;
|
||||
_sameWithShardingComparer = shardingPrepareResult.ShardingQueryableAsSequenceOptions
|
||||
?.SameWithShardingComparer;
|
||||
_queryEntities = shardingPrepareResult.QueryEntities;
|
||||
_isNoTracking = shardingPrepareResult.IsNoTracking;
|
||||
_isIgnoreFilter = shardingPrepareResult.IsIgnoreFilter;
|
||||
}
|
||||
public IShardingDbContext GetShardingDbContext()
|
||||
{
|
||||
return _shardingDbContext;
|
||||
}
|
||||
|
||||
public Expression GetNativeQueryExpression()
|
||||
{
|
||||
return _nativeQueryExpression;
|
||||
}
|
||||
|
||||
public bool UseUnionAllMerge()
|
||||
{
|
||||
return _useUnionAllMerge;
|
||||
}
|
||||
|
||||
public int? GetMaxQueryConnectionsLimit()
|
||||
{
|
||||
return _maxQueryConnectionsLimit;
|
||||
}
|
||||
|
||||
public ConnectionModeEnum? GetConnectionMode()
|
||||
{
|
||||
return _connectionMode;
|
||||
}
|
||||
|
||||
public bool? ReadOnly()
|
||||
{
|
||||
return _readOnly;
|
||||
}
|
||||
|
||||
public Action<ShardingRouteContext> GetAsRoute()
|
||||
{
|
||||
return _shardingRouteConfigure;
|
||||
}
|
||||
|
||||
public bool? IsSequence()
|
||||
{
|
||||
return _isSequence;
|
||||
}
|
||||
|
||||
public bool? SameWithShardingComparer()
|
||||
{
|
||||
return _sameWithShardingComparer;
|
||||
}
|
||||
|
||||
public Dictionary<Type, IQueryable> GetQueryEntities()
|
||||
{
|
||||
return _queryEntities;
|
||||
}
|
||||
|
||||
public bool? IsNotracking()
|
||||
{
|
||||
return _isNoTracking;
|
||||
}
|
||||
|
||||
public bool IsIgnoreFilter()
|
||||
{
|
||||
return _isIgnoreFilter;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"query entity types :{string.Join(",",_queryEntities.Keys)},is no tracking: {_isNoTracking},is ignore filter :{_isIgnoreFilter},is not support :{_useUnionAllMerge},max query connections limit:{_maxQueryConnectionsLimit},connection mode:{_connectionMode},readonly:{_readOnly},as route:{_shardingRouteConfigure != null},is sequence:{_isSequence},same with sharding comparer:{_sameWithShardingComparer}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Extensions.ShardingQueryableExtensions;
|
||||
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: DATE TIME
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
namespace ShardingCore.Sharding.Visitors.ShardingExtractParameters
|
||||
{
|
||||
public class ShardingPrepareResult
|
||||
{
|
||||
public bool UseUnionAllMerge { get; }
|
||||
public ShardingQueryableAsRouteOptions ShardingQueryableAsRouteOptions { get; }
|
||||
public ShardingQueryableUseConnectionModeOptions ShardingQueryableUseConnectionModeOptions { get; }
|
||||
public ShardingQueryableReadWriteSeparationOptions ShardingQueryableReadWriteSeparationOptions { get; }
|
||||
public ShardingQueryableAsSequenceOptions ShardingQueryableAsSequenceOptions { get; }
|
||||
public Dictionary<Type, IQueryable> QueryEntities { get; }
|
||||
public bool? IsNoTracking { get; }
|
||||
public bool IsIgnoreFilter { get; }
|
||||
|
||||
|
||||
public ShardingPrepareResult(bool useUnionAllMerge,
|
||||
ShardingQueryableAsRouteOptions shardingQueryableAsRouteOptions,
|
||||
ShardingQueryableUseConnectionModeOptions shardingQueryableUseConnectionModeOptions,
|
||||
ShardingQueryableReadWriteSeparationOptions shardingQueryableReadWriteSeparationOptions,
|
||||
ShardingQueryableAsSequenceOptions shardingQueryableAsSequenceOptions, Dictionary<Type, IQueryable> queryEntities,
|
||||
bool? isNoTracking, bool isIgnoreFilter)
|
||||
{
|
||||
UseUnionAllMerge = useUnionAllMerge;
|
||||
ShardingQueryableAsRouteOptions = shardingQueryableAsRouteOptions;
|
||||
ShardingQueryableUseConnectionModeOptions = shardingQueryableUseConnectionModeOptions;
|
||||
ShardingQueryableReadWriteSeparationOptions = shardingQueryableReadWriteSeparationOptions;
|
||||
ShardingQueryableAsSequenceOptions = shardingQueryableAsSequenceOptions;
|
||||
QueryEntities = queryEntities;
|
||||
IsNoTracking = isNoTracking;
|
||||
IsIgnoreFilter = isIgnoreFilter;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,223 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using ShardingCore.Core.TrackerManagers;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.ShardingQueryableExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
|
||||
|
||||
namespace ShardingCore.Sharding.Parsers.Visitors
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/5/1 21:43:12
|
||||
/// Email: 326308290@qq.com
|
||||
internal class ShardingQueryPrepareVisitor : ExpressionVisitor
|
||||
{
|
||||
private readonly IShardingDbContext _shardingDbContext;
|
||||
private bool isNotSupport;
|
||||
private ShardingQueryableUseConnectionModeOptions shardingQueryableUseConnectionModeOptions;
|
||||
private ShardingQueryableAsRouteOptions shardingQueryableAsRouteOptions;
|
||||
private ShardingQueryableReadWriteSeparationOptions shardingQueryableReadWriteSeparationOptions;
|
||||
private ShardingQueryableAsSequenceOptions shardingQueryableAsSequenceOptions;
|
||||
|
||||
|
||||
|
||||
private readonly ITrackerManager _trackerManager;
|
||||
private bool? isNoTracking;
|
||||
private bool isIgnoreFilter;
|
||||
private readonly Dictionary<Type, IQueryable> shardingEntities = new();
|
||||
|
||||
public ShardingQueryPrepareVisitor(IShardingDbContext shardingDbContext)
|
||||
{
|
||||
_shardingDbContext = shardingDbContext;
|
||||
_trackerManager = ShardingContainer.GetTrackerManager(shardingDbContext.GetType());
|
||||
}
|
||||
public ShardingPrepareResult GetShardingPrepareResult()
|
||||
{
|
||||
return new ShardingPrepareResult(isNotSupport,
|
||||
shardingQueryableAsRouteOptions,
|
||||
shardingQueryableUseConnectionModeOptions,
|
||||
shardingQueryableReadWriteSeparationOptions,
|
||||
shardingQueryableAsSequenceOptions,
|
||||
shardingEntities, isNoTracking, isIgnoreFilter);
|
||||
}
|
||||
#if EFCORE2 || EFCORE3
|
||||
protected override Expression VisitConstant(ConstantExpression node)
|
||||
{
|
||||
if (node.Value is IQueryable queryable)
|
||||
{
|
||||
TryAddShardingEntities(queryable.ElementType, null);
|
||||
}
|
||||
|
||||
return base.VisitConstant(node);
|
||||
}
|
||||
#endif
|
||||
#if EFCORE5 || EFCORE6
|
||||
protected override Expression VisitExtension(Expression node)
|
||||
{
|
||||
if (node is QueryRootExpression queryRootExpression)
|
||||
{
|
||||
TryAddShardingEntities(queryRootExpression.EntityType.ClrType, null);
|
||||
}
|
||||
return base.VisitExtension(node);
|
||||
}
|
||||
#endif
|
||||
private void TryAddShardingEntities(Type entityType, IQueryable queryable)
|
||||
{
|
||||
if (!shardingEntities.ContainsKey(entityType))
|
||||
{
|
||||
shardingEntities.Add(entityType, queryable);
|
||||
}
|
||||
}
|
||||
|
||||
protected override Expression VisitMember
|
||||
(MemberExpression memberExpression)
|
||||
{
|
||||
|
||||
if (memberExpression.IsMemberQueryable()) //2x,3x 路由 单元测试 分表和不分表
|
||||
{
|
||||
// Recurse down to see if we can simplify...
|
||||
var expression = Visit(memberExpression.Expression);
|
||||
|
||||
// If we've ended up with a constant, and it's a property or a field,
|
||||
// we can simplify ourselves to a constant
|
||||
if (expression is ConstantExpression)
|
||||
{
|
||||
object container = ((ConstantExpression)expression).Value;
|
||||
var member = memberExpression.Member;
|
||||
if (member is FieldInfo fieldInfo)
|
||||
{
|
||||
object value = fieldInfo.GetValue(container);
|
||||
if (value is IQueryable queryable)
|
||||
{
|
||||
TryAddShardingEntities(queryable.ElementType, queryable);
|
||||
}
|
||||
//return Expression.Constant(value);
|
||||
}
|
||||
if (member is PropertyInfo propertyInfo)
|
||||
{
|
||||
object value = propertyInfo.GetValue(container, null);
|
||||
if (value is IQueryable queryable)
|
||||
{
|
||||
TryAddShardingEntities(queryable.ElementType, queryable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.VisitMember(memberExpression);
|
||||
}
|
||||
protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||
{
|
||||
|
||||
switch (node.Method.Name)
|
||||
{
|
||||
case nameof(EntityFrameworkQueryableExtensions.AsNoTracking): isNoTracking = true; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.AsTracking): isNoTracking = false; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreFilter = true; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.Include):
|
||||
case nameof(EntityFrameworkQueryableExtensions.ThenInclude): DiscoverQueryEntities(node); break;
|
||||
default:
|
||||
{
|
||||
var customerExpression = DiscoverCustomerQueryEntities(node);
|
||||
if (customerExpression != null)
|
||||
{
|
||||
return Visit(customerExpression);
|
||||
}
|
||||
}
|
||||
; break;
|
||||
}
|
||||
|
||||
|
||||
return base.VisitMethodCall(node);
|
||||
}
|
||||
|
||||
private Expression DiscoverCustomerQueryEntities(MethodCallExpression node)
|
||||
{
|
||||
|
||||
if (node.Method.IsGenericMethod)
|
||||
{
|
||||
var genericMethodDefinition = node.Method.GetGenericMethodDefinition();
|
||||
|
||||
// find notsupport extention calls
|
||||
if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.NotSupportMethodInfo)
|
||||
{
|
||||
isNotSupport = true;
|
||||
// cut out extension expression
|
||||
return node.Arguments[0];
|
||||
}
|
||||
else if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.UseConnectionModeMethodInfo)
|
||||
{
|
||||
shardingQueryableUseConnectionModeOptions = node.Arguments
|
||||
.OfType<ConstantExpression>()
|
||||
.Where(o => o.Value is ShardingQueryableUseConnectionModeOptions)
|
||||
.Select(o => (ShardingQueryableUseConnectionModeOptions)o.Value)
|
||||
.Last();
|
||||
return node.Arguments[0];
|
||||
}
|
||||
else if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.AsRouteMethodInfo)
|
||||
{
|
||||
shardingQueryableAsRouteOptions = node.Arguments
|
||||
.OfType<ConstantExpression>()
|
||||
.Where(o => o.Value is ShardingQueryableAsRouteOptions)
|
||||
.Select(o => (ShardingQueryableAsRouteOptions)o.Value)
|
||||
.Last();
|
||||
return node.Arguments[0];
|
||||
}
|
||||
else if (genericMethodDefinition == EntityFrameworkShardingQueryableExtension.AsSequenceModeMethodInfo)
|
||||
{
|
||||
shardingQueryableAsSequenceOptions = node.Arguments
|
||||
.OfType<ConstantExpression>()
|
||||
.Where(o => o.Value is ShardingQueryableAsSequenceOptions)
|
||||
.Select(o => (ShardingQueryableAsSequenceOptions)o.Value)
|
||||
.Last();
|
||||
return node.Arguments[0];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void DiscoverQueryEntities(MethodCallExpression node)
|
||||
{
|
||||
var genericArguments = node.Type.GetGenericArguments();
|
||||
for (var i = 0; i < genericArguments.Length; i++)
|
||||
{
|
||||
var genericArgument = genericArguments[i];
|
||||
if (typeof(IEnumerable).IsAssignableFrom(genericArgument))
|
||||
{
|
||||
var arguments = genericArgument.GetGenericArguments();
|
||||
foreach (var argument in arguments)
|
||||
{
|
||||
//if is db context model
|
||||
if (_trackerManager.IsDbContextModel(argument))
|
||||
{
|
||||
TryAddShardingEntities(argument, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!genericArgument.IsSimpleType())
|
||||
{
|
||||
//if is db context model
|
||||
if (_trackerManager.IsDbContextModel(genericArgument))
|
||||
{
|
||||
TryAddShardingEntities(genericArgument, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
|
|||
{
|
||||
public interface IQueryCompilerContext
|
||||
{
|
||||
ISet<Type> GetQueryEntities();
|
||||
Dictionary<Type, IQueryable> GetQueryEntities();
|
||||
IShardingDbContext GetShardingDbContext();
|
||||
Expression GetQueryExpression();
|
||||
IEntityMetadataManager GetEntityMetadataManager();
|
||||
|
|
|
@ -1,100 +1,100 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.QueryRouteManagers;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
|
||||
//using System;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq.Expressions;
|
||||
//using ShardingCore.Core;
|
||||
//using ShardingCore.Core.QueryRouteManagers;
|
||||
//using ShardingCore.Extensions;
|
||||
//using ShardingCore.Sharding.Abstractions;
|
||||
//using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
//using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
|
||||
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: DATE TIME
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
namespace ShardingCore.ShardingExecutors
|
||||
{
|
||||
public class CompileParameter:ICompileParameter,IPrint
|
||||
{
|
||||
private readonly IShardingDbContext _shardingDbContext;
|
||||
private readonly Expression _nativeQueryExpression;
|
||||
private readonly bool _useUnionAllMerge;
|
||||
private readonly int? _maxQueryConnectionsLimit;
|
||||
private readonly ConnectionModeEnum? _connectionMode;
|
||||
private readonly bool? _readOnly;
|
||||
private readonly Action<ShardingRouteContext> _shardingRouteConfigure;
|
||||
private readonly bool? _isSequence;
|
||||
private readonly bool? _sameWithShardingComparer;
|
||||
public CompileParameter(IShardingDbContext shardingDbContext,Expression shardingQueryExpression)
|
||||
{
|
||||
_shardingDbContext = shardingDbContext;
|
||||
var shardingQueryableExtractParameter = new ShardingQueryableExtractParameterVisitor();
|
||||
_nativeQueryExpression = shardingQueryableExtractParameter.Visit(shardingQueryExpression);
|
||||
var extractShardingParameter = shardingQueryableExtractParameter.ExtractShardingParameter();
|
||||
_shardingRouteConfigure = extractShardingParameter.ShardingQueryableAsRouteOptions?.RouteConfigure;
|
||||
_useUnionAllMerge = extractShardingParameter.UseUnionAllMerge;
|
||||
_maxQueryConnectionsLimit = extractShardingParameter.ShardingQueryableUseConnectionModeOptions?.MaxQueryConnectionsLimit;
|
||||
_connectionMode = extractShardingParameter.ShardingQueryableUseConnectionModeOptions?.ConnectionMode;
|
||||
if (shardingDbContext.IsUseReadWriteSeparation())
|
||||
{
|
||||
_readOnly = extractShardingParameter?.ShardingQueryableReadWriteSeparationOptions?.RouteReadConnect??shardingDbContext.CurrentIsReadWriteSeparation();
|
||||
}
|
||||
///*
|
||||
//* @Author: xjm
|
||||
//* @Description:
|
||||
//* @Date: DATE TIME
|
||||
//* @Email: 326308290@qq.com
|
||||
//*/
|
||||
//namespace ShardingCore.ShardingExecutors
|
||||
//{
|
||||
// public class CompileParameter:ICompileParameter,IPrint
|
||||
// {
|
||||
// private readonly IShardingDbContext _shardingDbContext;
|
||||
// private readonly Expression _nativeQueryExpression;
|
||||
// private readonly bool _useUnionAllMerge;
|
||||
// private readonly int? _maxQueryConnectionsLimit;
|
||||
// private readonly ConnectionModeEnum? _connectionMode;
|
||||
// private readonly bool? _readOnly;
|
||||
// private readonly Action<ShardingRouteContext> _shardingRouteConfigure;
|
||||
// private readonly bool? _isSequence;
|
||||
// private readonly bool? _sameWithShardingComparer;
|
||||
// public CompileParameter(IShardingDbContext shardingDbContext,Expression shardingQueryExpression)
|
||||
// {
|
||||
// _shardingDbContext = shardingDbContext;
|
||||
// var shardingQueryableExtractParameter = new ShardingQueryableExtractParameterVisitor();
|
||||
// _nativeQueryExpression = shardingQueryableExtractParameter.Visit(shardingQueryExpression);
|
||||
// var extractShardingParameter = shardingQueryableExtractParameter.ExtractShardingParameter();
|
||||
// _shardingRouteConfigure = extractShardingParameter.ShardingQueryableAsRouteOptions?.RouteConfigure;
|
||||
// _useUnionAllMerge = extractShardingParameter.UseUnionAllMerge;
|
||||
// _maxQueryConnectionsLimit = extractShardingParameter.ShardingQueryableUseConnectionModeOptions?.MaxQueryConnectionsLimit;
|
||||
// _connectionMode = extractShardingParameter.ShardingQueryableUseConnectionModeOptions?.ConnectionMode;
|
||||
// if (shardingDbContext.IsUseReadWriteSeparation())
|
||||
// {
|
||||
// _readOnly = extractShardingParameter?.ShardingQueryableReadWriteSeparationOptions?.RouteReadConnect??shardingDbContext.CurrentIsReadWriteSeparation();
|
||||
// }
|
||||
|
||||
_isSequence = extractShardingParameter.ShardingQueryableAsSequenceOptions?.AsSequence;
|
||||
_sameWithShardingComparer = extractShardingParameter.ShardingQueryableAsSequenceOptions
|
||||
?.SameWithShardingComparer;
|
||||
}
|
||||
// _isSequence = extractShardingParameter.ShardingQueryableAsSequenceOptions?.AsSequence;
|
||||
// _sameWithShardingComparer = extractShardingParameter.ShardingQueryableAsSequenceOptions
|
||||
// ?.SameWithShardingComparer;
|
||||
// }
|
||||
|
||||
public IShardingDbContext GetShardingDbContext()
|
||||
{
|
||||
return _shardingDbContext;
|
||||
}
|
||||
// public IShardingDbContext GetShardingDbContext()
|
||||
// {
|
||||
// return _shardingDbContext;
|
||||
// }
|
||||
|
||||
public Expression GetNativeQueryExpression()
|
||||
{
|
||||
return _nativeQueryExpression;
|
||||
}
|
||||
// public Expression GetNativeQueryExpression()
|
||||
// {
|
||||
// return _nativeQueryExpression;
|
||||
// }
|
||||
|
||||
public bool UseUnionAllMerge()
|
||||
{
|
||||
return _useUnionAllMerge;
|
||||
}
|
||||
// public bool UseUnionAllMerge()
|
||||
// {
|
||||
// return _useUnionAllMerge;
|
||||
// }
|
||||
|
||||
public int? GetMaxQueryConnectionsLimit()
|
||||
{
|
||||
return _maxQueryConnectionsLimit;
|
||||
}
|
||||
// public int? GetMaxQueryConnectionsLimit()
|
||||
// {
|
||||
// return _maxQueryConnectionsLimit;
|
||||
// }
|
||||
|
||||
public ConnectionModeEnum? GetConnectionMode()
|
||||
{
|
||||
return _connectionMode;
|
||||
}
|
||||
// public ConnectionModeEnum? GetConnectionMode()
|
||||
// {
|
||||
// return _connectionMode;
|
||||
// }
|
||||
|
||||
public bool? ReadOnly()
|
||||
{
|
||||
return _readOnly;
|
||||
}
|
||||
// public bool? ReadOnly()
|
||||
// {
|
||||
// return _readOnly;
|
||||
// }
|
||||
|
||||
public Action<ShardingRouteContext> GetAsRoute()
|
||||
{
|
||||
return _shardingRouteConfigure;
|
||||
}
|
||||
// public Action<ShardingRouteContext> GetAsRoute()
|
||||
// {
|
||||
// return _shardingRouteConfigure;
|
||||
// }
|
||||
|
||||
public bool? IsSequence()
|
||||
{
|
||||
return _isSequence;
|
||||
}
|
||||
// public bool? IsSequence()
|
||||
// {
|
||||
// return _isSequence;
|
||||
// }
|
||||
|
||||
public bool? SameWithShardingComparer()
|
||||
{
|
||||
return _sameWithShardingComparer;
|
||||
}
|
||||
// public bool? SameWithShardingComparer()
|
||||
// {
|
||||
// return _sameWithShardingComparer;
|
||||
// }
|
||||
|
||||
public string GetPrintInfo()
|
||||
{
|
||||
return $"is not support :{_useUnionAllMerge},max query connections limit:{_maxQueryConnectionsLimit},connection mode:{_connectionMode},readonly:{_readOnly},as route:{_shardingRouteConfigure!=null},is sequence:{_isSequence},same with sharding comparer:{_sameWithShardingComparer}";
|
||||
}
|
||||
}
|
||||
}
|
||||
// public string GetPrintInfo()
|
||||
// {
|
||||
// return $"is not support :{_useUnionAllMerge},max query connections limit:{_maxQueryConnectionsLimit},connection mode:{_connectionMode},readonly:{_readOnly},as route:{_shardingRouteConfigure!=null},is sequence:{_isSequence},same with sharding comparer:{_sameWithShardingComparer}";
|
||||
// }
|
||||
// }
|
||||
//}
|
|
@ -2,6 +2,7 @@
|
|||
using ShardingCore.Core.QueryRouteManagers;
|
||||
using ShardingCore.Core.QueryRouteManagers.Abstractions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
@ -18,12 +19,12 @@ namespace ShardingCore.ShardingExecutors
|
|||
{
|
||||
private readonly ShardingRouteScope _shardingRouteScope;
|
||||
private readonly bool _hasCustomerQuery;
|
||||
public CustomerQueryScope(ICompileParameter compileParameter)
|
||||
public CustomerQueryScope(IPrepareParseResult prepareParseResult)
|
||||
{
|
||||
_hasCustomerQuery = compileParameter.HasCustomerQuery();
|
||||
_hasCustomerQuery = prepareParseResult.HasCustomerQuery();
|
||||
if (_hasCustomerQuery)
|
||||
{
|
||||
var asRoute = compileParameter.GetAsRoute();
|
||||
var asRoute = prepareParseResult.GetAsRoute();
|
||||
if ( asRoute!= null)
|
||||
{
|
||||
var shardingRouteManager = ShardingContainer.GetService<IShardingRouteManager>();
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
using ShardingCore.Sharding.Visitors.ShardingExtractParameters;
|
||||
using ShardingCore.ShardingExecutors;
|
||||
|
@ -16,20 +17,24 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
private readonly ILogger<DefaultShardingComplierExecutor> _logger;
|
||||
private readonly IShardingTrackQueryExecutor _shardingTrackQueryExecutor;
|
||||
private readonly IQueryCompilerContextFactory _queryCompilerContextFactory;
|
||||
private readonly IPrepareParser _prepareParser;
|
||||
|
||||
public DefaultShardingComplierExecutor(ILogger<DefaultShardingComplierExecutor> logger,IShardingTrackQueryExecutor shardingTrackQueryExecutor, IQueryCompilerContextFactory queryCompilerContextFactory)
|
||||
public DefaultShardingComplierExecutor(ILogger<DefaultShardingComplierExecutor> logger,
|
||||
IShardingTrackQueryExecutor shardingTrackQueryExecutor, IQueryCompilerContextFactory queryCompilerContextFactory,IPrepareParser prepareParser)
|
||||
{
|
||||
_logger = logger;
|
||||
_shardingTrackQueryExecutor = shardingTrackQueryExecutor;
|
||||
_queryCompilerContextFactory = queryCompilerContextFactory;
|
||||
_prepareParser = prepareParser;
|
||||
}
|
||||
public TResult Execute<TResult>(IShardingDbContext shardingDbContext, Expression query)
|
||||
{
|
||||
var compileParameter = new CompileParameter(shardingDbContext,query);
|
||||
_logger.LogDebug($"compile parameter:{compileParameter.GetPrintInfo()}");
|
||||
using (new CustomerQueryScope(compileParameter))
|
||||
//预解析表达式
|
||||
var prepareParseResult = _prepareParser.Parse(shardingDbContext,query);
|
||||
_logger.LogDebug($"compile parameter:{prepareParseResult}");
|
||||
using (new CustomerQueryScope(prepareParseResult))
|
||||
{
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(prepareParseResult);
|
||||
return _shardingTrackQueryExecutor.Execute<TResult>(queryCompilerContext);
|
||||
}
|
||||
|
||||
|
@ -41,12 +46,13 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
public TResult ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var compileParameter = new CompileParameter(shardingDbContext,query);
|
||||
_logger.LogDebug($"compile parameter:{compileParameter.GetPrintInfo()}");
|
||||
//预解析表达式
|
||||
var prepareParseResult = _prepareParser.Parse(shardingDbContext, query);
|
||||
_logger.LogDebug($"compile parameter:{prepareParseResult}");
|
||||
|
||||
using (new CustomerQueryScope(compileParameter))
|
||||
using (new CustomerQueryScope(prepareParseResult))
|
||||
{
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(prepareParseResult);
|
||||
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
|
||||
}
|
||||
}
|
||||
|
@ -55,11 +61,12 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
#if EFCORE2
|
||||
public IAsyncEnumerable<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query)
|
||||
{
|
||||
var compileParameter = new CompileParameter(shardingDbContext,query);
|
||||
_logger.LogDebug($"compile parameter:{compileParameter.GetPrintInfo()}");
|
||||
using (new CustomerQueryScope(compileParameter))
|
||||
//预解析表达式
|
||||
var prepareParseResult = _prepareParser.Parse(shardingDbContext, query);
|
||||
_logger.LogDebug($"compile parameter:{prepareParseResult}");
|
||||
using (new CustomerQueryScope(prepareParseResult))
|
||||
{
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(prepareParseResult);
|
||||
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext);
|
||||
}
|
||||
}
|
||||
|
@ -67,11 +74,12 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
public Task<TResult> ExecuteAsync<TResult>(IShardingDbContext shardingDbContext, Expression query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var compileParameter = new CompileParameter(shardingDbContext,query);
|
||||
_logger.LogDebug($"compile parameter:{compileParameter.GetPrintInfo()}");
|
||||
using (new CustomerQueryScope(compileParameter))
|
||||
//预解析表达式
|
||||
var prepareParseResult = _prepareParser.Parse(shardingDbContext, query);
|
||||
_logger.LogDebug($"compile parameter:{prepareParseResult}");
|
||||
using (new CustomerQueryScope(prepareParseResult))
|
||||
{
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(compileParameter);
|
||||
var queryCompilerContext = _queryCompilerContextFactory.Create(prepareParseResult);
|
||||
return _shardingTrackQueryExecutor.ExecuteAsync<TResult>(queryCompilerContext, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
#endif
|
||||
|
@ -123,7 +124,7 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors
|
|||
var streamMergeContext= streamMergeContextMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamMergeContextFactory, new object[] { mergeQueryCompilerContext });
|
||||
if (streamMergeContext is IPrint print)
|
||||
{
|
||||
_logger.LogDebug(print.GetPrintInfo());
|
||||
_logger.LogLazyDebug(()=> print.GetPrintInfo());
|
||||
}
|
||||
return streamMergeContext;
|
||||
#endif
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
if (_queryCompilerContext.GetQueryEntities().Count > 1&& routeResults.Length>0)
|
||||
{
|
||||
var entityMetadataManager = _queryCompilerContext.GetEntityMetadataManager();
|
||||
var queryShardingTables = _queryCompilerContext.GetQueryEntities().Where(o => entityMetadataManager.IsShardingTable(o)).ToArray();
|
||||
var queryShardingTables = _queryCompilerContext.GetQueryEntities().Keys.Where(o => entityMetadataManager.IsShardingTable(o)).ToArray();
|
||||
if (queryShardingTables.Length > 1 && _parallelTableManager.IsParallelTableQuery(queryShardingTables))
|
||||
{
|
||||
return routeResults.Where(o => o.ReplaceTables.Select(p => p.Tail).ToHashSet().Count == 1);
|
||||
|
@ -75,7 +75,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
{
|
||||
return new MergeQueryCompilerContext(queryCompilerContext, queryCombineResult,dataSourceRouteResult, tableRouteResults);
|
||||
}
|
||||
public ISet<Type> GetQueryEntities()
|
||||
public Dictionary<Type,IQueryable> GetQueryEntities()
|
||||
{
|
||||
return _queryCompilerContext.GetQueryEntities();
|
||||
}
|
||||
|
|
|
@ -10,12 +10,14 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Sharding.Parsers;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.ShardingExecutors
|
||||
{
|
||||
public class QueryCompilerContext: IQueryCompilerContext
|
||||
{
|
||||
private readonly ISet<Type> _queryEntities;
|
||||
private readonly Dictionary<Type/* 查询对象类型 */, IQueryable/* 查询对象对应的表达式 */> _queryEntities;
|
||||
private readonly IShardingDbContext _shardingDbContext;
|
||||
private readonly Expression _queryExpression;
|
||||
private readonly IEntityMetadataManager _entityMetadataManager;
|
||||
|
@ -30,31 +32,31 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
private readonly bool? _isSequence;
|
||||
private readonly bool? _sameWithShardingComparer;
|
||||
|
||||
private QueryCompilerContext(ICompileParameter compileParameter)
|
||||
private QueryCompilerContext(IPrepareParseResult prepareParseResult)
|
||||
{
|
||||
_shardingDbContext = compileParameter.GetShardingDbContext();
|
||||
_queryExpression = compileParameter.GetNativeQueryExpression();
|
||||
_shardingDbContext = prepareParseResult.GetShardingDbContext();
|
||||
_queryExpression = prepareParseResult.GetNativeQueryExpression();
|
||||
_shardingDbContextType = _shardingDbContext.GetType();
|
||||
var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(_queryExpression, _shardingDbContextType);
|
||||
_queryEntities = compileParseResult.QueryEntities;
|
||||
_isNoTracking = compileParseResult.IsNoTracking;
|
||||
_useUnionAllMerge = compileParameter.UseUnionAllMerge();
|
||||
_maxQueryConnectionsLimit = compileParameter.GetMaxQueryConnectionsLimit();
|
||||
_connectionMode = compileParameter.GetConnectionMode();
|
||||
//var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(_queryExpression, _shardingDbContextType);
|
||||
_queryEntities = prepareParseResult.GetQueryEntities();
|
||||
_isNoTracking = prepareParseResult.IsNotracking();
|
||||
_useUnionAllMerge = prepareParseResult.UseUnionAllMerge();
|
||||
_maxQueryConnectionsLimit = prepareParseResult.GetMaxQueryConnectionsLimit();
|
||||
_connectionMode = prepareParseResult.GetConnectionMode();
|
||||
_entityMetadataManager = ShardingContainer.GetRequiredEntityMetadataManager(_shardingDbContextType);
|
||||
|
||||
//原生对象的原生查询如果是读写分离就需要启用并行查询
|
||||
_isParallelQuery = compileParameter.ReadOnly().GetValueOrDefault();
|
||||
_isSequence = compileParameter.IsSequence();
|
||||
_sameWithShardingComparer = compileParameter.SameWithShardingComparer();
|
||||
_isParallelQuery = prepareParseResult.ReadOnly().GetValueOrDefault();
|
||||
_isSequence = prepareParseResult.IsSequence();
|
||||
_sameWithShardingComparer = prepareParseResult.SameWithShardingComparer();
|
||||
}
|
||||
|
||||
public static QueryCompilerContext Create(ICompileParameter compileParameter)
|
||||
public static QueryCompilerContext Create(IPrepareParseResult prepareParseResult)
|
||||
{
|
||||
return new QueryCompilerContext(compileParameter);
|
||||
return new QueryCompilerContext(prepareParseResult);
|
||||
}
|
||||
|
||||
public ISet<Type> GetQueryEntities()
|
||||
public Dictionary<Type, IQueryable> GetQueryEntities()
|
||||
{
|
||||
return _queryEntities;
|
||||
}
|
||||
|
@ -127,19 +129,19 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
|
||||
public bool IsSingleShardingEntityQuery()
|
||||
{
|
||||
return _queryEntities.Count(o => _entityMetadataManager.IsSharding(o)) == 1;
|
||||
return _queryEntities.Keys.Where(o => _entityMetadataManager.IsSharding(o)).Take(2).Count() == 1;
|
||||
}
|
||||
|
||||
public Type GetSingleShardingEntityType()
|
||||
{
|
||||
return _queryEntities.Single(o => _entityMetadataManager.IsSharding(o));
|
||||
return _queryEntities.Keys.Single(o => _entityMetadataManager.IsSharding(o));
|
||||
}
|
||||
|
||||
public QueryCompilerExecutor GetQueryCompilerExecutor()
|
||||
{
|
||||
if (!hasQueryCompilerExecutor.HasValue)
|
||||
{
|
||||
hasQueryCompilerExecutor = _queryEntities.All(o => !_entityMetadataManager.IsSharding(o));
|
||||
hasQueryCompilerExecutor = _queryEntities.Keys.All(o => !_entityMetadataManager.IsSharding(o));
|
||||
if (hasQueryCompilerExecutor.Value)
|
||||
{
|
||||
var virtualDataSource = _shardingDbContext.GetVirtualDataSource();
|
||||
|
|
|
@ -9,6 +9,8 @@ using ShardingCore.Sharding.ShardingExecutors.QueryableCombines;
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Parsers.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.ShardingExecutors
|
||||
{
|
||||
|
@ -35,13 +37,13 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
public IQueryCompilerContext Create(ICompileParameter compileParameter)
|
||||
public IQueryCompilerContext Create(IPrepareParseResult prepareParseResult)
|
||||
{
|
||||
var queryCompilerContext =
|
||||
QueryCompilerContext.Create(compileParameter);
|
||||
QueryCompilerContext.Create(prepareParseResult);
|
||||
if (queryCompilerContext.GetQueryCompilerExecutor() is not null)
|
||||
{
|
||||
_logger.LogDebug($"{queryCompilerContext.GetQueryExpression().ShardingPrint()} is native query");
|
||||
_logger.LogLazyDebug(()=>$"{queryCompilerContext.GetQueryExpression().ShardingPrint()} is native query");
|
||||
return queryCompilerContext;
|
||||
}
|
||||
|
||||
|
@ -49,13 +51,13 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
_logger.LogDebug($"queryable combine:{queryableCombine.GetType()}");
|
||||
var dataSourceRouteRuleEngineFactory = (IDataSourceRouteRuleEngineFactory)ShardingContainer.GetService(typeof(IDataSourceRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
|
||||
var tableRouteRuleEngineFactory = (ITableRouteRuleEngineFactory)ShardingContainer.GetService(typeof(ITableRouteRuleEngineFactory<>).GetGenericType0(queryCompilerContext.GetShardingDbContextType()));
|
||||
_logger.LogDebug($"queryable combine before:{queryCompilerContext.GetQueryExpression().ShardingPrint()}");
|
||||
_logger.LogLazyDebug(() => $"queryable combine before:{queryCompilerContext.GetQueryExpression().ShardingPrint()}");
|
||||
var queryCombineResult = queryableCombine.Combine(queryCompilerContext);
|
||||
_logger.LogDebug($"queryable combine after:{queryCombineResult.GetCombineQueryable().ShardingPrint()}");
|
||||
var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(), compileParameter.GetShardingDbContext());
|
||||
_logger.LogDebug(dataSourceRouteResult.GetPrintInfo());
|
||||
var routeResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable()).ToArray();
|
||||
_logger.LogDebug($"table route results:{string.Join(","+Environment.NewLine,routeResults.Select(o=>o.GetPrintInfo()))}");
|
||||
_logger.LogLazyDebug(() => $"queryable combine after:{queryCombineResult.GetCombineQueryable().ShardingPrint()}");
|
||||
var dataSourceRouteResult = dataSourceRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(), prepareParseResult.GetShardingDbContext(), prepareParseResult.GetQueryEntities());
|
||||
_logger.LogLazyDebug(() => $"{dataSourceRouteResult}");
|
||||
var routeResults = tableRouteRuleEngineFactory.Route(queryCombineResult.GetCombineQueryable(), prepareParseResult.GetQueryEntities()).ToArray();
|
||||
_logger.LogLazyDebug(() => $"table route results:{string.Join(","+Environment.NewLine,routeResults.Select(o=>o.GetPrintInfo()))}");
|
||||
var mergeCombineCompilerContext = MergeQueryCompilerContext.Create(queryCompilerContext, queryCombineResult, dataSourceRouteResult,
|
||||
routeResults);
|
||||
return mergeCombineCompilerContext;
|
||||
|
|
|
@ -52,7 +52,8 @@ namespace ShardingCore.Sharding
|
|||
/// <summary>
|
||||
/// 本次查询涉及的对象
|
||||
/// </summary>
|
||||
public ISet<Type> QueryEntities => MergeQueryCompilerContext.GetQueryEntities();
|
||||
public ISet<Type> QueryEntities { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 本次查询跨库
|
||||
|
@ -86,7 +87,7 @@ namespace ShardingCore.Sharding
|
|||
RewriteQueryable = rewriteQueryable;
|
||||
OptimizeResult = optimizeResult;
|
||||
_routeTailFactory = routeTailFactory;
|
||||
|
||||
QueryEntities= MergeQueryCompilerContext.GetQueryEntities().Keys.ToHashSet();
|
||||
_trackerManager = ShardingContainer.GetTrackerManager(mergeQueryCompilerContext.GetShardingDbContextType());
|
||||
_shardingEntityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(mergeQueryCompilerContext.GetShardingDbContextType());
|
||||
_parallelDbContexts = new ConcurrentDictionary<DbContext, object>();
|
||||
|
@ -184,7 +185,7 @@ namespace ShardingCore.Sharding
|
|||
|
||||
public bool IsSingleShardingEntityQuery()
|
||||
{
|
||||
return QueryEntities.Count(o => MergeQueryCompilerContext.GetEntityMetadataManager().IsSharding(o)) == 1;
|
||||
return QueryEntities.Where(o => MergeQueryCompilerContext.GetEntityMetadataManager().IsSharding(o)).Take(2).Count() == 1;
|
||||
}
|
||||
public Type GetSingleShardingEntityType()
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -8,7 +9,7 @@ namespace ShardingCore.Sharding.Visitors.Querys
|
|||
{
|
||||
public class CompileParseResult
|
||||
{
|
||||
public CompileParseResult(bool? isNoTracking, bool isIgnoreFilter, ISet<Type> queryEntities)
|
||||
public CompileParseResult(bool? isNoTracking, bool isIgnoreFilter, Dictionary<Type, Expression> queryEntities)
|
||||
{
|
||||
IsNoTracking = isNoTracking;
|
||||
IsIgnoreFilter = isIgnoreFilter;
|
||||
|
@ -25,6 +26,6 @@ namespace ShardingCore.Sharding.Visitors.Querys
|
|||
/// <summary>
|
||||
/// 当前涉及到的查询对象
|
||||
/// </summary>
|
||||
public ISet<Type> QueryEntities { get; }
|
||||
public Dictionary<Type, Expression> QueryEntities { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,131 +1,131 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.TrackerManagers;
|
||||
using ShardingCore.Extensions;
|
||||
//using System;
|
||||
//using System.Collections;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Linq;
|
||||
//using System.Linq.Expressions;
|
||||
//using System.Reflection;
|
||||
//using System.Text;
|
||||
//using System.Threading.Tasks;
|
||||
//using Microsoft.EntityFrameworkCore;
|
||||
//using Microsoft.EntityFrameworkCore.Query;
|
||||
//using ShardingCore.Core.Internal.Visitors;
|
||||
//using ShardingCore.Core.TrackerManagers;
|
||||
//using ShardingCore.Extensions;
|
||||
|
||||
namespace ShardingCore.Sharding.Visitors.Querys
|
||||
{
|
||||
internal class QueryCompileParseVisitors : ExpressionVisitor
|
||||
{
|
||||
private readonly ITrackerManager _trackerManager;
|
||||
private bool? isNoTracking;
|
||||
private bool isIgnoreFilter;
|
||||
private readonly ISet<Type> shardingEntities = new HashSet<Type>();
|
||||
//namespace ShardingCore.Sharding.Visitors.Querys
|
||||
//{
|
||||
// internal class QueryCompileParseVisitors : ExpressionVisitor
|
||||
// {
|
||||
// private readonly ITrackerManager _trackerManager;
|
||||
// private bool? isNoTracking;
|
||||
// private bool isIgnoreFilter;
|
||||
// private readonly ISet<Type> shardingEntities = new HashSet<Type>();
|
||||
|
||||
public QueryCompileParseVisitors(ITrackerManager trackerManager)
|
||||
{
|
||||
_trackerManager = trackerManager;
|
||||
}
|
||||
// public QueryCompileParseVisitors(ITrackerManager trackerManager)
|
||||
// {
|
||||
// _trackerManager = trackerManager;
|
||||
// }
|
||||
|
||||
public CompileParseResult GetCompileParseResult()
|
||||
{
|
||||
return new CompileParseResult(isNoTracking, isIgnoreFilter, shardingEntities);
|
||||
}
|
||||
#if EFCORE2 || EFCORE3
|
||||
protected override Expression VisitConstant(ConstantExpression node)
|
||||
{
|
||||
if (node.Value is IQueryable queryable)
|
||||
{
|
||||
shardingEntities.Add(queryable.ElementType);
|
||||
}
|
||||
// public CompileParseResult GetCompileParseResult()
|
||||
// {
|
||||
// return new CompileParseResult(isNoTracking, isIgnoreFilter, shardingEntities);
|
||||
// }
|
||||
//#if EFCORE2 || EFCORE3
|
||||
// protected override Expression VisitConstant(ConstantExpression node)
|
||||
// {
|
||||
// if (node.Value is IQueryable queryable)
|
||||
// {
|
||||
// shardingEntities.Add(queryable.ElementType);
|
||||
// }
|
||||
|
||||
return base.VisitConstant(node);
|
||||
}
|
||||
#endif
|
||||
#if EFCORE5 || EFCORE6
|
||||
protected override Expression VisitExtension(Expression node)
|
||||
{
|
||||
if (node is QueryRootExpression queryRootExpression)
|
||||
{
|
||||
shardingEntities.Add(queryRootExpression.EntityType.ClrType);
|
||||
}
|
||||
return base.VisitExtension(node);
|
||||
}
|
||||
#endif
|
||||
// return base.VisitConstant(node);
|
||||
// }
|
||||
//#endif
|
||||
//#if EFCORE5 || EFCORE6
|
||||
// protected override Expression VisitExtension(Expression node)
|
||||
// {
|
||||
// if (node is QueryRootExpression queryRootExpression)
|
||||
// {
|
||||
// shardingEntities.Add(queryRootExpression.EntityType.ClrType);
|
||||
// }
|
||||
// return base.VisitExtension(node);
|
||||
// }
|
||||
//#endif
|
||||
|
||||
protected override Expression VisitMember
|
||||
(MemberExpression memberExpression)
|
||||
{
|
||||
// Recurse down to see if we can simplify...
|
||||
var expression = Visit(memberExpression.Expression);
|
||||
// protected override Expression VisitMember
|
||||
// (MemberExpression memberExpression)
|
||||
// {
|
||||
// // Recurse down to see if we can simplify...
|
||||
// var expression = Visit(memberExpression.Expression);
|
||||
|
||||
// If we've ended up with a constant, and it's a property or a field,
|
||||
// we can simplify ourselves to a constant
|
||||
if (expression is ConstantExpression)
|
||||
{
|
||||
object container = ((ConstantExpression)expression).Value;
|
||||
var member = memberExpression.Member;
|
||||
if (member is FieldInfo fieldInfo)
|
||||
{
|
||||
object value = fieldInfo.GetValue(container);
|
||||
if (value is IQueryable queryable)
|
||||
{
|
||||
shardingEntities.Add(queryable.ElementType);
|
||||
}
|
||||
//return Expression.Constant(value);
|
||||
}
|
||||
if (member is PropertyInfo propertyInfo)
|
||||
{
|
||||
object value = propertyInfo.GetValue(container, null);
|
||||
if (value is IQueryable queryable)
|
||||
{
|
||||
shardingEntities.Add(queryable.ElementType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return base.VisitMember(memberExpression);
|
||||
}
|
||||
protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||
{
|
||||
switch (node.Method.Name)
|
||||
{
|
||||
case nameof(EntityFrameworkQueryableExtensions.AsNoTracking): isNoTracking = true; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.AsTracking): isNoTracking = false; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreFilter = true; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.Include):
|
||||
case nameof(EntityFrameworkQueryableExtensions.ThenInclude): DiscoverQueryEntities(node); break;
|
||||
}
|
||||
// // If we've ended up with a constant, and it's a property or a field,
|
||||
// // we can simplify ourselves to a constant
|
||||
// if (expression is ConstantExpression)
|
||||
// {
|
||||
// object container = ((ConstantExpression)expression).Value;
|
||||
// var member = memberExpression.Member;
|
||||
// if (member is FieldInfo fieldInfo)
|
||||
// {
|
||||
// object value = fieldInfo.GetValue(container);
|
||||
// if (value is IQueryable queryable)
|
||||
// {
|
||||
// shardingEntities.Add(queryable.ElementType);
|
||||
// }
|
||||
// //return Expression.Constant(value);
|
||||
// }
|
||||
// if (member is PropertyInfo propertyInfo)
|
||||
// {
|
||||
// object value = propertyInfo.GetValue(container, null);
|
||||
// if (value is IQueryable queryable)
|
||||
// {
|
||||
// shardingEntities.Add(queryable.ElementType);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return base.VisitMember(memberExpression);
|
||||
// }
|
||||
// protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||
// {
|
||||
// switch (node.Method.Name)
|
||||
// {
|
||||
// case nameof(EntityFrameworkQueryableExtensions.AsNoTracking): isNoTracking = true; break;
|
||||
// case nameof(EntityFrameworkQueryableExtensions.AsTracking): isNoTracking = false; break;
|
||||
// case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreFilter = true; break;
|
||||
// case nameof(EntityFrameworkQueryableExtensions.Include):
|
||||
// case nameof(EntityFrameworkQueryableExtensions.ThenInclude): DiscoverQueryEntities(node); break;
|
||||
// }
|
||||
|
||||
return base.VisitMethodCall(node);
|
||||
}
|
||||
// return base.VisitMethodCall(node);
|
||||
// }
|
||||
|
||||
private void DiscoverQueryEntities(MethodCallExpression node)
|
||||
{
|
||||
var genericArguments = node.Type.GetGenericArguments();
|
||||
for (var i = 0; i < genericArguments.Length; i++)
|
||||
{
|
||||
var genericArgument = genericArguments[i];
|
||||
if (typeof(IEnumerable).IsAssignableFrom(genericArgument))
|
||||
{
|
||||
var arguments = genericArgument.GetGenericArguments();
|
||||
foreach (var argument in arguments)
|
||||
{
|
||||
//if is db context model
|
||||
if (_trackerManager.IsDbContextModel(argument))
|
||||
{
|
||||
shardingEntities.Add(argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
// private void DiscoverQueryEntities(MethodCallExpression node)
|
||||
// {
|
||||
// var genericArguments = node.Type.GetGenericArguments();
|
||||
// for (var i = 0; i < genericArguments.Length; i++)
|
||||
// {
|
||||
// var genericArgument = genericArguments[i];
|
||||
// if (typeof(IEnumerable).IsAssignableFrom(genericArgument))
|
||||
// {
|
||||
// var arguments = genericArgument.GetGenericArguments();
|
||||
// foreach (var argument in arguments)
|
||||
// {
|
||||
// //if is db context model
|
||||
// if (_trackerManager.IsDbContextModel(argument))
|
||||
// {
|
||||
// shardingEntities.Add(argument);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if (!genericArgument.IsSimpleType())
|
||||
{
|
||||
//if is db context model
|
||||
if (_trackerManager.IsDbContextModel(genericArgument))
|
||||
{
|
||||
shardingEntities.Add(genericArgument);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (!genericArgument.IsSimpleType())
|
||||
// {
|
||||
// //if is db context model
|
||||
// if (_trackerManager.IsDbContextModel(genericArgument))
|
||||
// {
|
||||
// shardingEntities.Add(genericArgument);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.Visitors
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// Author: xjm
|
||||
/// Created: 2022/4/30 22:48:50
|
||||
/// Email: 326308290@qq.com
|
||||
public class SimpleQueryableParseVisitor
|
||||
{
|
||||
}
|
||||
}
|
|
@ -63,42 +63,42 @@ namespace ShardingCore.Utils
|
|||
return visitor.GetRouteParseExpression();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取本次查询的所有涉及到的对象
|
||||
/// </summary>
|
||||
/// <param name="queryable"></param>
|
||||
/// <param name="dbContextType"></param>
|
||||
/// <returns></returns>
|
||||
public static ISet<Type> GetQueryEntitiesFilter(IQueryable queryable,Type dbContextType)
|
||||
{
|
||||
return GetQueryEntitiesByExpression(queryable.Expression, dbContextType);
|
||||
}
|
||||
public static ISet<Type> GetQueryEntitiesByExpression(Expression expression, Type dbContextType)
|
||||
{
|
||||
var trackerManager = (ITrackerManager)ShardingContainer.GetService(typeof(ITrackerManager<>).GetGenericType0(dbContextType));
|
||||
///// <summary>
|
||||
///// 获取本次查询的所有涉及到的对象
|
||||
///// </summary>
|
||||
///// <param name="queryable"></param>
|
||||
///// <param name="dbContextType"></param>
|
||||
///// <returns></returns>
|
||||
//public static ISet<Type> GetQueryEntitiesFilter(IQueryable queryable,Type dbContextType)
|
||||
//{
|
||||
// return GetQueryEntitiesByExpression(queryable.Expression, dbContextType);
|
||||
//}
|
||||
//public static ISet<Type> GetQueryEntitiesByExpression(Expression expression, Type dbContextType)
|
||||
//{
|
||||
// var trackerManager = (ITrackerManager)ShardingContainer.GetService(typeof(ITrackerManager<>).GetGenericType0(dbContextType));
|
||||
|
||||
QueryEntitiesVisitor visitor = new QueryEntitiesVisitor(trackerManager);
|
||||
// QueryEntitiesVisitor visitor = new QueryEntitiesVisitor(trackerManager);
|
||||
|
||||
visitor.Visit(expression);
|
||||
// visitor.Visit(expression);
|
||||
|
||||
return visitor.GetQueryEntities();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取次需要编译的表达式解析信息
|
||||
/// </summary>
|
||||
/// <param name="expression"></param>
|
||||
/// <param name="dbContextType"></param>
|
||||
/// <returns></returns>
|
||||
public static CompileParseResult GetQueryCompileParseResultByExpression(Expression expression, Type dbContextType)
|
||||
{
|
||||
var trackerManager = (ITrackerManager)ShardingContainer.GetService(typeof(ITrackerManager<>).GetGenericType0(dbContextType));
|
||||
// return visitor.GetQueryEntities();
|
||||
//}
|
||||
///// <summary>
|
||||
///// 获取次需要编译的表达式解析信息
|
||||
///// </summary>
|
||||
///// <param name="expression"></param>
|
||||
///// <param name="dbContextType"></param>
|
||||
///// <returns></returns>
|
||||
//public static CompileParseResult GetQueryCompileParseResultByExpression(Expression expression, Type dbContextType)
|
||||
//{
|
||||
// var trackerManager = (ITrackerManager)ShardingContainer.GetService(typeof(ITrackerManager<>).GetGenericType0(dbContextType));
|
||||
|
||||
QueryCompileParseVisitors visitor = new QueryCompileParseVisitors(trackerManager);
|
||||
// QueryCompileParseVisitors visitor = new QueryCompileParseVisitors(trackerManager);
|
||||
|
||||
visitor.Visit(expression);
|
||||
// visitor.Visit(expression);
|
||||
|
||||
return visitor.GetCompileParseResult();
|
||||
}
|
||||
// return visitor.GetCompileParseResult();
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue