This commit is contained in:
parent
60042f2597
commit
947d70f537
|
@ -59,7 +59,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ShardingCoreBenchmark5x", "
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.NoShardingMultiLevel", "samples\Sample.NoShardingMultiLevel\Sample.NoShardingMultiLevel.csproj", "{DCEBAC86-E62B-4B6C-A352-B8C1C2C6F734}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.MultiConfig", "samples\Sample.MultiConfig\Sample.MultiConfig.csproj", "{D839D632-4AE4-4F75-8A2C-49EE029B0787}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sample.MultiConfig", "samples\Sample.MultiConfig\Sample.MultiConfig.csproj", "{D839D632-4AE4-4F75-8A2C-49EE029B0787}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
|
@ -144,9 +144,9 @@ namespace Sample.SqlServer.Controllers
|
|||
|
||||
var sresultx1121222 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "198").MaxAsync(o => o.Age);
|
||||
var unionUserIds = await _defaultTableDbContext.Set<SysUserMod>().Select(o=>new UnionUserId(){UserId = o.Id})
|
||||
.Union(_defaultTableDbContext.Set<SysUserSalary>().Select(o => new UnionUserId() { UserId = o.UserId })).ToListAsync();
|
||||
.Union(_defaultTableDbContext.Set<SysUserSalary>().Select(o => new UnionUserId() { UserId = o.UserId })).UseUnionAllMerge().ToListAsync();
|
||||
var unionUserIdCounts = await _defaultTableDbContext.Set<SysUserMod>().Select(o=>new UnionUserId(){UserId = o.Id})
|
||||
.Union(_defaultTableDbContext.Set<SysUserSalary>().Select(o => new UnionUserId() { UserId = o.UserId })).CountAsync();
|
||||
.Union(_defaultTableDbContext.Set<SysUserSalary>().Select(o => new UnionUserId() { UserId = o.UserId })).UseUnionAllMerge().CountAsync();
|
||||
var hashSet = unionUserIds.Select(o=>o.UserId).ToHashSet();
|
||||
var hashSetCount = hashSet.Count;
|
||||
|
||||
|
@ -176,7 +176,7 @@ namespace Sample.SqlServer.Controllers
|
|||
{
|
||||
Stopwatch sp = new Stopwatch();
|
||||
sp.Start();
|
||||
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserMod>().UnionMerge().OrderBy(o => o.Age).ToShardingPageAsync(p, s);
|
||||
var shardingPageResultAsync = await _defaultTableDbContext.Set<SysUserMod>().UseUnionAllMerge().OrderBy(o => o.Age).ToShardingPageAsync(p, s);
|
||||
sp.Stop();
|
||||
return Ok(new
|
||||
{
|
||||
|
@ -226,8 +226,26 @@ namespace Sample.SqlServer.Controllers
|
|||
[HttpGet]
|
||||
public async Task<IActionResult> Get2a3()
|
||||
{
|
||||
var sql = from o in _defaultTableDbContext.Set<SysUserSalary>()
|
||||
orderby o.Id descending
|
||||
select new
|
||||
{
|
||||
o.Id,
|
||||
o.UserId,
|
||||
o.DateOfMonth,
|
||||
o.SalaryDecimal,
|
||||
o.SalaryFloat
|
||||
};
|
||||
var xx=await sql.ToListAsync();
|
||||
Console.WriteLine("Get2a3-------------");
|
||||
var sysUserMods = await _defaultTableDbContext.Set<SysUserSalary>().Skip(2).Take(2).ToListAsync();
|
||||
var sysUserMods = await _defaultTableDbContext.Set<SysUserSalary>().UseConnectionMode(1).Take(2).Select(o=>new
|
||||
{
|
||||
o.Id,
|
||||
o.UserId,
|
||||
o.DateOfMonth,
|
||||
o.SalaryDecimal,
|
||||
o.SalaryFloat
|
||||
}).OrderByDescending(o=>o.Id).ToListAsync();
|
||||
return Ok(sysUserMods);
|
||||
}
|
||||
[HttpGet]
|
||||
|
|
|
@ -14,7 +14,8 @@ namespace Sample.SqlServer.Domain.Maps
|
|||
{
|
||||
public void Configure(EntityTypeBuilder<SysUserMod> builder)
|
||||
{
|
||||
builder.HasKey(o => o.Id);
|
||||
//builder.HasKey(o => o.Id);
|
||||
builder.HasNoKey();
|
||||
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
|
||||
builder.Property(o => o.Name).HasMaxLength(128);
|
||||
builder.ToTable(nameof(SysUserMod));
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EFCore.BulkExtensions" Version="6.0.0-rc.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="6.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
@ -6,21 +6,17 @@ using Microsoft.Extensions.Hosting;
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Sample.SqlServer.DbContexts;
|
||||
using Sample.SqlServer.Shardings;
|
||||
using Sample.SqlServer.UnionAllMerge;
|
||||
using ShardingCore;
|
||||
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.NotSupportShardingProviders;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
using ShardingCore.TableExists;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Sample.SqlServer
|
||||
{
|
||||
public static class SEX
|
||||
{
|
||||
}
|
||||
public class Startup
|
||||
{
|
||||
public static readonly ILoggerFactory efLogger = LoggerFactory.Create(builder =>
|
||||
|
@ -42,25 +38,14 @@ namespace Sample.SqlServer
|
|||
o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
|
||||
o.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
|
||||
o.AddShardingTableRoute<TestYearShardingVirtualTableRoute>();
|
||||
o.UseInnerDbContextConfigure(builder =>
|
||||
{
|
||||
builder
|
||||
.ReplaceService<IQuerySqlGeneratorFactory,
|
||||
ShardingSqlServerQuerySqlGeneratorFactory<DefaultShardingDbContext>>()
|
||||
.ReplaceService<IQueryCompiler, NotSupportShardingCompiler>();
|
||||
});
|
||||
})
|
||||
.AddConfig(op =>
|
||||
{
|
||||
op.ConfigId = "c1";
|
||||
op.MaxQueryConnectionsLimit = 5;
|
||||
op.UseShardingQuery((conStr, builder) =>
|
||||
op.UseSqlServer(builder =>
|
||||
{
|
||||
builder.UseSqlServer(conStr).UseLoggerFactory(efLogger).ReplaceService<IQuerySqlGeneratorFactory, ShardingSqlServerQuerySqlGeneratorFactory<DefaultShardingDbContext>>();
|
||||
});
|
||||
op.UseShardingTransaction((connection, builder) =>
|
||||
{
|
||||
builder.UseSqlServer(connection).UseLoggerFactory(efLogger).ReplaceService<IQuerySqlGeneratorFactory, ShardingSqlServerQuerySqlGeneratorFactory<DefaultShardingDbContext>>();
|
||||
builder.UseLoggerFactory(efLogger).UseUnionAllMerge<DefaultShardingDbContext>();
|
||||
});
|
||||
op.ReplaceTableEnsureManager(sp => new SqlServerTableEnsureManager<DefaultShardingDbContext>());
|
||||
op.AddDefaultDataSource("A",
|
||||
|
@ -68,7 +53,6 @@ namespace Sample.SqlServer
|
|||
"Data Source = 101.37.117.55;persist security info=True;Initial Catalog=ShardingCoreDBXA;uid=sa;pwd=xjmumixl7610#;Max Pool Size=100;"
|
||||
);
|
||||
}).EnsureConfig();
|
||||
services.TryAddSingleton<INotSupportShardingProvider, UnionSupportShardingProvider>();
|
||||
//services.AddShardingDbContext<DefaultShardingDbContext1>(
|
||||
// (conn, o) =>
|
||||
// o.UseSqlServer(conn).UseLoggerFactory(efLogger)
|
||||
|
@ -133,16 +117,4 @@ namespace Sample.SqlServer
|
|||
app.DbSeed();
|
||||
}
|
||||
}
|
||||
|
||||
public class UnionSupportShardingProvider : INotSupportShardingProvider
|
||||
{
|
||||
public void CheckNotSupportSharding(IQueryCompilerContext queryCompilerContext)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext)
|
||||
{
|
||||
return queryCompilerContext.IsUnion();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||
using ShardingCore.Core.ShardingConfigurations;
|
||||
using ShardingCore.EFCores.OptionsExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace Sample.SqlServer.UnionAllMerge
|
||||
{
|
||||
public static class ShardingCoreSqlServerExtension
|
||||
{
|
||||
public static void UseSqlServer<TShardingDbContext>(this ShardingConfigOptions<TShardingDbContext> option,Action<DbContextOptionsBuilder> builderConfigure=null) where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
option.UseShardingQuery((conStr, builder) =>
|
||||
{
|
||||
builder.UseSqlServer(conStr);
|
||||
builderConfigure?.Invoke(builder);
|
||||
});
|
||||
option.UseShardingTransaction((connection, builder) =>
|
||||
{
|
||||
builder.UseSqlServer(connection);
|
||||
builderConfigure?.Invoke(builder);
|
||||
});
|
||||
}
|
||||
private static UnionAllMergeOptionsExtension CreateOrGetUnionAllMergeExtension(this DbContextOptionsBuilder optionsBuilder)
|
||||
=> optionsBuilder.Options.FindExtension<UnionAllMergeOptionsExtension>() ??
|
||||
new UnionAllMergeOptionsExtension();
|
||||
public static DbContextOptionsBuilder UseUnionAllMerge<TShardingDbContext>(this DbContextOptionsBuilder optionsBuilder) where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
var extension = optionsBuilder.CreateOrGetUnionAllMergeExtension();
|
||||
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension);
|
||||
return optionsBuilder.ReplaceService<IQuerySqlGeneratorFactory,
|
||||
UnionAllMergeSqlServerQuerySqlGeneratorFactory<TShardingDbContext>>()
|
||||
.ReplaceService<IQueryCompiler, UnionAllMergeQueryCompiler>(); ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -8,18 +8,19 @@ using Microsoft.EntityFrameworkCore.Query;
|
|||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using ShardingCore;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace Sample.SqlServer
|
||||
namespace Sample.SqlServer.UnionAllMerge
|
||||
{
|
||||
public class NotSupportShardingCompiler : QueryCompiler
|
||||
public class UnionAllMergeQueryCompiler : QueryCompiler, IUnionAllMergeQueryCompiler
|
||||
{
|
||||
private readonly IQueryContextFactory _queryContextFactory;
|
||||
private readonly IDatabase _database;
|
||||
private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _logger;
|
||||
private readonly IModel _model;
|
||||
|
||||
public NotSupportShardingCompiler(IQueryContextFactory queryContextFactory, ICompiledQueryCache compiledQueryCache, ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator, IDatabase database, IDiagnosticsLogger<DbLoggerCategory.Query> logger, ICurrentDbContext currentContext, IEvaluatableExpressionFilter evaluatableExpressionFilter, IModel model) : base(queryContextFactory, compiledQueryCache, compiledQueryCacheKeyGenerator, database, logger, currentContext, evaluatableExpressionFilter, model)
|
||||
public UnionAllMergeQueryCompiler(IQueryContextFactory queryContextFactory, ICompiledQueryCache compiledQueryCache, ICompiledQueryCacheKeyGenerator compiledQueryCacheKeyGenerator, IDatabase database, IDiagnosticsLogger<DbLoggerCategory.Query> logger, ICurrentDbContext currentContext, IEvaluatableExpressionFilter evaluatableExpressionFilter, IModel model) : base(queryContextFactory, compiledQueryCache, compiledQueryCacheKeyGenerator, database, logger, currentContext, evaluatableExpressionFilter, model)
|
||||
{
|
||||
_queryContextFactory = queryContextFactory;
|
||||
_database = database;
|
||||
|
@ -29,8 +30,8 @@ namespace Sample.SqlServer
|
|||
|
||||
public override TResult Execute<TResult>(Expression query)
|
||||
{
|
||||
var notSupportManager = ShardingContainer.GetService<INotSupportManager>();
|
||||
if (notSupportManager?.Current != null)
|
||||
var notSupportManager = ShardingContainer.GetService<IUnionAllMergeManager>();
|
||||
if (notSupportManager?.Current != null)
|
||||
{
|
||||
return NotSupportShardingExecute<TResult>(query);
|
||||
}
|
||||
|
@ -57,7 +58,7 @@ namespace Sample.SqlServer
|
|||
|
||||
public override TResult ExecuteAsync<TResult>(Expression query, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
var notSupportManager = ShardingContainer.GetService<INotSupportManager>();
|
||||
var notSupportManager = ShardingContainer.GetService<IUnionAllMergeManager>();
|
||||
if (notSupportManager?.Current != null)
|
||||
{
|
||||
var result = NotSupportShardingExecuteAsync<TResult>(query, cancellationToken);
|
|
@ -6,29 +6,29 @@ using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
|
|||
using Microsoft.EntityFrameworkCore.SqlServer.Query.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using ShardingCore;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace Sample.SqlServer
|
||||
namespace Sample.SqlServer.UnionAllMerge
|
||||
{
|
||||
public class ShardingSqlServerQuerySqlGeneratorFactory<TShardingDbContext> : IQuerySqlGeneratorFactory
|
||||
where TShardingDbContext:DbContext,IShardingDbContext
|
||||
public class UnionAllMergeSqlServerQuerySqlGeneratorFactory<TShardingDbContext> : IQuerySqlGeneratorFactory, IUnionAllMergeQuerySqlGeneratorFactory
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
public ShardingSqlServerQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies)
|
||||
public UnionAllMergeSqlServerQuerySqlGeneratorFactory(QuerySqlGeneratorDependencies dependencies)
|
||||
{
|
||||
Dependencies = dependencies;
|
||||
}
|
||||
|
||||
public QuerySqlGeneratorDependencies Dependencies { get; }
|
||||
public QuerySqlGenerator Create() => new ShardingSqlServerQuerySqlGenerator<TShardingDbContext>(Dependencies);
|
||||
public QuerySqlGenerator Create() => new UnionAllMergeSqlServerQuerySqlGenerator<TShardingDbContext>(Dependencies);
|
||||
}
|
||||
|
||||
public class ShardingSqlServerQuerySqlGenerator<TShardingDbContext> : SqlServerQuerySqlGenerator
|
||||
public class UnionAllMergeSqlServerQuerySqlGenerator<TShardingDbContext> : SqlServerQuerySqlGenerator
|
||||
where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
public ShardingSqlServerQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies)
|
||||
public UnionAllMergeSqlServerQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies)
|
||||
: base(dependencies)
|
||||
{
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ namespace Sample.SqlServer
|
|||
|
||||
private Expression OverrideVisitTable(TableExpression tableExpression)
|
||||
{
|
||||
var supportManager = ShardingContainer.GetService<INotSupportManager>();
|
||||
var supportManager = ShardingContainer.GetService<IUnionAllMergeManager>();
|
||||
if (supportManager?.Current != null)
|
||||
{
|
||||
var tableRouteResults = supportManager?.Current.TableRoutesResults.ToArray();
|
||||
if (tableRouteResults.IsNotEmpty() &&
|
||||
tableRouteResults[0].ReplaceTables.Any(o => o.OriginalName == tableExpression.Name))
|
||||
{
|
||||
var tails = tableRouteResults.Select(o=>o.ReplaceTables.FirstOrDefault(r=>r.OriginalName==tableExpression.Name).Tail).ToHashSet();
|
||||
var tails = tableRouteResults.Select(o => o.ReplaceTables.FirstOrDefault(r => r.OriginalName == tableExpression.Name).Tail).ToHashSet();
|
||||
|
||||
var sqlGenerationHelper = typeof(QuerySqlGenerator).GetTypeFieldValue(this, "_sqlGenerationHelper") as ISqlGenerationHelper;
|
||||
var tableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
|
||||
|
@ -70,9 +70,9 @@ namespace Sample.SqlServer
|
|||
newTableName = "(" + string.Join(" union all ", tails.Select(tail => $"select * from {sqlGenerationHelper.DelimitIdentifier($"{tableExpression.Name}{virtualTable.EntityMetadata.TableSeparator}{tail}", tableExpression.Schema)}")) + ")";
|
||||
}
|
||||
|
||||
var relationalCommandBuilder = typeof(QuerySqlGenerator).GetTypeFieldValue(this, "_relationalCommandBuilder") as IRelationalCommandBuilder;
|
||||
relationalCommandBuilder.Append(newTableName).Append(this.AliasSeparator).Append(sqlGenerationHelper.DelimitIdentifier(tableExpression.Alias));
|
||||
return tableExpression;
|
||||
var relationalCommandBuilder = typeof(QuerySqlGenerator).GetTypeFieldValue(this, "_relationalCommandBuilder") as IRelationalCommandBuilder;
|
||||
relationalCommandBuilder.Append(newTableName).Append(this.AliasSeparator).Append(sqlGenerationHelper.DelimitIdentifier(tableExpression.Alias));
|
||||
return tableExpression;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ using ShardingCore.Jobs;
|
|||
using ShardingCore.Jobs.Abstaractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
@ -75,7 +76,7 @@ namespace ShardingCore.Bootstrapers
|
|||
public void Initialize()
|
||||
{
|
||||
var shardingEntityType = _entityType.ClrType;
|
||||
var entityMetadata = new EntityMetadata(shardingEntityType, _virtualTableName,typeof(TShardingDbContext),_entityType.FindPrimaryKey().Properties.Select(o=>o.PropertyInfo).ToList(),_queryFilterExpression);
|
||||
var entityMetadata = new EntityMetadata(shardingEntityType, _virtualTableName,typeof(TShardingDbContext),_entityType.FindPrimaryKey()?.Properties?.Select(o=>o.PropertyInfo)?.ToList()??new List<PropertyInfo>(),_queryFilterExpression);
|
||||
if (!_entityMetadataManager.AddEntityMetadata(entityMetadata))
|
||||
throw new ShardingCoreInvalidOperationException($"repeat add entity metadata {shardingEntityType.FullName}");
|
||||
//设置标签
|
||||
|
|
|
@ -105,7 +105,8 @@ namespace ShardingCore.Bootstrapers
|
|||
foreach (var entity in context.Model.GetEntityTypes())
|
||||
{
|
||||
var entityType = entity.ClrType;
|
||||
_trackerManager.AddDbContextModel(entityType);
|
||||
|
||||
_trackerManager.AddDbContextModel(entityType,entity.FindPrimaryKey()!=null);
|
||||
//entity.GetAnnotation("")
|
||||
if (_entityConfigOptions.HasVirtualDataSourceRoute(entityType) ||
|
||||
_entityConfigOptions.HasVirtualTableRoute(entityType))
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
using ShardingCore.Core.CustomerDatabaseProcessers;
|
||||
|
||||
namespace ShardingCore.Core.NotSupportShardingProviders.Abstractions
|
||||
{
|
||||
public interface INotSupportAccessor
|
||||
{
|
||||
NotSupportContext SqlSupportContext { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using ShardingCore.Core.CustomerDatabaseProcessers;
|
||||
using ShardingCore.Core.CustomerDatabaseSqlSupports;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Core.NotSupportShardingProviders.Abstractions
|
||||
{
|
||||
public interface INotSupportManager
|
||||
{
|
||||
NotSupportContext Current { get; }
|
||||
/// <summary>
|
||||
/// 创建scope
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
NotSupportScope CreateScope(IEnumerable<TableRouteResult> tableRouteResults);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.NotSupportShardingProviders
|
||||
{
|
||||
public class DefaultNotSupportShardingProvider: INotSupportShardingProvider
|
||||
{
|
||||
public void CheckNotSupportSharding(IQueryCompilerContext queryCompilerContext)
|
||||
{
|
||||
if (IsNotSupportSharding(queryCompilerContext))
|
||||
throw new ShardingCoreInvalidOperationException(
|
||||
$"not support sharding query :[{queryCompilerContext.GetQueryExpression().ShardingPrint()}]");
|
||||
}
|
||||
|
||||
public bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext)
|
||||
{
|
||||
return queryCompilerContext.IsUnion();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.NotSupportShardingProviders
|
||||
{
|
||||
public interface INotSupportShardingProvider
|
||||
{
|
||||
void CheckNotSupportSharding(IQueryCompilerContext queryCompilerContext);
|
||||
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
|
||||
bool IsNotSupportSharding(IQueryCompilerContext queryCompilerContext);
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.CustomerDatabaseProcessers;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.CustomerDatabaseSqlSupports
|
||||
{
|
||||
public class NotSupportAccessor: INotSupportAccessor
|
||||
{
|
||||
private static AsyncLocal<NotSupportContext> _sqlSupportContext = new AsyncLocal<NotSupportContext>();
|
||||
|
||||
|
||||
public NotSupportContext SqlSupportContext
|
||||
{
|
||||
get => _sqlSupportContext.Value;
|
||||
set => _sqlSupportContext.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Core.CustomerDatabaseProcessers
|
||||
{
|
||||
public class NotSupportContext
|
||||
{
|
||||
public NotSupportContext(IEnumerable<TableRouteResult> tableRoutesResults)
|
||||
{
|
||||
TableRoutesResults = tableRoutesResults;
|
||||
}
|
||||
|
||||
public IEnumerable<TableRouteResult> TableRoutesResults { get; }
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using ShardingCore.Core.CustomerDatabaseProcessers;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Core.CustomerDatabaseSqlSupports
|
||||
{
|
||||
public class NotSupportManager: INotSupportManager
|
||||
{
|
||||
private readonly INotSupportAccessor _notSupportAccessor;
|
||||
public NotSupportContext Current => _notSupportAccessor.SqlSupportContext;
|
||||
|
||||
public NotSupportManager(INotSupportAccessor notSupportAccessor)
|
||||
{
|
||||
_notSupportAccessor = notSupportAccessor;
|
||||
}
|
||||
public NotSupportScope CreateScope(IEnumerable<TableRouteResult> tableRouteResults)
|
||||
{
|
||||
var scope = new NotSupportScope(_notSupportAccessor);
|
||||
_notSupportAccessor.SqlSupportContext = new NotSupportContext(tableRouteResults);
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.CustomerDatabaseSqlSupports
|
||||
{
|
||||
public class NotSupportScope:IDisposable
|
||||
{
|
||||
public INotSupportAccessor NotSupportAccessor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="notSupportAccessor"></param>
|
||||
public NotSupportScope(INotSupportAccessor notSupportAccessor)
|
||||
{
|
||||
NotSupportAccessor = notSupportAccessor;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
NotSupportAccessor.SqlSupportContext = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -180,7 +180,7 @@ namespace ShardingCore.Core.ShardingConfigurations
|
|||
ConnectionConfigure = transactionConfigure ?? throw new ArgumentNullException(nameof(transactionConfigure));
|
||||
}
|
||||
/// <summary>
|
||||
/// 仅内部DbContext配置的方法
|
||||
/// 仅内部真实DbContext配置的方法
|
||||
/// </summary>
|
||||
/// <param name="innerDbContextConfigure"></param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace ShardingCore.Core.TrackerManagers
|
|||
*/
|
||||
public interface ITrackerManager
|
||||
{
|
||||
bool AddDbContextModel(Type entityType);
|
||||
bool AddDbContextModel(Type entityType,bool hasKey);
|
||||
bool EntityUseTrack(Type entityType);
|
||||
bool IsDbContextModel(Type entityType);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
@ -16,21 +17,25 @@ namespace ShardingCore.Core.TrackerManagers
|
|||
*/
|
||||
public class TrackerManager<TShardingDbContext>: ITrackerManager<TShardingDbContext> where TShardingDbContext : DbContext, IShardingDbContext
|
||||
{
|
||||
private readonly ISet<Type> _dbContextModels = new HashSet<Type>();
|
||||
private readonly ConcurrentDictionary<Type,bool> _dbContextModels = new ();
|
||||
|
||||
public bool AddDbContextModel(Type entityType)
|
||||
public bool AddDbContextModel(Type entityType, bool hasKey)
|
||||
{
|
||||
return _dbContextModels.Add(entityType);
|
||||
return _dbContextModels.TryAdd(entityType, hasKey);
|
||||
}
|
||||
|
||||
public bool EntityUseTrack(Type entityType)
|
||||
{
|
||||
return _dbContextModels.Contains(entityType);
|
||||
if (!_dbContextModels.TryGetValue(entityType, out var hasKey))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return hasKey;
|
||||
}
|
||||
|
||||
public bool IsDbContextModel(Type entityType)
|
||||
{
|
||||
return _dbContextModels.Contains(entityType);
|
||||
return _dbContextModels.ContainsKey(entityType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
namespace ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions
|
||||
{
|
||||
public interface IUnionAllMergeAccessor
|
||||
{
|
||||
UnionAllMergeContext SqlSupportContext { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions
|
||||
{
|
||||
public interface IUnionAllMergeManager
|
||||
{
|
||||
UnionAllMergeContext Current { get; }
|
||||
/// <summary>
|
||||
/// 创建scope
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
UnionAllMergeScope CreateScope(IEnumerable<TableRouteResult> tableRouteResults);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System.Threading;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.UnionAllMergeShardingProviders
|
||||
{
|
||||
public class UnionAllMergeAccessor: IUnionAllMergeAccessor
|
||||
{
|
||||
private static AsyncLocal<UnionAllMergeContext> _sqlSupportContext = new AsyncLocal<UnionAllMergeContext>();
|
||||
|
||||
|
||||
public UnionAllMergeContext SqlSupportContext
|
||||
{
|
||||
get => _sqlSupportContext.Value;
|
||||
set => _sqlSupportContext.Value = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Core.UnionAllMergeShardingProviders
|
||||
{
|
||||
public class UnionAllMergeContext
|
||||
{
|
||||
public UnionAllMergeContext(IEnumerable<TableRouteResult> tableRoutesResults)
|
||||
{
|
||||
TableRoutesResults = tableRoutesResults;
|
||||
}
|
||||
|
||||
public IEnumerable<TableRouteResult> TableRoutesResults { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
|
||||
namespace ShardingCore.Core.UnionAllMergeShardingProviders
|
||||
{
|
||||
public class UnionAllMergeManager: IUnionAllMergeManager
|
||||
{
|
||||
private readonly IUnionAllMergeAccessor _unionAllMergeAccessor;
|
||||
public UnionAllMergeContext Current => _unionAllMergeAccessor.SqlSupportContext;
|
||||
|
||||
public UnionAllMergeManager(IUnionAllMergeAccessor unionAllMergeAccessor)
|
||||
{
|
||||
_unionAllMergeAccessor = unionAllMergeAccessor;
|
||||
}
|
||||
public UnionAllMergeScope CreateScope(IEnumerable<TableRouteResult> tableRouteResults)
|
||||
{
|
||||
var scope = new UnionAllMergeScope(_unionAllMergeAccessor);
|
||||
_unionAllMergeAccessor.SqlSupportContext = new UnionAllMergeContext(tableRouteResults);
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
|
||||
namespace ShardingCore.Core.UnionAllMergeShardingProviders
|
||||
{
|
||||
public class UnionAllMergeScope:IDisposable
|
||||
{
|
||||
public IUnionAllMergeAccessor UnionAllMergeAccessor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
/// <param name="unionAllMergeAccessor"></param>
|
||||
public UnionAllMergeScope(IUnionAllMergeAccessor unionAllMergeAccessor)
|
||||
{
|
||||
UnionAllMergeAccessor = unionAllMergeAccessor;
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
UnionAllMergeAccessor.SqlSupportContext = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,12 +29,14 @@ using ShardingCore.Sharding.Abstractions;
|
|||
using ShardingCore.Sharding.ShardingQueryExecutors;
|
||||
using ShardingCore.TableCreator;
|
||||
using System;
|
||||
using ShardingCore.Core.CustomerDatabaseSqlSupports;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using ShardingCore.Core.QueryTrackers;
|
||||
using ShardingCore.Core.ShardingConfigurations;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualDataSources.Abstractions;
|
||||
using ShardingCore.DynamicDataSources;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.ParallelTables;
|
||||
using ShardingCore.Sharding.ReadWriteConfigurations;
|
||||
using ShardingCore.Sharding.ReadWriteConfigurations.Abstractions;
|
||||
|
@ -125,6 +127,11 @@ namespace ShardingCore
|
|||
services.TryAddSingleton<IShardingQueryExecutor, DefaultShardingQueryExecutor>();
|
||||
services.TryAddSingleton<IReadWriteConnectorFactory, ReadWriteConnectorFactory>();
|
||||
|
||||
//
|
||||
services.TryAddSingleton<IQueryableParseEngine, QueryableParseEngine>();
|
||||
services.TryAddSingleton<IQueryableRewriteEngine, QueryableRewriteEngine>();
|
||||
services.TryAddSingleton<IQueryableOptimizeEngine, QueryableOptimizeEngine>();
|
||||
|
||||
//route manage
|
||||
services.TryAddSingleton<IShardingRouteManager, ShardingRouteManager>();
|
||||
services.TryAddSingleton<IShardingRouteAccessor, ShardingRouteAccessor>();
|
||||
|
@ -133,14 +140,15 @@ namespace ShardingCore
|
|||
services.TryAddSingleton<IShardingPageManager, ShardingPageManager>();
|
||||
services.TryAddSingleton<IShardingPageAccessor, ShardingPageAccessor>();
|
||||
services.TryAddSingleton<IShardingBootstrapper, ShardingBootstrapper>();
|
||||
services.TryAddSingleton<INotSupportManager, NotSupportManager>();
|
||||
services.TryAddSingleton<INotSupportAccessor, NotSupportAccessor>();
|
||||
services.TryAddSingleton<IUnionAllMergeManager, UnionAllMergeManager>();
|
||||
services.TryAddSingleton<IUnionAllMergeAccessor, UnionAllMergeAccessor>();
|
||||
services.TryAddSingleton<IQueryTracker, QueryTracker>();
|
||||
services.TryAddSingleton<IShardingTrackQueryExecutor, DefaultShardingTrackQueryExecutor>();
|
||||
services.TryAddSingleton<INativeTrackQueryExecutor, NativeTrackQueryExecutor>();
|
||||
//读写分离手动指定
|
||||
services.TryAddSingleton<IShardingReadWriteManager, ShardingReadWriteManager>();
|
||||
|
||||
|
||||
services.TryAddShardingJob();
|
||||
return services;
|
||||
}
|
||||
|
@ -174,7 +182,7 @@ namespace ShardingCore
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
//public static IServiceCollection AddSingleShardingDbContext<TShardingDbContext>(this IServiceCollection services, Action<ShardingConfigOptions> configure,
|
||||
// Action<string, DbContextOptionsBuilder> optionsAction = null,
|
||||
// ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ShardingCore.EFCores.OptionsExtensions
|
||||
{
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:
|
||||
* @Date: 2021/10/17 20:27:12
|
||||
* @Ver: 1.0
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
|
||||
#if EFCORE6
|
||||
public class UnionAllMergeOptionsExtension : IDbContextOptionsExtension
|
||||
{
|
||||
public void ApplyServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
public void Validate(IDbContextOptions options)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public DbContextOptionsExtensionInfo Info => new UnionAllMergeDbContextOptionsExtensionInfo(this);
|
||||
|
||||
private class UnionAllMergeDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo
|
||||
{
|
||||
public UnionAllMergeDbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension)
|
||||
{
|
||||
}
|
||||
|
||||
public override int GetServiceProviderHashCode() => 0;
|
||||
|
||||
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other) => true;
|
||||
|
||||
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
|
||||
{
|
||||
}
|
||||
|
||||
public override bool IsDatabaseProvider => false;
|
||||
public override string LogFragment => "UnionAllMergeOptionsExtension";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if EFCORE3 || EFCORE5
|
||||
|
||||
public class UnionAllMergeOptionsExtension: IDbContextOptionsExtension
|
||||
{
|
||||
public void ApplyServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
public void Validate(IDbContextOptions options)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public DbContextOptionsExtensionInfo Info => new UnionAllMergeDbContextOptionsExtensionInfo(this);
|
||||
|
||||
private class UnionAllMergeDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo
|
||||
{
|
||||
public UnionAllMergeDbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension) { }
|
||||
|
||||
public override long GetServiceProviderHashCode() => 0;
|
||||
|
||||
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) { }
|
||||
|
||||
public override bool IsDatabaseProvider => false;
|
||||
public override string LogFragment => "UnionAllMergeOptionsExtension";
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#if EFCORE2
|
||||
|
||||
public class UnionAllMergeOptionsExtension: IDbContextOptionsExtension
|
||||
{
|
||||
public bool ApplyServices(IServiceCollection services)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public long GetServiceProviderHashCode() => 0;
|
||||
|
||||
public void Validate(IDbContextOptions options)
|
||||
{
|
||||
}
|
||||
|
||||
public string LogFragment => "UnionAllMergeOptionsExtension";
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -273,13 +273,17 @@ namespace ShardingCore.Extensions
|
|||
|
||||
public static IEnumerable<object> GetPrimaryKeyValues<TEntity>(TEntity entity,IKey primaryKey) where TEntity : class
|
||||
{
|
||||
return primaryKey.Properties.Select(o => entity.GetPropertyValue(o.Name));
|
||||
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.FindEntityType(entity.GetType()).FindPrimaryKey();
|
||||
if (entityPrimaryKey == null)
|
||||
{
|
||||
return entity;
|
||||
}
|
||||
var primaryKeyValue = GetPrimaryKeyValues(entity, entityPrimaryKey).ToArray();
|
||||
if (primaryKeyValue.IsEmpty())
|
||||
return null;
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Exceptions;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
{
|
||||
|
@ -59,6 +60,10 @@ namespace ShardingCore.Extensions
|
|||
//propertyAccess = Expression.MakeMemberAccess(parameter, property);
|
||||
for (int i = 1; i < childProperties.Length; i++)
|
||||
{
|
||||
if (property == null)
|
||||
{
|
||||
throw new ShardingCoreException($"property:[{propertyExpression}] not in type:[{entityType}]");
|
||||
}
|
||||
property = property.PropertyType.GetProperty(childProperties[i]);
|
||||
//propertyAccess = Expression.MakeMemberAccess(propertyAccess, property);
|
||||
}
|
||||
|
@ -69,6 +74,11 @@ namespace ShardingCore.Extensions
|
|||
//propertyAccess = Expression.MakeMemberAccess(parameter, property);
|
||||
}
|
||||
|
||||
if (property == null)
|
||||
{
|
||||
throw new ShardingCoreException($"property:[{propertyExpression}] not in type:[{entityType}]");
|
||||
}
|
||||
|
||||
return property.GetValue(obj);
|
||||
//var lambda = Expression.Lambda(propertyAccess, parameter);
|
||||
//Delegate fn = lambda.Compile();
|
||||
|
|
|
@ -3,9 +3,11 @@ using System.Collections.Generic;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.EntityMetadatas;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Visitors;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
|
@ -21,11 +23,15 @@ namespace ShardingCore.Extensions
|
|||
/// </summary>
|
||||
internal static class IShardingQueryableExtension
|
||||
{
|
||||
private static readonly MethodInfo QueryableSkipMethod = typeof(Queryable).GetMethod(nameof(Queryable.Skip));
|
||||
private static readonly MethodInfo QueryableTakeMethod = typeof(Queryable).GetMethods().First(
|
||||
m => m.Name == nameof(Queryable.Take)
|
||||
&& m.GetParameters().Length == 2 && m.GetParameters()[1].ParameterType == typeof(int));
|
||||
internal static ExtraEntry GetExtraEntry<T>(this IQueryable<T> source)
|
||||
{
|
||||
var extraVisitor = new QueryableExtraDiscoverVisitor();
|
||||
extraVisitor.Visit(source.Expression);
|
||||
var extraEntry = new ExtraEntry(extraVisitor.GetSkip(), extraVisitor.GetTake(), extraVisitor.GetOrders(),extraVisitor.GetSelectContext(),extraVisitor.GetGroupByContext());
|
||||
var extraEntry = new ExtraEntry(extraVisitor.GetPaginationContext().Skip, extraVisitor.GetPaginationContext().Take, extraVisitor.GetOrderByContext().PropertyOrders,extraVisitor.GetSelectContext(),extraVisitor.GetGroupByContext());
|
||||
extraEntry.ProcessGroupBySelectProperties();
|
||||
return extraEntry;
|
||||
}
|
||||
|
@ -35,39 +41,57 @@ namespace ShardingCore.Extensions
|
|||
/// <typeparam name="T">实体类型</typeparam>
|
||||
/// <param name="source">数据源</param>
|
||||
/// <returns></returns>
|
||||
internal static IQueryable<T> RemoveSkip<T>(this IQueryable<T> source)
|
||||
internal static IQueryable RemoveSkip(this IQueryable source)
|
||||
{
|
||||
var expression = new RemoveSkipVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>)source.Provider.CreateQuery(expression);
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
|
||||
internal static IQueryable ReSkip(this IQueryable source, int skip)
|
||||
{
|
||||
MethodInfo method = QueryableSkipMethod.MakeGenericMethod(source.ElementType);
|
||||
var expression = Expression.Call(
|
||||
method,
|
||||
source.Expression,
|
||||
Expression.Constant(skip));
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
|
||||
internal static IQueryable ReTake(this IQueryable source, int take)
|
||||
{
|
||||
MethodInfo method = QueryableTakeMethod.MakeGenericMethod(source.ElementType);
|
||||
var expression = Expression.Call(
|
||||
method,
|
||||
source.Expression,
|
||||
Expression.Constant(take));
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除Take表达式
|
||||
/// </summary>
|
||||
/// <typeparam name="T">实体类型</typeparam>
|
||||
/// <param name="source">数据源</param>
|
||||
/// <returns></returns>
|
||||
internal static IQueryable<T> RemoveTake<T>(this IQueryable<T> source)
|
||||
internal static IQueryable RemoveTake(this IQueryable source)
|
||||
{
|
||||
var expression = new RemoveTakeVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>) source.Provider.CreateQuery(expression);
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal static IQueryable<T> RemoveOrderBy<T>(this IQueryable<T> source)
|
||||
internal static IQueryable RemoveOrderBy(this IQueryable source)
|
||||
{
|
||||
var expression = new RemoveOrderByVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>)source.Provider.CreateQuery(expression);
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal static IQueryable<T> RemoveOrderByDescending<T>(this IQueryable<T> source)
|
||||
internal static IQueryable RemoveOrderByDescending(this IQueryable source)
|
||||
{
|
||||
var expression = new RemoveOrderByDescendingVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>)source.Provider.CreateQuery(expression);
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
internal static IQueryable<T> RemoveAnyOrderBy<T>(this IQueryable<T> source)
|
||||
internal static IQueryable RemoveAnyOrderBy(this IQueryable source)
|
||||
{
|
||||
var expression = new RemoveAnyOrderVisitor().Visit(source.Expression);
|
||||
return (IQueryable<T>) source.Provider.CreateQuery(expression);
|
||||
return source.Provider.CreateQuery(expression);
|
||||
}
|
||||
|
||||
internal static bool? GetIsNoTracking(this IQueryable source)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Extensions.InternalExtensions
|
||||
{
|
||||
internal static class InternalObjectExtension
|
||||
{
|
||||
public static T As<T>(this object obj) where T : class
|
||||
{
|
||||
return (T)obj;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ namespace ShardingCore.Extensions
|
|||
var property = obj.GetType().GetProperty(propertyName, _bindingFlags);
|
||||
if (property != null)
|
||||
{
|
||||
return obj.GetType().GetProperty(propertyName, _bindingFlags)?.GetValue(obj);
|
||||
return property.GetValue(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -65,7 +65,7 @@ namespace ShardingCore.Extensions
|
|||
var property=type.GetProperty(propertyName, _bindingFlags);
|
||||
if (property != null)
|
||||
{
|
||||
return type.GetProperty(propertyName, _bindingFlags)?.GetValue(obj);
|
||||
return property.GetValue(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -3,6 +3,12 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||
using ShardingCore.EFCores.OptionsExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
|
||||
namespace ShardingCore.Extensions
|
||||
|
@ -13,5 +19,11 @@ namespace ShardingCore.Extensions
|
|||
{
|
||||
return shardingDbContext.GetVirtualDataSource().UseReadWriteSeparation;
|
||||
}
|
||||
|
||||
public static bool SupportUnionAllMerge(this IShardingDbContext shardingDbContext)
|
||||
{
|
||||
var dbContext = (DbContext)shardingDbContext;
|
||||
return dbContext.GetService<IDbContextServices>().ContextOptions.FindExtension<UnionAllMergeOptionsExtension>() is not null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
|
|||
{
|
||||
|
||||
internal static readonly MethodInfo NotSupportMethodInfo
|
||||
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(UnionMerge)).Single();
|
||||
= typeof(EntityFrameworkShardingQueryableExtension).GetTypeInfo().GetDeclaredMethods(nameof(UseUnionAllMerge)).Single();
|
||||
internal static readonly MethodInfo AsRouteMethodInfo
|
||||
= typeof(EntityFrameworkShardingQueryableExtension)
|
||||
.GetTypeInfo()
|
||||
|
@ -57,7 +57,7 @@ namespace ShardingCore.Extensions.ShardingQueryableExtensions
|
|||
/// <param name="source"></param>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <returns></returns>
|
||||
public static IQueryable<TEntity> UnionMerge<TEntity>(this IQueryable<TEntity> source)
|
||||
public static IQueryable<TEntity> UseUnionAllMerge<TEntity>(this IQueryable<TEntity> source)
|
||||
{
|
||||
Check.NotNull(source, nameof(source));
|
||||
return
|
||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.Internals;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
|
@ -21,16 +22,16 @@ namespace ShardingCore.Extensions
|
|||
{
|
||||
#region Private expression tree helpers
|
||||
|
||||
private static LambdaExpression GenerateSelector<TEntity>(String propertyName, out Type resultType)
|
||||
private static LambdaExpression GenerateSelector(Type entityType,String propertyName, out Type resultType)
|
||||
{
|
||||
PropertyInfo property;
|
||||
Expression propertyAccess;
|
||||
var parameter = Expression.Parameter(typeof(TEntity), "o");
|
||||
var parameter = Expression.Parameter(entityType, "o");
|
||||
|
||||
if (propertyName.Contains('.'))
|
||||
{
|
||||
String[] childProperties = propertyName.Split('.');
|
||||
property = typeof(TEntity).GetProperty(childProperties[0]);
|
||||
property = entityType.GetProperty(childProperties[0]);
|
||||
propertyAccess = Expression.MakeMemberAccess(parameter, property);
|
||||
for (int i = 1; i < childProperties.Length; i++)
|
||||
{
|
||||
|
@ -40,7 +41,7 @@ namespace ShardingCore.Extensions
|
|||
}
|
||||
else
|
||||
{
|
||||
property = typeof(TEntity).GetProperty(propertyName);
|
||||
property = entityType.GetProperty(propertyName);
|
||||
propertyAccess = Expression.MakeMemberAccess(parameter, property);
|
||||
}
|
||||
|
||||
|
@ -49,11 +50,11 @@ namespace ShardingCore.Extensions
|
|||
return Expression.Lambda(propertyAccess, parameter);
|
||||
}
|
||||
|
||||
private static MethodCallExpression GenerateMethodCall<TEntity>(IQueryable<TEntity> source, string methodName, String fieldName,IShardingComparer shardingComparer=null)
|
||||
private static MethodCallExpression GenerateMethodCall(IQueryable source, string methodName, String fieldName,IShardingComparer shardingComparer=null)
|
||||
{
|
||||
Type type = typeof(TEntity);
|
||||
Type type = source.ElementType;
|
||||
Type selectorResultType;
|
||||
LambdaExpression selector = GenerateSelector<TEntity>(fieldName, out selectorResultType);
|
||||
LambdaExpression selector = GenerateSelector(type,fieldName, out selectorResultType);
|
||||
MethodCallExpression resultExp;
|
||||
if (shardingComparer == null)
|
||||
{
|
||||
|
@ -73,28 +74,28 @@ namespace ShardingCore.Extensions
|
|||
|
||||
#endregion
|
||||
|
||||
internal static IOrderedQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
internal static IOrderedQueryable OrderBy(this IQueryable source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.OrderBy), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
|
||||
MethodCallExpression resultExp = GenerateMethodCall(source, nameof(Queryable.OrderBy), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery(resultExp) as IOrderedQueryable;
|
||||
}
|
||||
|
||||
internal static IOrderedQueryable<TEntity> OrderByDescending<TEntity>(this IQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
internal static IOrderedQueryable OrderByDescending(this IQueryable source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.OrderByDescending), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
|
||||
MethodCallExpression resultExp = GenerateMethodCall(source, nameof(Queryable.OrderByDescending), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery(resultExp) as IOrderedQueryable;
|
||||
}
|
||||
|
||||
internal static IOrderedQueryable<TEntity> ThenBy<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
internal static IOrderedQueryable ThenBy(this IOrderedQueryable source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.ThenBy), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
|
||||
MethodCallExpression resultExp = GenerateMethodCall(source, nameof(Queryable.ThenBy), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery(resultExp) as IOrderedQueryable;
|
||||
}
|
||||
|
||||
internal static IOrderedQueryable<TEntity> ThenByDescending<TEntity>(this IOrderedQueryable<TEntity> source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
internal static IOrderedQueryable ThenByDescending(this IOrderedQueryable source, string fieldName, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
MethodCallExpression resultExp = GenerateMethodCall<TEntity>(source, nameof(Queryable.ThenByDescending), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery<TEntity>(resultExp) as IOrderedQueryable<TEntity>;
|
||||
MethodCallExpression resultExp = GenerateMethodCall(source, nameof(Queryable.ThenByDescending), fieldName, shardingComparer);
|
||||
return source.Provider.CreateQuery(resultExp) as IOrderedQueryable;
|
||||
}
|
||||
/// <summary>
|
||||
/// 排序利用表达式
|
||||
|
@ -102,12 +103,11 @@ namespace ShardingCore.Extensions
|
|||
/// <param name="source"></param>
|
||||
/// <param name="sortExpression">"child.name asc,child.age desc"</param>
|
||||
/// <param name="shardingComparer"></param>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
/// <returns></returns>
|
||||
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression, IShardingComparer shardingComparer = null)
|
||||
internal static IOrderedQueryable OrderWithExpression(this IQueryable source, string sortExpression, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
String[] orderFields = sortExpression.Split(',');
|
||||
IOrderedQueryable<TEntity> result = null;
|
||||
IOrderedQueryable result = null;
|
||||
for (int currentFieldIndex = 0; currentFieldIndex < orderFields.Length; currentFieldIndex++)
|
||||
{
|
||||
String[] expressionPart = orderFields[currentFieldIndex].Trim().Split(' ');
|
||||
|
@ -125,9 +125,17 @@ namespace ShardingCore.Extensions
|
|||
|
||||
return result;
|
||||
}
|
||||
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
return OrderWithExpression((IQueryable)source,sortExpression,shardingComparer).As<IOrderedQueryable<TEntity>>();
|
||||
}
|
||||
internal static IOrderedQueryable<TEntity> OrderWithExpression<TEntity>(this IQueryable<TEntity> source, IEnumerable<PropertyOrder> propertyOrders, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
IOrderedQueryable<TEntity> result = null;
|
||||
return OrderWithExpression(source.As<IQueryable>(), propertyOrders,shardingComparer).As<IOrderedQueryable<TEntity>>();
|
||||
}
|
||||
internal static IOrderedQueryable OrderWithExpression(this IQueryable source, IEnumerable<PropertyOrder> propertyOrders, IShardingComparer shardingComparer = null)
|
||||
{
|
||||
IOrderedQueryable result = null;
|
||||
var currentIndex = 0;
|
||||
foreach (var propertyOrder in propertyOrders)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.Abstractions
|
||||
{
|
||||
public interface IUnionAllMergeQueryCompiler
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.Abstractions
|
||||
{
|
||||
public interface IUnionAllMergeQuerySqlGeneratorFactory
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ShardingCore.Core;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
|
@ -18,5 +18,7 @@ namespace ShardingCore.Sharding.MergeContexts
|
|||
ConnectionModeEnum GetConnectionMode();
|
||||
bool IsSequenceQuery();
|
||||
bool SameWithTailComparer();
|
||||
IComparer<string> ShardingTailComparer();
|
||||
bool CanTrip();
|
||||
}
|
||||
}
|
|
@ -12,13 +12,11 @@ namespace ShardingCore.Sharding.MergeContexts
|
|||
*/
|
||||
public interface IParseResult
|
||||
{
|
||||
int? GetSkip();
|
||||
int? GetTake();
|
||||
|
||||
PropertyOrder[] GetOrders();
|
||||
PaginationContext GetPaginationContext();
|
||||
OrderByContext GetOrderByContext();
|
||||
|
||||
SelectContext GetSelectContext();
|
||||
|
||||
GroupByContext GetGroupByConteext();
|
||||
GroupByContext GetGroupByContext();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public interface IQueryableOptimizeEngine
|
||||
{
|
||||
IOptimizeResult Optimize(IMergeQueryCompilerContext mergeQueryCompilerContext, IParseResult parseResult,
|
||||
IQueryable rewriteQueryable);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
internal interface IStreamMergeParameter
|
||||
{
|
||||
IParseResult GetParseResult();
|
||||
|
||||
IRewriteResult GetRewriteResult();
|
||||
IOptimizeResult GetOptimizeResult();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public sealed class OptimizeResult: IOptimizeResult
|
||||
{
|
||||
private readonly int _maxQueryConnectionsLimit;
|
||||
private readonly ConnectionModeEnum _connectionMode;
|
||||
private readonly bool _isSequenceQuery;
|
||||
private readonly bool _sameWithTailComparer;
|
||||
private readonly IComparer<string> _shardingTailComparer;
|
||||
private readonly bool _canTrip;
|
||||
|
||||
public OptimizeResult(int maxQueryConnectionsLimit, ConnectionModeEnum connectionMode,bool isSequenceQuery,bool sameWithTailComparer,IComparer<string> shardingTailComparer,bool canTrip)
|
||||
{
|
||||
_maxQueryConnectionsLimit = maxQueryConnectionsLimit;
|
||||
_connectionMode = connectionMode;
|
||||
_isSequenceQuery = isSequenceQuery;
|
||||
_sameWithTailComparer = sameWithTailComparer;
|
||||
_shardingTailComparer = shardingTailComparer;
|
||||
_canTrip = canTrip;
|
||||
}
|
||||
public int GetMaxQueryConnectionsLimit()
|
||||
{
|
||||
return _maxQueryConnectionsLimit;
|
||||
}
|
||||
|
||||
public ConnectionModeEnum GetConnectionMode()
|
||||
{
|
||||
return _connectionMode;
|
||||
}
|
||||
|
||||
public bool IsSequenceQuery()
|
||||
{
|
||||
return _isSequenceQuery;
|
||||
}
|
||||
|
||||
public bool SameWithTailComparer()
|
||||
{
|
||||
return _sameWithTailComparer;
|
||||
}
|
||||
|
||||
public IComparer<string> ShardingTailComparer()
|
||||
{
|
||||
return _shardingTailComparer;
|
||||
}
|
||||
public bool CanTrip()
|
||||
{
|
||||
return _canTrip;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public sealed class OrderByContext
|
||||
{
|
||||
public LinkedList<PropertyOrder> PropertyOrders { get; } = new LinkedList<PropertyOrder>();
|
||||
public string GetOrderExpression()
|
||||
{
|
||||
return string.Join(",", PropertyOrders);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public sealed class PaginationContext
|
||||
{
|
||||
public int? Skip { get; set; }
|
||||
public int? Take { get; set; }
|
||||
|
||||
public bool HasSkip()
|
||||
{
|
||||
return Skip.HasValue;
|
||||
}
|
||||
public bool HasTake()
|
||||
{
|
||||
return Take.HasValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.Internal.Visitors.Selects;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public sealed class ParseResult:IParseResult
|
||||
{
|
||||
private readonly PaginationContext _paginationContext;
|
||||
private readonly OrderByContext _orderByContext;
|
||||
private readonly SelectContext _selectContext;
|
||||
private readonly GroupByContext _groupByContext;
|
||||
|
||||
public ParseResult(PaginationContext paginationContext, OrderByContext orderByContext, SelectContext selectContext,GroupByContext groupByContext)
|
||||
{
|
||||
_paginationContext = paginationContext;
|
||||
_orderByContext = orderByContext;
|
||||
_selectContext = selectContext;
|
||||
_groupByContext = groupByContext;
|
||||
}
|
||||
|
||||
public PaginationContext GetPaginationContext()
|
||||
{
|
||||
return _paginationContext;
|
||||
}
|
||||
|
||||
public OrderByContext GetOrderByContext()
|
||||
{
|
||||
return _orderByContext;
|
||||
}
|
||||
|
||||
|
||||
public SelectContext GetSelectContext()
|
||||
{
|
||||
return _selectContext;
|
||||
}
|
||||
|
||||
public GroupByContext GetGroupByContext()
|
||||
{
|
||||
return _groupByContext;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
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.Internal.Visitors.Selects;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.Sharding.EntityQueryConfigurations;
|
||||
using ShardingCore.Sharding.ShardingExecutors;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public sealed class QueryableOptimizeEngine: IQueryableOptimizeEngine
|
||||
{
|
||||
public IOptimizeResult Optimize(IMergeQueryCompilerContext mergeQueryCompilerContext, IParseResult parseResult,
|
||||
IQueryable rewriteQueryable)
|
||||
{
|
||||
var shardingDbContext = mergeQueryCompilerContext.GetShardingDbContext();
|
||||
var maxParallelExecuteCount = shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit;
|
||||
var connectionMode = shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode;
|
||||
IComparer<string> shardingTailComparer = Comparer<string>.Default;
|
||||
bool sameWithTailComparer = true;
|
||||
bool sequenceQuery = false;
|
||||
if (mergeQueryCompilerContext.IsSingleShardingEntityQuery() && mergeQueryCompilerContext.IsCrossTable() && !mergeQueryCompilerContext.UseUnionAllMerge())
|
||||
{
|
||||
var singleShardingEntityType = mergeQueryCompilerContext.GetSingleShardingEntityType();
|
||||
var virtualTableManager = ShardingContainer.GetVirtualTableManager(mergeQueryCompilerContext.GetShardingDbContextType());
|
||||
var virtualTable = virtualTableManager.GetVirtualTable(singleShardingEntityType);
|
||||
if (virtualTable.EnableEntityQuery)
|
||||
{
|
||||
if (virtualTable.EntityQueryMetadata.DefaultTailComparer != null)
|
||||
{
|
||||
shardingTailComparer = virtualTable.EntityQueryMetadata.DefaultTailComparer;
|
||||
}
|
||||
sameWithTailComparer = virtualTable.EntityQueryMetadata.DefaultTailComparerNeedReverse;
|
||||
string methodName = mergeQueryCompilerContext.IsEnumerableQuery() ?
|
||||
EntityQueryMetadata.QUERY_ENUMERATOR :
|
||||
((MethodCallExpression)mergeQueryCompilerContext.GetQueryExpression()).Method.Name;
|
||||
|
||||
if (virtualTable.EntityQueryMetadata.TryGetConnectionsLimit(methodName, out var limit))
|
||||
{
|
||||
maxParallelExecuteCount = Math.Min(limit, maxParallelExecuteCount);
|
||||
}
|
||||
|
||||
var isSequence = mergeQueryCompilerContext.IsSequence();
|
||||
var sameWithShardingComparer = mergeQueryCompilerContext.SameWithShardingComparer();
|
||||
if (isSequence.HasValue && sameWithShardingComparer.HasValue)
|
||||
{
|
||||
sequenceQuery = isSequence.Value;
|
||||
sameWithTailComparer = sameWithShardingComparer.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TryGetSequenceQuery(parseResult, singleShardingEntityType, virtualTable, methodName,
|
||||
out var tailComparerIsAsc))
|
||||
{
|
||||
sequenceQuery = true;
|
||||
if (!tailComparerIsAsc)
|
||||
{
|
||||
sameWithTailComparer = !sameWithTailComparer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxParallelExecuteCount = mergeQueryCompilerContext.GetMaxQueryConnectionsLimit() ?? maxParallelExecuteCount;
|
||||
|
||||
connectionMode = CalcConnectionMode(mergeQueryCompilerContext.GetDataSourceRouteResult().IntersectDataSources.Count,maxParallelExecuteCount, mergeQueryCompilerContext.GetConnectionMode() ?? connectionMode);
|
||||
var canTrip = mergeQueryCompilerContext.GetTableRouteResults().Length > maxParallelExecuteCount;
|
||||
return new OptimizeResult(maxParallelExecuteCount, connectionMode, sequenceQuery, sameWithTailComparer,
|
||||
shardingTailComparer, canTrip);
|
||||
}
|
||||
|
||||
private ConnectionModeEnum CalcConnectionMode(int sqlCount,int maxQueryConnectionsLimit, ConnectionModeEnum connectionMode)
|
||||
{
|
||||
switch (connectionMode)
|
||||
{
|
||||
case ConnectionModeEnum.MEMORY_STRICTLY:
|
||||
case ConnectionModeEnum.CONNECTION_STRICTLY: return connectionMode;
|
||||
default:
|
||||
{
|
||||
return maxQueryConnectionsLimit < sqlCount
|
||||
? ConnectionModeEnum.CONNECTION_STRICTLY
|
||||
: ConnectionModeEnum.MEMORY_STRICTLY; ;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否需要判断order
|
||||
/// </summary>
|
||||
/// <param name="methodName"></param>
|
||||
/// <param name="propertyOrders"></param>
|
||||
/// <returns></returns>
|
||||
private bool EffectOrder(string methodName, PropertyOrder[] propertyOrders)
|
||||
{
|
||||
if ((methodName == null ||
|
||||
nameof(Queryable.First) == methodName ||
|
||||
nameof(Queryable.FirstOrDefault) == methodName ||
|
||||
nameof(Queryable.Last) == methodName ||
|
||||
nameof(Queryable.LastOrDefault) == methodName ||
|
||||
nameof(Queryable.Single) == methodName ||
|
||||
nameof(Queryable.SingleOrDefault) == methodName ||
|
||||
EntityQueryMetadata.QUERY_ENUMERATOR == methodName) &&
|
||||
propertyOrders.Length > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 尝试获取当前方法是否采用顺序查询,如果有先判断排序没有的情况下判断默认
|
||||
/// </summary>
|
||||
/// <param name="parseResult"></param>
|
||||
/// <param name="singleShardingEntityType"></param>
|
||||
/// <param name="virtualTable"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <param name="tailComparerIsAsc"></param>
|
||||
/// <returns></returns>
|
||||
private bool TryGetSequenceQuery(IParseResult parseResult, Type singleShardingEntityType, IVirtualTable virtualTable, string methodName, out bool tailComparerIsAsc)
|
||||
{
|
||||
var propertyOrders = parseResult.GetOrderByContext().PropertyOrders.ToArray();
|
||||
var effectOrder = EffectOrder(methodName, propertyOrders);
|
||||
|
||||
if (effectOrder)
|
||||
{
|
||||
var primaryOrder = propertyOrders[0];
|
||||
//不是多级order
|
||||
var primaryOrderPropertyName = primaryOrder.PropertyExpression;
|
||||
if (!primaryOrderPropertyName.Contains("."))
|
||||
{
|
||||
if (virtualTable.EnableEntityQuery && virtualTable.EntityQueryMetadata.TryContainsComparerOrder(primaryOrderPropertyName, out var seqQueryOrderMatch)
|
||||
&& (primaryOrder.OwnerType == singleShardingEntityType || seqQueryOrderMatch.OrderMatch.HasFlag(SeqOrderMatchEnum.Named)))//要么必须是当前对象查询要么就是名称一样
|
||||
{
|
||||
tailComparerIsAsc = seqQueryOrderMatch.IsSameAsShardingTailComparer ? primaryOrder.IsAsc : !primaryOrder.IsAsc;
|
||||
//如果是获取最后一个还需要再次翻转
|
||||
if (nameof(Queryable.Last) == methodName || nameof(Queryable.LastOrDefault) == methodName)
|
||||
{
|
||||
tailComparerIsAsc = !tailComparerIsAsc;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tailComparerIsAsc = true;
|
||||
return false;
|
||||
}
|
||||
if (virtualTable.EnableEntityQuery && methodName != null &&
|
||||
virtualTable.EntityQueryMetadata.TryGetDefaultSequenceQueryTrip(methodName, out var defaultAsc))
|
||||
{
|
||||
tailComparerIsAsc = defaultAsc;
|
||||
return true;
|
||||
}
|
||||
//Max和Min
|
||||
if (nameof(Queryable.Max) == methodName || nameof(Queryable.Min) == methodName)
|
||||
{
|
||||
//如果是max或者min
|
||||
if (virtualTable.EnableEntityQuery && parseResult.GetSelectContext().SelectProperties.Count == 1 && virtualTable.EntityQueryMetadata.TryContainsComparerOrder(parseResult.GetSelectContext().SelectProperties[0].PropertyName, out var seqQueryOrderMatch)
|
||||
&& (parseResult.GetSelectContext().SelectProperties[0].OwnerType == singleShardingEntityType || seqQueryOrderMatch.OrderMatch.HasFlag(SeqOrderMatchEnum.Named)))
|
||||
{
|
||||
tailComparerIsAsc = seqQueryOrderMatch.IsSameAsShardingTailComparer ? nameof(Queryable.Min) == methodName : nameof(Queryable.Max) == methodName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tailComparerIsAsc = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
/*
|
||||
|
@ -14,7 +15,12 @@ namespace ShardingCore.Sharding.MergeContexts
|
|||
{
|
||||
public IParseResult Parse(IMergeQueryCompilerContext mergeQueryCompilerContext)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var combineQueryable = mergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable();
|
||||
var queryableExtraDiscoverVisitor = new QueryableExtraDiscoverVisitor();
|
||||
queryableExtraDiscoverVisitor.Visit(combineQueryable.Expression);
|
||||
return new ParseResult(queryableExtraDiscoverVisitor.GetPaginationContext(),
|
||||
queryableExtraDiscoverVisitor.GetOrderByContext(), queryableExtraDiscoverVisitor.GetSelectContext(),
|
||||
queryableExtraDiscoverVisitor.GetGroupByContext());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.ShardingQueryableExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
using ShardingCore.Sharding.Visitors.Selects;
|
||||
|
||||
#if EFCORE2
|
||||
using Microsoft.EntityFrameworkCore.Query.Sql;
|
||||
#endif
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
public sealed class QueryableRewriteEngine : IQueryableRewriteEngine
|
||||
{
|
||||
public IQueryable GetRewriteQueryable(IMergeQueryCompilerContext mergeQueryCompilerContext, IParseResult parseResult)
|
||||
{
|
||||
var paginationContext = parseResult.GetPaginationContext();
|
||||
var orderByContext = parseResult.GetOrderByContext();
|
||||
var groupByContext = parseResult.GetGroupByContext();
|
||||
var selectContext = parseResult.GetSelectContext();
|
||||
var skip = paginationContext.Skip;
|
||||
var take = paginationContext.Take;
|
||||
var orders = orderByContext.PropertyOrders;
|
||||
|
||||
//去除分页,获取前Take+Skip数量
|
||||
var reWriteQueryable = mergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable();
|
||||
if (take.HasValue)
|
||||
{
|
||||
reWriteQueryable = reWriteQueryable.RemoveTake();
|
||||
}
|
||||
|
||||
if (skip.HasValue)
|
||||
{
|
||||
reWriteQueryable = reWriteQueryable.RemoveSkip();
|
||||
}
|
||||
|
||||
if (take.HasValue)
|
||||
{
|
||||
if (skip.HasValue)
|
||||
{
|
||||
reWriteQueryable = reWriteQueryable.ReSkip(0).ReTake(take.Value + skip.GetValueOrDefault());
|
||||
}
|
||||
else
|
||||
{
|
||||
reWriteQueryable = reWriteQueryable.ReTake(take.Value + skip.GetValueOrDefault());
|
||||
}
|
||||
}
|
||||
//包含group by
|
||||
if (groupByContext.GroupExpression != null)
|
||||
{
|
||||
if (orders.IsEmpty())
|
||||
{
|
||||
//将查询的属性转换成order by
|
||||
var selectProperties = selectContext.SelectProperties.Where(o => !(o is SelectAggregateProperty)).ToArray();
|
||||
if (selectProperties.IsNotEmpty())
|
||||
{
|
||||
var sort = string.Join(",", selectProperties.Select(o => $"{o.PropertyName} asc"));
|
||||
reWriteQueryable = reWriteQueryable.OrderWithExpression(sort, null);
|
||||
foreach (var orderProperty in selectProperties)
|
||||
{
|
||||
orders.AddLast(new PropertyOrder(orderProperty.PropertyName, true, orderProperty.OwnerType));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!mergeQueryCompilerContext.UseUnionAllMerge())
|
||||
{
|
||||
//将查询的属性转换成order by 并且order和select的未聚合查询必须一致
|
||||
var selectProperties = selectContext.SelectProperties.Where(o => !(o is SelectAggregateProperty));
|
||||
|
||||
if (orders.Count() != selectProperties.Count())
|
||||
throw new ShardingCoreInvalidOperationException("group by query order items not equal select un-aggregate items");
|
||||
var os = orders.Select(o => o.PropertyExpression).ToList();
|
||||
var ss = selectProperties.Select(o => o.PropertyName).ToList();
|
||||
for (int i = 0; i < os.Count(); i++)
|
||||
{
|
||||
if (!os[i].Equals(ss[i]))
|
||||
throw new ShardingCoreInvalidOperationException($"group by query order items not equal select un-aggregate items: order:[{os[i]}],select:[{ss[i]}");
|
||||
}
|
||||
|
||||
}
|
||||
if (selectContext.HasAverage())
|
||||
{
|
||||
var averageSelectProperties = selectContext.SelectProperties.OfType<SelectAverageProperty>().ToList();
|
||||
var selectAggregateProperties = selectContext.SelectProperties.OfType<SelectAggregateProperty>().Where(o => !(o is SelectAverageProperty)).ToList();
|
||||
foreach (var averageSelectProperty in averageSelectProperties)
|
||||
{
|
||||
var selectCountProperty = selectAggregateProperties.FirstOrDefault(o => o is SelectCountProperty selectCountProperty);
|
||||
if (null != selectCountProperty)
|
||||
{
|
||||
averageSelectProperty.BindCountProperty(selectCountProperty.Property);
|
||||
}
|
||||
var selectSumProperty = selectAggregateProperties.FirstOrDefault(o => o is SelectSumProperty selectSumProperty && selectSumProperty.FromProperty == averageSelectProperty.FromProperty);
|
||||
if (selectSumProperty != null)
|
||||
{
|
||||
averageSelectProperty.BindSumProperty(selectSumProperty.Property);
|
||||
}
|
||||
|
||||
if (averageSelectProperty.CountProperty == null && averageSelectProperty.SumProperty == null)
|
||||
throw new ShardingCoreInvalidOperationException(
|
||||
$"use aggregate function average error,not found count aggregate function and not found sum aggregate function that property name same as average aggregate function property name:[{averageSelectProperty.FromProperty?.Name}]");
|
||||
}
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// //将查询的属性转换成order by 并且order和select的未聚合查询必须一致
|
||||
// var selectProperties = selectContext.SelectProperties.Where(o => !(o is SelectAggregateProperty));
|
||||
|
||||
// if (orders.Count() != selectProperties.Count())
|
||||
// throw new ShardingCoreInvalidOperationException("group by query order items not equal select un-aggregate items");
|
||||
// var os = orders.Select(o => o.PropertyExpression).ToList();
|
||||
// var ss = selectProperties.Select(o => o.PropertyName).ToList();
|
||||
// for (int i = 0; i < os.Count(); i++)
|
||||
// {
|
||||
// if (!os[i].Equals(ss[i]))
|
||||
// throw new ShardingCoreInvalidOperationException($"group by query order items not equal select un-aggregate items: order:[{os[i]}],select:[{ss[i]}");
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
if (mergeQueryCompilerContext.UseUnionAllMerge() & !mergeQueryCompilerContext.GetShardingDbContext().SupportUnionAllMerge())
|
||||
{
|
||||
throw new ShardingCoreException(
|
||||
$"if use {nameof(EntityFrameworkShardingQueryableExtension.UseUnionAllMerge)} plz rewrite {nameof(IQuerySqlGeneratorFactory)} with {nameof(IUnionAllMergeQuerySqlGeneratorFactory)} and {nameof(IQueryCompiler)} with {nameof(IUnionAllMergeQueryCompiler)}");
|
||||
|
||||
}
|
||||
|
||||
return reWriteQueryable;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeContexts
|
||||
{
|
||||
internal class RewriteResult
|
||||
{
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ namespace ShardingCore.Core.Internal.Visitors.Selects
|
|||
*/
|
||||
public class SelectContext
|
||||
{
|
||||
public List<SelectProperty> SelectProperties { get; set; } = new List<SelectProperty>();
|
||||
public List<SelectOwnerProperty> SelectProperties { get; } = new List<SelectOwnerProperty>();
|
||||
|
||||
public bool HasAverage()
|
||||
{
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.NotSupportShardingProviders.Abstractions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.Abstractions.ParallelExecutors;
|
||||
|
@ -10,6 +9,7 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions;
|
||||
using ShardingCore.Extensions;
|
||||
|
||||
namespace ShardingCore.Sharding.MergeEngines.Abstractions
|
||||
|
@ -24,9 +24,9 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions
|
|||
internal abstract class AbstractBaseMergeEngine<TEntity>
|
||||
{
|
||||
protected abstract StreamMergeContext<TEntity> GetStreamMergeContext();
|
||||
protected bool IsUnSupport()
|
||||
protected bool UseUnionAllMerge()
|
||||
{
|
||||
return GetStreamMergeContext().IsNotSupportSharding();
|
||||
return GetStreamMergeContext().UseUnionAllMerge();
|
||||
}
|
||||
/// <summary>
|
||||
/// 将查询分表分库结果按每个数据源进行分组
|
||||
|
@ -47,9 +47,9 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions
|
|||
{
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
if (IsUnSupport())
|
||||
if (UseUnionAllMerge())
|
||||
{
|
||||
var customerDatabaseSqlSupportManager = ShardingContainer.GetService<INotSupportManager>();
|
||||
var customerDatabaseSqlSupportManager = ShardingContainer.GetService<IUnionAllMergeManager>();
|
||||
using (customerDatabaseSqlSupportManager.CreateScope(
|
||||
((UnSupportSqlRouteUnit)dataSourceSqlExecutorUnit.SqlExecutorGroups[0].Groups[0]
|
||||
.RouteUnit).TableRouteResults))
|
||||
|
@ -74,7 +74,7 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions
|
|||
return streamMergeContext.DataSourceRouteResult.IntersectDataSources.SelectMany(
|
||||
dataSourceName =>
|
||||
{
|
||||
if (IsUnSupport())
|
||||
if (UseUnionAllMerge())
|
||||
{
|
||||
return new []{ (ISqlRouteUnit)new UnSupportSqlRouteUnit(dataSourceName, streamMergeContext.TableRouteResults) };
|
||||
}
|
||||
|
@ -112,7 +112,6 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions
|
|||
{
|
||||
var streamMergeContext = GetStreamMergeContext();
|
||||
var maxQueryConnectionsLimit = streamMergeContext.GetMaxQueryConnectionsLimit();
|
||||
var sqlCount = sqlGroups.Count();
|
||||
////根据用户配置单次查询期望并发数
|
||||
//int exceptCount =
|
||||
// Math.Max(
|
||||
|
@ -120,7 +119,7 @@ namespace ShardingCore.Sharding.MergeEngines.Abstractions
|
|||
// ? sqlCount / maxQueryConnectionsLimit
|
||||
// : sqlCount / maxQueryConnectionsLimit + 1, 1);
|
||||
//计算应该使用那种链接模式
|
||||
ConnectionModeEnum connectionMode = streamMergeContext.GetConnectionMode(sqlCount);
|
||||
ConnectionModeEnum connectionMode = streamMergeContext.GetConnectionMode();
|
||||
|
||||
//将SqlExecutorUnit进行分区,每个区maxQueryConnectionsLimit个
|
||||
//[1,2,3,4,5,6,7],maxQueryConnectionsLimit=3,结果就是[[1,2,3],[4,5,6],[7]]
|
||||
|
|
|
@ -10,6 +10,7 @@ using ShardingCore.Sharding.MergeEngines.ParallelExecutors;
|
|||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Helpers;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.MergeEngines.Abstractions;
|
||||
|
@ -36,7 +37,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.EnumeratorStreamMergeEngines.
|
|||
public override IStreamMergeAsyncEnumerator<TEntity>[] GetRouteQueryStreamMergeAsyncEnumerators(bool async, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
var noPaginationNoOrderQueryable = StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().RemoveAnyOrderBy();
|
||||
var noPaginationNoOrderQueryable = StreamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().RemoveAnyOrderBy().As<IQueryable<TEntity>>();
|
||||
var skip = StreamMergeContext.Skip.GetValueOrDefault();
|
||||
var take = StreamMergeContext.Take.HasValue ? StreamMergeContext.Take.Value : (_total - skip);
|
||||
if (take > int.MaxValue)
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace ShardingCore.Sharding.MergeEngines.EnumeratorStreamMergeEngines
|
|||
return new SingleQueryEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext);
|
||||
}
|
||||
|
||||
if (_streamMergeContext.IsNotSupportSharding())
|
||||
if (_streamMergeContext.UseUnionAllMerge())
|
||||
{
|
||||
return new DefaultShardingEnumeratorAsyncStreamMergeEngine<TShardingDbContext, TEntity>(_streamMergeContext);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.MergeEngines.Abstractions;
|
||||
|
@ -25,7 +26,7 @@ namespace ShardingCore.Sharding.MergeEngines.ParallelExecutors
|
|||
public AppendOrderSequenceEnumeratorParallelExecutor(StreamMergeContext<TEntity> streamMergeContext, bool async)
|
||||
{
|
||||
_streamMergeContext = streamMergeContext;
|
||||
_noPaginationQueryable = streamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake(); ;
|
||||
_noPaginationQueryable = streamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().As<IQueryable<TEntity>>(); ;
|
||||
_async = async;
|
||||
}
|
||||
public override async Task<ShardingMergeResult<IStreamMergeAsyncEnumerator<TEntity>>> ExecuteAsync(SqlExecutorUnit sqlExecutorUnit, CancellationToken cancellationToken = new CancellationToken())
|
||||
|
@ -39,8 +40,8 @@ namespace ShardingCore.Sharding.MergeEngines.ParallelExecutors
|
|||
private (IQueryable<TEntity>, DbContext) CreateAsyncExecuteQueryable(SequenceResult sequenceResult, IEnumerable<PropertyOrder> reSetOrders, ConnectionModeEnum connectionMode)
|
||||
{
|
||||
var shardingDbContext = _streamMergeContext.CreateDbContext(sequenceResult.DSName, sequenceResult.TableRouteResult, connectionMode);
|
||||
var newQueryable = (IQueryable<TEntity>)(_noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(reSetOrders))
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
var newQueryable = _noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take).OrderWithExpression(reSetOrders)
|
||||
.ReplaceDbContextQueryable(shardingDbContext).As<IQueryable<TEntity>>();
|
||||
return (newQueryable, shardingDbContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Threading.Tasks;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Abstractions.ParallelExecutors;
|
||||
using ShardingCore.Sharding.Enumerators;
|
||||
using ShardingCore.Sharding.MergeEngines.Abstractions;
|
||||
|
@ -25,7 +26,7 @@ namespace ShardingCore.Sharding.MergeEngines.ParallelExecutors
|
|||
{
|
||||
_streamMergeContext = streamMergeContext;
|
||||
_async = async;
|
||||
_noPaginationQueryable = streamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake();
|
||||
_noPaginationQueryable = streamMergeContext.GetOriginalQueryable().RemoveSkip().RemoveTake().As<IQueryable<TEntity>>();
|
||||
}
|
||||
public override async Task<ShardingMergeResult<IStreamMergeAsyncEnumerator<TEntity>>> ExecuteAsync(SqlExecutorUnit sqlExecutorUnit, CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
|
@ -38,8 +39,8 @@ namespace ShardingCore.Sharding.MergeEngines.ParallelExecutors
|
|||
private (IQueryable<TEntity>, DbContext) CreateAsyncExecuteQueryable( SequenceResult sequenceResult, ConnectionModeEnum connectionMode)
|
||||
{
|
||||
var shardingDbContext = _streamMergeContext.CreateDbContext(sequenceResult.DSName, sequenceResult.TableRouteResult, connectionMode);
|
||||
var newQueryable = (IQueryable<TEntity>)(_noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take))
|
||||
.ReplaceDbContextQueryable(shardingDbContext);
|
||||
var newQueryable = _noPaginationQueryable.Skip(sequenceResult.Skip).Take(sequenceResult.Take)
|
||||
.ReplaceDbContextQueryable(shardingDbContext).As<IQueryable<TEntity>>();
|
||||
return (newQueryable, shardingDbContext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ using ShardingCore.Core.EntityMetadatas;
|
|||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.Visitors.Selects;
|
||||
|
||||
|
@ -37,12 +38,12 @@ namespace ShardingCore.Core.Internal.StreamMerge.ReWrite
|
|||
var reWriteQueryable = _queryable;
|
||||
if (take.HasValue)
|
||||
{
|
||||
reWriteQueryable = reWriteQueryable.RemoveTake();
|
||||
reWriteQueryable = reWriteQueryable.RemoveTake().As<IQueryable<T>>();
|
||||
}
|
||||
|
||||
if (skip.HasValue)
|
||||
{
|
||||
reWriteQueryable = reWriteQueryable.RemoveSkip();
|
||||
reWriteQueryable = reWriteQueryable.RemoveSkip().As<IQueryable<T>>();
|
||||
}
|
||||
|
||||
if (take.HasValue)
|
||||
|
|
|
@ -32,13 +32,13 @@ namespace ShardingCore.Sharding.ShardingExecutors.Abstractions
|
|||
/// </summary>
|
||||
/// <returns></returns>
|
||||
bool IsQueryTrack();
|
||||
[Obsolete("plz use NotSupport() eg. dbcontext.Set<User>().NotSupport().Where(...).ToList()")]
|
||||
bool IsUnion();
|
||||
bool IsNotSupport();
|
||||
bool UseUnionAllMerge();
|
||||
|
||||
int? GetMaxQueryConnectionsLimit();
|
||||
ConnectionModeEnum? GetConnectionMode();
|
||||
bool? IsSequence();
|
||||
bool? SameWithShardingComparer();
|
||||
bool IsSingleShardingEntityQuery();
|
||||
Type GetSingleShardingEntityType();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,14 +105,9 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
return _queryCompilerContext.IsQueryTrack();
|
||||
}
|
||||
|
||||
public bool IsUnion()
|
||||
public bool UseUnionAllMerge()
|
||||
{
|
||||
return _queryCompilerContext.IsUnion();
|
||||
}
|
||||
|
||||
public bool IsNotSupport()
|
||||
{
|
||||
return _queryCompilerContext.IsNotSupport();
|
||||
return _queryCompilerContext.UseUnionAllMerge();
|
||||
}
|
||||
|
||||
public int? GetMaxQueryConnectionsLimit()
|
||||
|
@ -135,6 +130,16 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
return _queryCompilerContext.SameWithShardingComparer();
|
||||
}
|
||||
|
||||
public bool IsSingleShardingEntityQuery()
|
||||
{
|
||||
return _queryCompilerContext.IsSingleShardingEntityQuery();
|
||||
}
|
||||
|
||||
public Type GetSingleShardingEntityType()
|
||||
{
|
||||
return _queryCompilerContext.GetSingleShardingEntityType();
|
||||
}
|
||||
|
||||
public QueryCompilerExecutor GetQueryCompilerExecutor()
|
||||
{
|
||||
if (!hasQueryCompilerExecutor.HasValue)
|
||||
|
|
|
@ -23,9 +23,8 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
private QueryCompilerExecutor _queryCompilerExecutor;
|
||||
private bool? hasQueryCompilerExecutor;
|
||||
private readonly bool? _isNoTracking;
|
||||
private readonly bool _isUnion;
|
||||
private readonly bool _isParallelQuery;
|
||||
private readonly bool _isNotSupport;
|
||||
private readonly bool _useUnionAllMerge;
|
||||
private readonly int? _maxQueryConnectionsLimit;
|
||||
private readonly ConnectionModeEnum? _connectionMode;
|
||||
private readonly bool? _isSequence;
|
||||
|
@ -39,8 +38,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
var compileParseResult = ShardingUtil.GetQueryCompileParseResultByExpression(_queryExpression, _shardingDbContextType);
|
||||
_queryEntities = compileParseResult.QueryEntities;
|
||||
_isNoTracking = compileParseResult.IsNoTracking;
|
||||
_isUnion = compileParseResult.IsUnion;
|
||||
_isNotSupport = compileParameter.IsNotSupport();
|
||||
_useUnionAllMerge = compileParameter.IsNotSupport();
|
||||
_maxQueryConnectionsLimit = compileParameter.GetMaxQueryConnectionsLimit();
|
||||
_connectionMode = compileParameter.GetConnectionMode();
|
||||
_entityMetadataManager = ShardingContainer.GetRequiredEntityMetadataManager(_shardingDbContextType);
|
||||
|
@ -102,14 +100,9 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsUnion()
|
||||
public bool UseUnionAllMerge()
|
||||
{
|
||||
return _isUnion;
|
||||
}
|
||||
|
||||
public bool IsNotSupport()
|
||||
{
|
||||
return _isNotSupport;
|
||||
return _useUnionAllMerge;
|
||||
}
|
||||
|
||||
public int? GetMaxQueryConnectionsLimit()
|
||||
|
@ -132,6 +125,15 @@ namespace ShardingCore.Sharding.ShardingExecutors
|
|||
return _sameWithShardingComparer;
|
||||
}
|
||||
|
||||
public bool IsSingleShardingEntityQuery()
|
||||
{
|
||||
return _queryEntities.Count(o => _entityMetadataManager.IsSharding(o)) == 1;
|
||||
}
|
||||
|
||||
public Type GetSingleShardingEntityType()
|
||||
{
|
||||
return _queryEntities.Single(o => _entityMetadataManager.IsSharding(o));
|
||||
}
|
||||
|
||||
public QueryCompilerExecutor GetQueryCompilerExecutor()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core;
|
||||
using ShardingCore.Core.Internal.StreamMerge.ReWrite;
|
||||
using ShardingCore.Core.Internal.Visitors;
|
||||
using ShardingCore.Core.Internal.Visitors.Selects;
|
||||
using ShardingCore.Core.ShardingConfigurations.Abstractions;
|
||||
using ShardingCore.Core.TrackerManagers;
|
||||
|
@ -10,20 +8,16 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
|||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
|
||||
using ShardingCore.Exceptions;
|
||||
using ShardingCore.Extensions;
|
||||
using ShardingCore.Extensions.InternalExtensions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.ShardingComparision.Abstractions;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using ShardingCore.Core.NotSupportShardingProviders;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||
using ShardingCore.Core.VirtualTables;
|
||||
using ShardingCore.Sharding.EntityQueryConfigurations;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
|
||||
|
||||
namespace ShardingCore.Sharding
|
||||
|
@ -39,212 +33,66 @@ namespace ShardingCore.Sharding
|
|||
, IAsyncDisposable
|
||||
#endif
|
||||
{
|
||||
private readonly INotSupportShardingProvider _notSupportShardingProvider;
|
||||
private static readonly INotSupportShardingProvider _defaultNotSupportShardingProvider =
|
||||
new DefaultNotSupportShardingProvider();
|
||||
|
||||
|
||||
public IMergeQueryCompilerContext MergeQueryCompilerContext { get; }
|
||||
public IParseResult ParseResult { get; }
|
||||
public IQueryable RewriteQueryable { get; }
|
||||
public IOptimizeResult OptimizeResult { get; }
|
||||
|
||||
//private readonly IShardingScopeFactory _shardingScopeFactory;
|
||||
private readonly IQueryable<TEntity> _source;
|
||||
private readonly IShardingDbContext _shardingDbContext;
|
||||
private readonly IRouteTailFactory _routeTailFactory;
|
||||
|
||||
private readonly IQueryable<TEntity> _reWriteSource;
|
||||
//public IEnumerable<TableRouteResult> RouteResults { get; }
|
||||
//public DataSourceRouteResult RoutingResult { get; }
|
||||
public int? Skip { get; private set; }
|
||||
public int? Take { get; }
|
||||
public IEnumerable<PropertyOrder> Orders { get; private set; }
|
||||
|
||||
public SelectContext SelectContext { get; }
|
||||
public GroupByContext GroupByContext { get; }
|
||||
public TableRouteResult[] TableRouteResults { get; }
|
||||
public DataSourceRouteResult DataSourceRouteResult { get; }
|
||||
public SelectContext SelectContext => ParseResult.GetSelectContext();
|
||||
public GroupByContext GroupByContext => ParseResult.GetGroupByContext();
|
||||
public TableRouteResult[] TableRouteResults => MergeQueryCompilerContext.GetTableRouteResults();
|
||||
public DataSourceRouteResult DataSourceRouteResult => MergeQueryCompilerContext.GetDataSourceRouteResult();
|
||||
|
||||
/// <summary>
|
||||
/// 本次查询涉及的对象
|
||||
/// </summary>
|
||||
public ISet<Type> QueryEntities { get; }
|
||||
public ISet<Type> QueryEntities => MergeQueryCompilerContext.GetQueryEntities();
|
||||
|
||||
/// <summary>
|
||||
/// 本次查询跨库
|
||||
/// </summary>
|
||||
public bool IsCrossDataSource { get; }
|
||||
public bool IsCrossDataSource => MergeQueryCompilerContext.IsCrossDataSource();
|
||||
|
||||
/// <summary>
|
||||
/// 本次查询跨表
|
||||
/// </summary>
|
||||
public bool IsCrossTable { get; }
|
||||
public bool IsCrossTable => MergeQueryCompilerContext.IsCrossTable();
|
||||
|
||||
private readonly ITrackerManager _trackerManager;
|
||||
private readonly IShardingEntityConfigOptions _shardingEntityConfigOptions;
|
||||
|
||||
private readonly ConcurrentDictionary<DbContext, object> _parallelDbContexts;
|
||||
|
||||
private readonly bool _seqQuery = false;
|
||||
public IComparer<string> ShardingTailComparer => OptimizeResult.ShardingTailComparer();
|
||||
|
||||
public IComparer<string> ShardingTailComparer { get; } = Comparer<string>.Default;
|
||||
/// <summary>
|
||||
/// 分表后缀比较是否重排正序
|
||||
/// </summary>
|
||||
public bool TailComparerNeedReverse { get; } = true;
|
||||
|
||||
private int _maxParallelExecuteCount;
|
||||
private ConnectionModeEnum _connectionMode;
|
||||
public bool TailComparerNeedReverse => OptimizeResult.SameWithTailComparer();
|
||||
|
||||
|
||||
public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext,
|
||||
|
||||
public StreamMergeContext(IMergeQueryCompilerContext mergeQueryCompilerContext,IParseResult parseResult,IQueryable rewriteQueryable,IOptimizeResult optimizeResult,
|
||||
IRouteTailFactory routeTailFactory)
|
||||
{
|
||||
MergeQueryCompilerContext = mergeQueryCompilerContext;
|
||||
QueryEntities = mergeQueryCompilerContext.GetQueryEntities();
|
||||
//_shardingScopeFactory = shardingScopeFactory;
|
||||
_source = (IQueryable<TEntity>)mergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable();
|
||||
_shardingDbContext = mergeQueryCompilerContext.GetShardingDbContext();
|
||||
ParseResult = parseResult;
|
||||
RewriteQueryable = rewriteQueryable;
|
||||
OptimizeResult = optimizeResult;
|
||||
_routeTailFactory = routeTailFactory;
|
||||
DataSourceRouteResult = mergeQueryCompilerContext.GetDataSourceRouteResult();
|
||||
TableRouteResults = mergeQueryCompilerContext.GetTableRouteResults();
|
||||
IsCrossDataSource = mergeQueryCompilerContext.IsCrossDataSource();
|
||||
IsCrossTable = mergeQueryCompilerContext.IsCrossTable();
|
||||
var reWriteResult = new ReWriteEngine<TEntity>(_source).ReWrite();
|
||||
Skip = reWriteResult.Skip;
|
||||
Take = reWriteResult.Take;
|
||||
Orders = reWriteResult.Orders ?? Enumerable.Empty<PropertyOrder>();
|
||||
SelectContext = reWriteResult.SelectContext;
|
||||
GroupByContext = reWriteResult.GroupByContext;
|
||||
_reWriteSource = reWriteResult.ReWriteQueryable;
|
||||
_trackerManager =
|
||||
(ITrackerManager)ShardingContainer.GetService(
|
||||
typeof(ITrackerManager<>).GetGenericType0(mergeQueryCompilerContext.GetShardingDbContextType()));
|
||||
|
||||
|
||||
_trackerManager = ShardingContainer.GetTrackerManager(mergeQueryCompilerContext.GetShardingDbContextType());
|
||||
_shardingEntityConfigOptions = ShardingContainer.GetRequiredShardingEntityConfigOption(mergeQueryCompilerContext.GetShardingDbContextType());
|
||||
_notSupportShardingProvider = ShardingContainer.GetService<INotSupportShardingProvider>() ?? _defaultNotSupportShardingProvider;
|
||||
_parallelDbContexts = new ConcurrentDictionary<DbContext, object>();
|
||||
|
||||
var maxParallelExecuteCount = _shardingDbContext.GetVirtualDataSource().ConfigurationParams.MaxQueryConnectionsLimit;
|
||||
var connectionMode = _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ConnectionMode;
|
||||
if (IsSingleShardingEntityQuery() && IsCrossTable && !IsNotSupportSharding())
|
||||
{
|
||||
var singleShardingEntityType = GetSingleShardingEntityType();
|
||||
var virtualTableManager = (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(MergeQueryCompilerContext.GetShardingDbContextType()));
|
||||
var virtualTable = virtualTableManager.GetVirtualTable(singleShardingEntityType);
|
||||
|
||||
if (virtualTable.EnableEntityQuery)
|
||||
{
|
||||
ShardingTailComparer =
|
||||
virtualTable.EntityQueryMetadata.DefaultTailComparer ?? Comparer<string>.Default;
|
||||
TailComparerNeedReverse = virtualTable.EntityQueryMetadata.DefaultTailComparerNeedReverse;
|
||||
string methodName = MergeQueryCompilerContext.IsEnumerableQuery() ?
|
||||
EntityQueryMetadata.QUERY_ENUMERATOR :
|
||||
((MethodCallExpression)MergeQueryCompilerContext.GetQueryExpression()).Method.Name;
|
||||
|
||||
if (virtualTable.EntityQueryMetadata.TryGetConnectionsLimit(methodName, out var limit))
|
||||
{
|
||||
maxParallelExecuteCount = Math.Min(limit, maxParallelExecuteCount);
|
||||
}
|
||||
|
||||
var isSequence = mergeQueryCompilerContext.IsSequence();
|
||||
var sameWithShardingComparer = mergeQueryCompilerContext.SameWithShardingComparer();
|
||||
if (isSequence.HasValue && sameWithShardingComparer.HasValue)
|
||||
{
|
||||
_seqQuery = isSequence.Value;
|
||||
TailComparerNeedReverse = sameWithShardingComparer.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
var propertyOrders = Orders as PropertyOrder[] ?? Orders.ToArray();
|
||||
if (TryGetSequenceQuery(propertyOrders, singleShardingEntityType, virtualTable, methodName,
|
||||
out var tailComparerIsAsc))
|
||||
{
|
||||
_seqQuery = true;
|
||||
if (!tailComparerIsAsc)
|
||||
{
|
||||
TailComparerNeedReverse = !TailComparerNeedReverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_maxParallelExecuteCount = mergeQueryCompilerContext.GetMaxQueryConnectionsLimit() ?? maxParallelExecuteCount;
|
||||
_connectionMode = mergeQueryCompilerContext.GetConnectionMode() ?? connectionMode;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否需要判断order
|
||||
/// </summary>
|
||||
/// <param name="methodName"></param>
|
||||
/// <param name="propertyOrders"></param>
|
||||
/// <returns></returns>
|
||||
private bool EffectOrder(string methodName, PropertyOrder[] propertyOrders)
|
||||
{
|
||||
if ((methodName == null ||
|
||||
nameof(Queryable.First) == methodName ||
|
||||
nameof(Queryable.FirstOrDefault) == methodName ||
|
||||
nameof(Queryable.Last) == methodName ||
|
||||
nameof(Queryable.LastOrDefault) == methodName ||
|
||||
nameof(Queryable.Single) == methodName ||
|
||||
nameof(Queryable.SingleOrDefault) == methodName ||
|
||||
EntityQueryMetadata.QUERY_ENUMERATOR == methodName) &&
|
||||
propertyOrders.Length > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 尝试获取当前方法是否采用顺序查询,如果有先判断排序没有的情况下判断默认
|
||||
/// </summary>
|
||||
/// <param name="propertyOrders"></param>
|
||||
/// <param name="singleShardingEntityType"></param>
|
||||
/// <param name="virtualTable"></param>
|
||||
/// <param name="methodName"></param>
|
||||
/// <param name="tailComparerIsAsc"></param>
|
||||
/// <returns></returns>
|
||||
private bool TryGetSequenceQuery(PropertyOrder[] propertyOrders, Type singleShardingEntityType, IVirtualTable virtualTable, string methodName, out bool tailComparerIsAsc)
|
||||
{
|
||||
var effectOrder = EffectOrder(methodName, propertyOrders);
|
||||
|
||||
if (effectOrder)
|
||||
{
|
||||
var primaryOrder = propertyOrders[0];
|
||||
//不是多级order
|
||||
var primaryOrderPropertyName = primaryOrder.PropertyExpression;
|
||||
if (!primaryOrderPropertyName.Contains("."))
|
||||
{
|
||||
if (virtualTable.EnableEntityQuery && virtualTable.EntityQueryMetadata.TryContainsComparerOrder(primaryOrderPropertyName, out var seqQueryOrderMatch)
|
||||
&& (primaryOrder.OwnerType == singleShardingEntityType || seqQueryOrderMatch.OrderMatch.HasFlag(SeqOrderMatchEnum.Named)))//要么必须是当前对象查询要么就是名称一样
|
||||
{
|
||||
tailComparerIsAsc = seqQueryOrderMatch.IsSameAsShardingTailComparer ? primaryOrder.IsAsc : !primaryOrder.IsAsc;
|
||||
//如果是获取最后一个还需要再次翻转
|
||||
if (nameof(Queryable.Last) == methodName || nameof(Queryable.LastOrDefault) == methodName)
|
||||
{
|
||||
tailComparerIsAsc = !tailComparerIsAsc;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
tailComparerIsAsc = true;
|
||||
return false;
|
||||
}
|
||||
if (virtualTable.EnableEntityQuery && methodName != null &&
|
||||
virtualTable.EntityQueryMetadata.TryGetDefaultSequenceQueryTrip(methodName, out var defaultAsc))
|
||||
{
|
||||
tailComparerIsAsc = defaultAsc;
|
||||
return true;
|
||||
}
|
||||
//Max和Min
|
||||
if (nameof(Queryable.Max) == methodName || nameof(Queryable.Min) == methodName)
|
||||
{
|
||||
//如果是max或者min
|
||||
if (virtualTable.EnableEntityQuery && SelectContext.SelectProperties.Count == 1 && virtualTable.EntityQueryMetadata.TryContainsComparerOrder(SelectContext.SelectProperties[0].PropertyName, out var seqQueryOrderMatch)
|
||||
&& (SelectContext.SelectProperties[0].OwnerType == singleShardingEntityType || seqQueryOrderMatch.OrderMatch.HasFlag(SeqOrderMatchEnum.Named)))
|
||||
{
|
||||
tailComparerIsAsc = seqQueryOrderMatch.IsSameAsShardingTailComparer ? nameof(Queryable.Min) == methodName : nameof(Queryable.Max) == methodName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tailComparerIsAsc = true;
|
||||
return false;
|
||||
Orders = parseResult.GetOrderByContext().PropertyOrders.ToArray();
|
||||
Skip = parseResult.GetPaginationContext().Skip;
|
||||
Take = parseResult.GetPaginationContext().Take;
|
||||
}
|
||||
|
||||
public void ReSetOrders(IEnumerable<PropertyOrder> orders)
|
||||
|
@ -268,7 +116,7 @@ namespace ShardingCore.Sharding
|
|||
var routeTail = _routeTailFactory.Create(tableRouteResult);
|
||||
//如果开启了读写分离或者本次查询是跨表的表示本次查询的dbcontext是不存储的用完后就直接dispose
|
||||
var parallelQuery = IsParallelQuery();
|
||||
var dbContext = _shardingDbContext.GetDbContext(dataSourceName, parallelQuery, routeTail);
|
||||
var dbContext = GetShardingDbContext().GetDbContext(dataSourceName, parallelQuery, routeTail);
|
||||
if (parallelQuery && RealConnectionMode(connectionMode) == ConnectionModeEnum.MEMORY_STRICTLY)
|
||||
{
|
||||
_parallelDbContexts.TryAdd(dbContext, null);
|
||||
|
@ -300,11 +148,11 @@ namespace ShardingCore.Sharding
|
|||
|
||||
public IQueryable<TEntity> GetReWriteQueryable()
|
||||
{
|
||||
return _reWriteSource;
|
||||
return RewriteQueryable.As<IQueryable<TEntity>>();
|
||||
}
|
||||
public IQueryable<TEntity> GetOriginalQueryable()
|
||||
{
|
||||
return _source;
|
||||
return MergeQueryCompilerContext.GetQueryCombineResult().GetCombineQueryable().As<IQueryable<TEntity>>();
|
||||
}
|
||||
|
||||
public int? GetPaginationReWriteTake()
|
||||
|
@ -349,39 +197,25 @@ namespace ShardingCore.Sharding
|
|||
|
||||
public IShardingDbContext GetShardingDbContext()
|
||||
{
|
||||
return _shardingDbContext;
|
||||
return MergeQueryCompilerContext.GetShardingDbContext();
|
||||
}
|
||||
|
||||
public int GetMaxQueryConnectionsLimit()
|
||||
{
|
||||
return _maxParallelExecuteCount;
|
||||
return OptimizeResult.GetMaxQueryConnectionsLimit();
|
||||
}
|
||||
public ConnectionModeEnum GetConnectionMode(int sqlCount)
|
||||
public ConnectionModeEnum GetConnectionMode()
|
||||
{
|
||||
return CalcConnectionMode(sqlCount);
|
||||
return OptimizeResult.GetConnectionMode();
|
||||
}
|
||||
|
||||
private ConnectionModeEnum CalcConnectionMode(int sqlCount)
|
||||
{
|
||||
switch (_connectionMode)
|
||||
{
|
||||
case ConnectionModeEnum.MEMORY_STRICTLY:
|
||||
case ConnectionModeEnum.CONNECTION_STRICTLY: return _connectionMode;
|
||||
default:
|
||||
{
|
||||
return GetMaxQueryConnectionsLimit() < sqlCount
|
||||
? ConnectionModeEnum.CONNECTION_STRICTLY
|
||||
: ConnectionModeEnum.MEMORY_STRICTLY; ;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否启用读写分离
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool IsUseReadWriteSeparation()
|
||||
{
|
||||
return _shardingDbContext.IsUseReadWriteSeparation() && _shardingDbContext.CurrentIsReadWriteSeparation();
|
||||
return GetShardingDbContext().IsUseReadWriteSeparation() && GetShardingDbContext().CurrentIsReadWriteSeparation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -410,7 +244,7 @@ namespace ShardingCore.Sharding
|
|||
|
||||
public IShardingComparer GetShardingComparer()
|
||||
{
|
||||
return _shardingDbContext.GetVirtualDataSource().ConfigurationParams.ShardingComparer;
|
||||
return GetShardingDbContext().GetVirtualDataSource().ConfigurationParams.ShardingComparer;
|
||||
}
|
||||
|
||||
public TResult PreperExecute<TResult>(Func<TResult> emptyFunc)
|
||||
|
@ -456,20 +290,9 @@ namespace ShardingCore.Sharding
|
|||
return _shardingEntityConfigOptions.ThrowIfQueryRouteNotMatch;
|
||||
}
|
||||
|
||||
private bool? _isNotSupport;
|
||||
public bool IsNotSupportSharding()
|
||||
public bool UseUnionAllMerge()
|
||||
{
|
||||
if (MergeQueryCompilerContext.IsNotSupport())
|
||||
return true;
|
||||
if (!_isNotSupport.HasValue)
|
||||
{
|
||||
_isNotSupport = _notSupportShardingProvider.IsNotSupportSharding(MergeQueryCompilerContext);
|
||||
if (_isNotSupport.Value)
|
||||
{
|
||||
_notSupportShardingProvider.CheckNotSupportSharding(MergeQueryCompilerContext);
|
||||
}
|
||||
}
|
||||
return _isNotSupport.Value;
|
||||
return MergeQueryCompilerContext.UseUnionAllMerge();
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
|
@ -490,18 +313,18 @@ namespace ShardingCore.Sharding
|
|||
#endif
|
||||
public bool IsSeqQuery()
|
||||
{
|
||||
return _seqQuery;
|
||||
return OptimizeResult.IsSequenceQuery();
|
||||
}
|
||||
|
||||
public bool CanTrip()
|
||||
{
|
||||
return TableRouteResults.Length > GetMaxQueryConnectionsLimit();
|
||||
return OptimizeResult.CanTrip();
|
||||
}
|
||||
|
||||
public string GetPrintInfo()
|
||||
{
|
||||
return
|
||||
$"stream merge context:[max query connections limit:{GetMaxQueryConnectionsLimit()}],[is use read write separation:{IsUseReadWriteSeparation()}],[is parallel query:{IsParallelQuery()}],[is not support sharding:{IsNotSupportSharding()}],[is sequence query:{IsSeqQuery()}],[can trip:{CanTrip()}],[is route not match:{IsRouteNotMatch()}],[throw if query route not match:{ThrowIfQueryRouteNotMatch()}],[is pagination query:{IsPaginationQuery()}],[has group query:{HasGroupQuery()}],[is merge query:{IsMergeQuery()}],[is single sharding entity query:{IsSingleShardingEntityQuery()}]";
|
||||
$"stream merge context:[max query connections limit:{GetMaxQueryConnectionsLimit()}],[is use read write separation:{IsUseReadWriteSeparation()}],[is parallel query:{IsParallelQuery()}],[is not support sharding:{UseUnionAllMerge()}],[is sequence query:{IsSeqQuery()}],[can trip:{CanTrip()}],[is route not match:{IsRouteNotMatch()}],[throw if query route not match:{ThrowIfQueryRouteNotMatch()}],[is pagination query:{IsPaginationQuery()}],[has group query:{HasGroupQuery()}],[is merge query:{IsMergeQuery()}],[is single sharding entity query:{IsSingleShardingEntityQuery()}]";
|
||||
}
|
||||
|
||||
public int? GetSkip()
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Linq;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using ShardingCore.Core.VirtualRoutes.DataSourceRoutes.RouteRuleEngine;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.MergeContexts;
|
||||
using ShardingCore.Sharding.ShardingExecutors.Abstractions;
|
||||
|
||||
namespace ShardingCore.Sharding
|
||||
|
@ -18,14 +19,25 @@ namespace ShardingCore.Sharding
|
|||
public class StreamMergeContextFactory<TShardingDbContext> : IStreamMergeContextFactory<TShardingDbContext> where TShardingDbContext:DbContext,IShardingDbContext
|
||||
{
|
||||
private readonly IRouteTailFactory _routeTailFactory;
|
||||
private readonly IQueryableParseEngine _queryableParseEngine;
|
||||
private readonly IQueryableRewriteEngine _queryableRewriteEngine;
|
||||
private readonly IQueryableOptimizeEngine _queryableOptimizeEngine;
|
||||
|
||||
public StreamMergeContextFactory(IRouteTailFactory routeTailFactory)
|
||||
public StreamMergeContextFactory(IRouteTailFactory routeTailFactory
|
||||
, IQueryableParseEngine queryableParseEngine, IQueryableRewriteEngine queryableRewriteEngine, IQueryableOptimizeEngine queryableOptimizeEngine
|
||||
)
|
||||
{
|
||||
_routeTailFactory = routeTailFactory;
|
||||
_queryableParseEngine = queryableParseEngine;
|
||||
_queryableRewriteEngine = queryableRewriteEngine;
|
||||
_queryableOptimizeEngine = queryableOptimizeEngine;
|
||||
}
|
||||
public StreamMergeContext<T> Create<T>(IMergeQueryCompilerContext mergeQueryCompilerContext)
|
||||
{
|
||||
return new StreamMergeContext<T>(mergeQueryCompilerContext, _routeTailFactory);
|
||||
var parseResult = _queryableParseEngine.Parse(mergeQueryCompilerContext);
|
||||
var rewriteQueryable = _queryableRewriteEngine.GetRewriteQueryable(mergeQueryCompilerContext, parseResult);
|
||||
var optimizeResult = _queryableOptimizeEngine.Optimize(mergeQueryCompilerContext, parseResult, rewriteQueryable);
|
||||
return new StreamMergeContext<T>(mergeQueryCompilerContext, parseResult, rewriteQueryable,optimizeResult, _routeTailFactory);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,7 +41,7 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
var selectAggregateProperties = SelectContext.SelectProperties.OfType<SelectAggregateProperty>().Where(o=>!(o is SelectAverageProperty)).ToList();
|
||||
foreach (var averageSelectProperty in averageSelectProperties)
|
||||
{
|
||||
var selectCountProperty = selectAggregateProperties.FirstOrDefault(o=>o is SelectCountProperty);
|
||||
var selectCountProperty = selectAggregateProperties.FirstOrDefault(o=>o is SelectCountProperty selectCountProperty);
|
||||
if (null != selectCountProperty)
|
||||
{
|
||||
averageSelectProperty.BindCountProperty(selectCountProperty.Property);
|
||||
|
|
|
@ -36,21 +36,25 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
|
||||
private PropertyInfo GetAggregateFromProperty(MethodCallExpression aggregateMethodCallExpression)
|
||||
{
|
||||
if (aggregateMethodCallExpression.Arguments.Count > 1)
|
||||
{
|
||||
var selector = aggregateMethodCallExpression.Arguments[1] as LambdaExpression;
|
||||
if (selector == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var memberExpression = selector.Body as MemberExpression;
|
||||
if (memberExpression == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (memberExpression.Member.DeclaringType == null)
|
||||
return null;
|
||||
var fromProperty = memberExpression.Member.DeclaringType.GetProperty(memberExpression.Member.Name);
|
||||
return fromProperty;
|
||||
}
|
||||
|
||||
var selector = aggregateMethodCallExpression.Arguments[1] as LambdaExpression;
|
||||
if (selector == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var memberExpression = selector.Body as MemberExpression;
|
||||
if (memberExpression == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if(memberExpression.Member.DeclaringType == null)
|
||||
return null;
|
||||
var fromProperty = memberExpression.Member.DeclaringType.GetProperty(memberExpression.Member.Name);
|
||||
return fromProperty;
|
||||
throw new ShardingCoreException($"cant {nameof(GetAggregateFromProperty)},{aggregateMethodCallExpression.ShardingPrint()}");
|
||||
|
||||
}
|
||||
protected override Expression VisitNew(NewExpression node)
|
||||
|
@ -68,46 +72,46 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
var method = methodCallExpression.Method;
|
||||
if (method.Name == nameof(Queryable.Count) || method.Name == nameof(Queryable.Sum) || method.Name == nameof(Queryable.Max) || method.Name == nameof(Queryable.Min) || method.Name == nameof(Queryable.Average))
|
||||
{
|
||||
SelectProperty selectProperty = null;
|
||||
SelectOwnerProperty selectOwnerProperty = null;
|
||||
|
||||
if (method.Name == nameof(Queryable.Average))
|
||||
{
|
||||
var fromProperty = GetAggregateFromProperty(methodCallExpression);
|
||||
selectProperty = new SelectAverageProperty(declaringType,
|
||||
selectOwnerProperty = new SelectAverageProperty(declaringType,
|
||||
propertyInfo, fromProperty, true, method.Name);
|
||||
}
|
||||
else if (method.Name == nameof(Queryable.Count))
|
||||
{
|
||||
selectProperty = new SelectCountProperty(declaringType,
|
||||
selectOwnerProperty = new SelectCountProperty(declaringType,
|
||||
propertyInfo, true, method.Name);
|
||||
}
|
||||
else if (method.Name == nameof(Queryable.Sum))
|
||||
{
|
||||
var fromProperty = GetAggregateFromProperty(methodCallExpression);
|
||||
selectProperty = new SelectSumProperty(declaringType,
|
||||
selectOwnerProperty = new SelectSumProperty(declaringType,
|
||||
propertyInfo, fromProperty, true, method.Name);
|
||||
}
|
||||
else if (method.Name == nameof(Queryable.Max))
|
||||
{
|
||||
selectProperty = new SelectMaxProperty(declaringType,
|
||||
selectOwnerProperty = new SelectMaxProperty(declaringType,
|
||||
propertyInfo, true, method.Name);
|
||||
}
|
||||
else if (method.Name == nameof(Queryable.Min))
|
||||
{
|
||||
selectProperty = new SelectMinProperty(declaringType,
|
||||
selectOwnerProperty = new SelectMinProperty(declaringType,
|
||||
propertyInfo, true, method.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
selectProperty = new SelectAggregateProperty(declaringType,
|
||||
selectOwnerProperty = new SelectAggregateProperty(declaringType,
|
||||
propertyInfo,
|
||||
true, method.Name);
|
||||
}
|
||||
_selectContext.SelectProperties.Add(selectProperty);
|
||||
_selectContext.SelectProperties.Add(selectOwnerProperty);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_selectContext.SelectProperties.Add(new SelectProperty(declaringType,
|
||||
_selectContext.SelectProperties.Add(new SelectOwnerProperty(declaringType,
|
||||
propertyInfo));
|
||||
}
|
||||
return base.VisitNew(node);
|
||||
|
|
|
@ -18,11 +18,10 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
*/
|
||||
internal class QueryableExtraDiscoverVisitor : ShardingExpressionVisitor
|
||||
{
|
||||
private int? _skip;
|
||||
private int? _take;
|
||||
private LinkedList<PropertyOrder> _orders = new LinkedList<PropertyOrder>();
|
||||
private GroupByContext _groupByContext = new GroupByContext();
|
||||
private SelectContext _selectContext = new SelectContext();
|
||||
private PaginationContext _paginationContext = new PaginationContext();
|
||||
private OrderByContext _orderByContext = new OrderByContext();
|
||||
|
||||
|
||||
public SelectContext GetSelectContext()
|
||||
|
@ -35,51 +34,29 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
return _groupByContext;
|
||||
}
|
||||
|
||||
public int? GetSkip()
|
||||
public PaginationContext GetPaginationContext()
|
||||
{
|
||||
return _skip;
|
||||
return _paginationContext;
|
||||
}
|
||||
|
||||
public bool HasSkip()
|
||||
public OrderByContext GetOrderByContext()
|
||||
{
|
||||
return _skip.HasValue;
|
||||
return _orderByContext;
|
||||
}
|
||||
|
||||
public int? GetTake()
|
||||
{
|
||||
return _take;
|
||||
}
|
||||
|
||||
public bool HasTake()
|
||||
{
|
||||
return _take.HasValue;
|
||||
}
|
||||
|
||||
public IEnumerable<PropertyOrder> GetOrders()
|
||||
{
|
||||
return _orders;
|
||||
}
|
||||
|
||||
public string GetOrderExpression()
|
||||
{
|
||||
return string.Join(",", _orders);
|
||||
}
|
||||
|
||||
|
||||
protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||
{
|
||||
var method = node.Method;
|
||||
if (node.Method.Name == nameof(Queryable.Skip))
|
||||
{
|
||||
if (HasSkip())
|
||||
if (_paginationContext.HasSkip())
|
||||
throw new ShardingCoreInvalidOperationException("more than one skip found");
|
||||
_skip = (int)GetFieldValue(node.Arguments[1]);
|
||||
_paginationContext.Skip = (int)GetExpressionValue(node.Arguments[1]);
|
||||
}
|
||||
else if (node.Method.Name == nameof(Queryable.Take))
|
||||
{
|
||||
if (HasTake())
|
||||
if (_paginationContext.HasTake())
|
||||
throw new ShardingCoreInvalidOperationException("more than one take found");
|
||||
_take = (int)GetFieldValue(node.Arguments[1]);
|
||||
_paginationContext.Take = (int)GetExpressionValue(node.Arguments[1]);
|
||||
}
|
||||
else if (method.Name == nameof(Queryable.OrderBy) || method.Name == nameof(Queryable.OrderByDescending) || method.Name == nameof(Queryable.ThenBy) || method.Name == nameof(Queryable.ThenByDescending))
|
||||
{
|
||||
|
@ -94,7 +71,7 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
throw new NotSupportedException("sharding order only support property expression");
|
||||
properties.Reverse();
|
||||
var propertyExpression = string.Join(".", properties);
|
||||
_orders.AddFirst(new PropertyOrder(propertyExpression, method.Name == nameof(Queryable.OrderBy) || method.Name == nameof(Queryable.ThenBy), expression.Member.DeclaringType));
|
||||
_orderByContext.PropertyOrders.AddFirst(new PropertyOrder(propertyExpression, method.Name == nameof(Queryable.OrderBy) || method.Name == nameof(Queryable.ThenBy), expression.Member.DeclaringType));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +100,7 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
var declaringType = memberExpression.Member.DeclaringType;
|
||||
var memberName = memberExpression.Member.Name;
|
||||
var propertyInfo = declaringType.GetProperty(memberName);
|
||||
_selectContext.SelectProperties.Add(new SelectProperty(declaringType, propertyInfo));
|
||||
_selectContext.SelectProperties.Add(new SelectOwnerProperty(declaringType, propertyInfo));
|
||||
//memberExpression.Acc
|
||||
}
|
||||
//if (expression != null)
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
* @Date: Monday, 28 December 2020 22:09:39
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
public class QueryableRouteShardingTableDiscoverVisitor : ExpressionVisitor
|
||||
public class QueryableRouteShardingTableDiscoverVisitor : ShardingExpressionVisitor
|
||||
{
|
||||
|
||||
private readonly EntityMetadata _entityMetadata;
|
||||
|
@ -131,117 +131,117 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
return expression is MethodCallExpression;
|
||||
}
|
||||
|
||||
private object GetShardingKeyValue(Expression expression)
|
||||
{
|
||||
if (expression == null)
|
||||
return null;
|
||||
switch (expression)
|
||||
{
|
||||
case ConstantExpression e:
|
||||
return e.Value;
|
||||
//private object GetShardingKeyValue(Expression expression)
|
||||
//{
|
||||
// if (expression == null)
|
||||
// return null;
|
||||
// switch (expression)
|
||||
// {
|
||||
// case ConstantExpression e:
|
||||
// return e.Value;
|
||||
|
||||
case MemberExpression e when e.Member is FieldInfo field:
|
||||
return field.GetValue(
|
||||
GetShardingKeyValue(
|
||||
e.Expression
|
||||
)
|
||||
);
|
||||
// case MemberExpression e when e.Member is FieldInfo field:
|
||||
// return field.GetValue(
|
||||
// GetShardingKeyValue(
|
||||
// e.Expression
|
||||
// )
|
||||
// );
|
||||
|
||||
case MemberExpression e when e.Member is PropertyInfo property:
|
||||
return property.GetValue(
|
||||
GetShardingKeyValue(
|
||||
e.Expression
|
||||
)
|
||||
);
|
||||
// case MemberExpression e when e.Member is PropertyInfo property:
|
||||
// return property.GetValue(
|
||||
// GetShardingKeyValue(
|
||||
// e.Expression
|
||||
// )
|
||||
// );
|
||||
|
||||
case ListInitExpression e when e.NewExpression.Arguments.Count() == 0:
|
||||
{
|
||||
var collection = e.NewExpression.Constructor.Invoke(new object[0]);
|
||||
foreach (var i in e.Initializers)
|
||||
{
|
||||
i.AddMethod.Invoke(
|
||||
collection,
|
||||
i.Arguments
|
||||
.Select(
|
||||
a => GetShardingKeyValue(a)
|
||||
)
|
||||
.ToArray()
|
||||
);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
case NewArrayExpression e when e.NodeType == ExpressionType.NewArrayInit && e.Expressions.Count > 0:
|
||||
{
|
||||
var collection = new List<object>(e.Expressions.Count);
|
||||
foreach (var arrayItemExpression in e.Expressions)
|
||||
{
|
||||
collection.Add(GetShardingKeyValue(arrayItemExpression));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
// case ListInitExpression e when e.NewExpression.Arguments.Count() == 0:
|
||||
// {
|
||||
// var collection = e.NewExpression.Constructor.Invoke(new object[0]);
|
||||
// foreach (var i in e.Initializers)
|
||||
// {
|
||||
// i.AddMethod.Invoke(
|
||||
// collection,
|
||||
// i.Arguments
|
||||
// .Select(
|
||||
// a => GetShardingKeyValue(a)
|
||||
// )
|
||||
// .ToArray()
|
||||
// );
|
||||
// }
|
||||
// return collection;
|
||||
// }
|
||||
// case NewArrayExpression e when e.NodeType == ExpressionType.NewArrayInit && e.Expressions.Count > 0:
|
||||
// {
|
||||
// var collection = new List<object>(e.Expressions.Count);
|
||||
// foreach (var arrayItemExpression in e.Expressions)
|
||||
// {
|
||||
// collection.Add(GetShardingKeyValue(arrayItemExpression));
|
||||
// }
|
||||
// return collection;
|
||||
// }
|
||||
|
||||
|
||||
case MethodCallExpression e:
|
||||
return e.Method.Invoke(
|
||||
GetShardingKeyValue(e.Object),
|
||||
e.Arguments
|
||||
.Select(
|
||||
a => GetShardingKeyValue(a)
|
||||
)
|
||||
.ToArray()
|
||||
);
|
||||
// case MethodCallExpression e:
|
||||
// return e.Method.Invoke(
|
||||
// GetShardingKeyValue(e.Object),
|
||||
// e.Arguments
|
||||
// .Select(
|
||||
// a => GetShardingKeyValue(a)
|
||||
// )
|
||||
// .ToArray()
|
||||
// );
|
||||
|
||||
default:
|
||||
//TODO: better messaging
|
||||
throw new ShardingCoreException("cant get value " + expression);
|
||||
}
|
||||
//if (expression is ConstantExpression constantExpression)
|
||||
//{
|
||||
// return constantExpression.Value;
|
||||
//}
|
||||
//if (expression is UnaryExpression unaryExpression)
|
||||
//{
|
||||
// return Expression.Lambda(unaryExpression.Operand).Compile().DynamicInvoke();
|
||||
//}
|
||||
// default:
|
||||
// //TODO: better messaging
|
||||
// throw new ShardingCoreException("cant get value " + expression);
|
||||
// }
|
||||
// //if (expression is ConstantExpression constantExpression)
|
||||
// //{
|
||||
// // return constantExpression.Value;
|
||||
// //}
|
||||
// //if (expression is UnaryExpression unaryExpression)
|
||||
// //{
|
||||
// // return Expression.Lambda(unaryExpression.Operand).Compile().DynamicInvoke();
|
||||
// //}
|
||||
|
||||
//if (expression is MemberExpression member1Expression)
|
||||
//{
|
||||
// //if (expression is MemberExpression member1Expression)
|
||||
// //{
|
||||
|
||||
// if (member1Expression.Expression is ConstantExpression memberConstantExpression)
|
||||
// {
|
||||
// if (member1Expression.Member is FieldInfo memberFieldInfo)
|
||||
// {
|
||||
// object container = memberConstantExpression.Value;
|
||||
// return memberFieldInfo.GetValue(container);
|
||||
// }
|
||||
// if (member1Expression.Member is PropertyInfo memberPropertyInfo)
|
||||
// {
|
||||
// object container = memberConstantExpression.Value;
|
||||
// return memberPropertyInfo.GetValue(container);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return memberConstantExpression.Value;
|
||||
// }
|
||||
// }
|
||||
// return Expression.Lambda(member1Expression).Compile().DynamicInvoke();
|
||||
//}
|
||||
// // if (member1Expression.Expression is ConstantExpression memberConstantExpression)
|
||||
// // {
|
||||
// // if (member1Expression.Member is FieldInfo memberFieldInfo)
|
||||
// // {
|
||||
// // object container = memberConstantExpression.Value;
|
||||
// // return memberFieldInfo.GetValue(container);
|
||||
// // }
|
||||
// // if (member1Expression.Member is PropertyInfo memberPropertyInfo)
|
||||
// // {
|
||||
// // object container = memberConstantExpression.Value;
|
||||
// // return memberPropertyInfo.GetValue(container);
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // return memberConstantExpression.Value;
|
||||
// // }
|
||||
// // }
|
||||
// // return Expression.Lambda(member1Expression).Compile().DynamicInvoke();
|
||||
// //}
|
||||
|
||||
//if (expression is MethodCallExpression methodCallExpression)
|
||||
//{
|
||||
// return Expression.Lambda(methodCallExpression).Compile().DynamicInvoke();
|
||||
// //return methodCallExpression.Method.Invoke(
|
||||
// // GetShardingKeyValue(methodCallExpression.Object),
|
||||
// // methodCallExpression.Arguments
|
||||
// // .Select(
|
||||
// // a => GetShardingKeyValue(a)
|
||||
// // )
|
||||
// // .ToArray()
|
||||
// //);
|
||||
//}
|
||||
// //if (expression is MethodCallExpression methodCallExpression)
|
||||
// //{
|
||||
// // return Expression.Lambda(methodCallExpression).Compile().DynamicInvoke();
|
||||
// // //return methodCallExpression.Method.Invoke(
|
||||
// // // GetShardingKeyValue(methodCallExpression.Object),
|
||||
// // // methodCallExpression.Arguments
|
||||
// // // .Select(
|
||||
// // // a => GetShardingKeyValue(a)
|
||||
// // // )
|
||||
// // // .ToArray()
|
||||
// // //);
|
||||
// //}
|
||||
|
||||
//throw new ShardingCoreException("cant get value " + expression);
|
||||
}
|
||||
// //throw new ShardingCoreException("cant get value " + expression);
|
||||
//}
|
||||
|
||||
protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||
{
|
||||
|
@ -337,20 +337,20 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
{
|
||||
if (methodCallExpression.Object is MemberExpression member1Expression)
|
||||
{
|
||||
arrayObject = GetShardingKeyValue(member1Expression);
|
||||
arrayObject = GetExpressionValue(member1Expression);
|
||||
}
|
||||
else if (methodCallExpression.Object is ListInitExpression member2Expression)
|
||||
{
|
||||
arrayObject = GetShardingKeyValue(member2Expression);
|
||||
arrayObject = GetExpressionValue(member2Expression);
|
||||
}
|
||||
}
|
||||
else if (methodCallExpression.Arguments[0] is MemberExpression member2Expression)
|
||||
{
|
||||
arrayObject = GetShardingKeyValue(member2Expression);
|
||||
arrayObject = GetExpressionValue(member2Expression);
|
||||
}
|
||||
else if (methodCallExpression.Arguments[0] is NewArrayExpression member3Expression)
|
||||
{
|
||||
arrayObject = GetShardingKeyValue(member3Expression);
|
||||
arrayObject = GetExpressionValue(member3Expression);
|
||||
}
|
||||
|
||||
if (arrayObject != null)
|
||||
|
@ -418,11 +418,11 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
object shardingValue = default;
|
||||
if (methodCallExpression.Arguments[0] is MemberExpression member2Expression)
|
||||
{
|
||||
shardingValue = GetShardingKeyValue(member2Expression);
|
||||
shardingValue = GetExpressionValue(member2Expression);
|
||||
}
|
||||
else if (methodCallExpression.Arguments[0] is ConstantExpression constantExpression)
|
||||
{
|
||||
shardingValue = GetShardingKeyValue(constantExpression);
|
||||
shardingValue = GetExpressionValue(constantExpression);
|
||||
}
|
||||
|
||||
if (shardingValue != default)
|
||||
|
@ -477,7 +477,7 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
{
|
||||
conditionOnRight = true;
|
||||
shardingPropertyName = shardingPredicateResult.ShardingPropertyName;
|
||||
value = GetShardingKeyValue(binaryExpression.Right);
|
||||
value = GetExpressionValue(binaryExpression.Right);
|
||||
}
|
||||
else
|
||||
return x => true;
|
||||
|
@ -489,7 +489,7 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
{
|
||||
conditionOnRight = false;
|
||||
shardingPropertyName = shardingPredicateResult.ShardingPropertyName;
|
||||
value = GetShardingKeyValue(binaryExpression.Left);
|
||||
value = GetExpressionValue(binaryExpression.Left);
|
||||
}
|
||||
else
|
||||
return x => true;
|
||||
|
|
|
@ -8,18 +8,13 @@ namespace ShardingCore.Sharding.Visitors.Querys
|
|||
{
|
||||
public class CompileParseResult
|
||||
{
|
||||
public CompileParseResult(bool isUnion, bool? isNoTracking, bool isIgnoreFilter, ISet<Type> queryEntities)
|
||||
public CompileParseResult(bool? isNoTracking, bool isIgnoreFilter, ISet<Type> queryEntities)
|
||||
{
|
||||
IsUnion = isUnion;
|
||||
IsNoTracking = isNoTracking;
|
||||
IsIgnoreFilter = isIgnoreFilter;
|
||||
QueryEntities = queryEntities;
|
||||
}
|
||||
/// <summary>
|
||||
/// 是否使用了union查询
|
||||
/// </summary>
|
||||
public bool IsUnion { get; }
|
||||
/// <summary>
|
||||
/// 是否使用了追踪
|
||||
/// </summary>
|
||||
public bool? IsNoTracking { get; }
|
||||
|
|
|
@ -15,7 +15,6 @@ namespace ShardingCore.Sharding.Visitors.Querys
|
|||
internal class QueryCompileParseVisitors : ExpressionVisitor
|
||||
{
|
||||
private readonly ITrackerManager _trackerManager;
|
||||
private bool isUnion;
|
||||
private bool? isNoTracking;
|
||||
private bool isIgnoreFilter;
|
||||
private readonly ISet<Type> shardingEntities = new HashSet<Type>();
|
||||
|
@ -27,7 +26,7 @@ namespace ShardingCore.Sharding.Visitors.Querys
|
|||
|
||||
public CompileParseResult GetCompileParseResult()
|
||||
{
|
||||
return new CompileParseResult(isUnion, isNoTracking, isIgnoreFilter, shardingEntities);
|
||||
return new CompileParseResult(isNoTracking, isIgnoreFilter, shardingEntities);
|
||||
}
|
||||
#if EFCORE2 || EFCORE3
|
||||
protected override Expression VisitConstant(ConstantExpression node)
|
||||
|
@ -54,7 +53,6 @@ namespace ShardingCore.Sharding.Visitors.Querys
|
|||
{
|
||||
switch (node.Method.Name)
|
||||
{
|
||||
case nameof(Queryable.Union): isUnion = true; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.AsNoTracking): isNoTracking = true; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.AsTracking): isNoTracking = false; break;
|
||||
case nameof(EntityFrameworkQueryableExtensions.IgnoreQueryFilters): isIgnoreFilter = true; break;
|
||||
|
|
|
@ -8,7 +8,7 @@ using ShardingCore.Core.Internal.Visitors.Selects;
|
|||
|
||||
namespace ShardingCore.Sharding.Visitors.Selects
|
||||
{
|
||||
public class SelectAggregateProperty : SelectProperty
|
||||
public class SelectAggregateProperty : SelectOwnerProperty
|
||||
{
|
||||
public SelectAggregateProperty(Type ownerType, PropertyInfo property, bool isAggregateMethod, string aggregateMethod):base(ownerType, property)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace ShardingCore.Sharding.Visitors.Selects
|
|||
{
|
||||
public class SelectCountProperty:SelectAggregateProperty
|
||||
{
|
||||
|
||||
public SelectCountProperty(Type ownerType, PropertyInfo property, bool isAggregateMethod, string aggregateMethod) : base(ownerType, property, isAggregateMethod, aggregateMethod)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Sharding.Visitors.Selects;
|
||||
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:±í´ïselectÊôÐÔ
|
||||
* @Date: Tuesday, 02 February 2021 08:17:48
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
namespace ShardingCore.Core.Internal.Visitors.Selects
|
||||
{
|
||||
public class SelectOwnerProperty: SelectProperty
|
||||
{
|
||||
public SelectOwnerProperty(Type ownerType, PropertyInfo property) : base(property)
|
||||
{
|
||||
OwnerType = ownerType;
|
||||
Property = property;
|
||||
}
|
||||
public Type OwnerType { get; }
|
||||
public PropertyInfo Property { get; }
|
||||
public string PropertyName => Property.Name;
|
||||
}
|
||||
}
|
|
@ -1,23 +1,19 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/*
|
||||
* @Author: xjm
|
||||
* @Description:表达select属性
|
||||
* @Date: Tuesday, 02 February 2021 08:17:48
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
namespace ShardingCore.Core.Internal.Visitors.Selects
|
||||
namespace ShardingCore.Sharding.Visitors.Selects
|
||||
{
|
||||
public class SelectProperty
|
||||
{
|
||||
public SelectProperty(Type ownerType, PropertyInfo property)
|
||||
public SelectProperty( PropertyInfo property)
|
||||
{
|
||||
OwnerType = ownerType;
|
||||
Property = property;
|
||||
}
|
||||
public Type OwnerType { get; }
|
||||
public PropertyInfo Property { get; }
|
||||
public string PropertyName => Property.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Exceptions;
|
||||
|
||||
namespace ShardingCore.Core.Internal.Visitors
|
||||
|
@ -10,27 +13,92 @@ namespace ShardingCore.Core.Internal.Visitors
|
|||
* @Date: Wednesday, 13 January 2021 11:31:01
|
||||
* @Email: 326308290@qq.com
|
||||
*/
|
||||
internal abstract class ShardingExpressionVisitor:ExpressionVisitor
|
||||
public abstract class ShardingExpressionVisitor:ExpressionVisitor
|
||||
{
|
||||
|
||||
public object GetFieldValue(Expression expression)
|
||||
//public object GetFieldValue(Expression expression)
|
||||
//{
|
||||
// if (expression is ConstantExpression)
|
||||
// return (expression as ConstantExpression).Value;
|
||||
// if (expression is UnaryExpression)
|
||||
// {
|
||||
// UnaryExpression unary = expression as UnaryExpression;
|
||||
// LambdaExpression lambda = Expression.Lambda(unary.Operand);
|
||||
// Delegate fn = lambda.Compile();
|
||||
// return fn.DynamicInvoke(null);
|
||||
// }
|
||||
|
||||
// if (expression is MemberExpression member1Expression)
|
||||
// {
|
||||
// return Expression.Lambda(member1Expression).Compile().DynamicInvoke();
|
||||
// }
|
||||
|
||||
// throw new ShardingCoreException("cant get value " + expression);
|
||||
//}
|
||||
protected object GetExpressionValue(Expression expression)
|
||||
{
|
||||
if (expression is ConstantExpression)
|
||||
return (expression as ConstantExpression).Value;
|
||||
if (expression is UnaryExpression)
|
||||
if (expression == null)
|
||||
return null;
|
||||
switch (expression)
|
||||
{
|
||||
UnaryExpression unary = expression as UnaryExpression;
|
||||
LambdaExpression lambda = Expression.Lambda(unary.Operand);
|
||||
Delegate fn = lambda.Compile();
|
||||
return fn.DynamicInvoke(null);
|
||||
}
|
||||
case ConstantExpression e:
|
||||
return e.Value;
|
||||
|
||||
if (expression is MemberExpression member1Expression)
|
||||
{
|
||||
return Expression.Lambda(member1Expression).Compile().DynamicInvoke();
|
||||
}
|
||||
case MemberExpression e when e.Member is FieldInfo field:
|
||||
return field.GetValue(
|
||||
GetExpressionValue(
|
||||
e.Expression
|
||||
)
|
||||
);
|
||||
|
||||
throw new ShardingCoreException("cant get value " + expression);
|
||||
case MemberExpression e when e.Member is PropertyInfo property:
|
||||
return property.GetValue(
|
||||
GetExpressionValue(
|
||||
e.Expression
|
||||
)
|
||||
);
|
||||
|
||||
case ListInitExpression e when e.NewExpression.Arguments.Count() == 0:
|
||||
{
|
||||
var collection = e.NewExpression.Constructor.Invoke(new object[0]);
|
||||
foreach (var i in e.Initializers)
|
||||
{
|
||||
i.AddMethod.Invoke(
|
||||
collection,
|
||||
i.Arguments
|
||||
.Select(
|
||||
a => GetExpressionValue(a)
|
||||
)
|
||||
.ToArray()
|
||||
);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
case NewArrayExpression e when e.NodeType == ExpressionType.NewArrayInit && e.Expressions.Count > 0:
|
||||
{
|
||||
var collection = new List<object>(e.Expressions.Count);
|
||||
foreach (var arrayItemExpression in e.Expressions)
|
||||
{
|
||||
collection.Add(GetExpressionValue(arrayItemExpression));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
case MethodCallExpression e:
|
||||
return e.Method.Invoke(
|
||||
GetExpressionValue(e.Object),
|
||||
e.Arguments
|
||||
.Select(
|
||||
a => GetExpressionValue(a)
|
||||
)
|
||||
.ToArray()
|
||||
);
|
||||
|
||||
default:
|
||||
//TODO: better messaging
|
||||
throw new ShardingCoreException("cant get value " + expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using ShardingCore.Core.EntityMetadatas;
|
||||
using ShardingCore.Core.TrackerManagers;
|
||||
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||
|
||||
namespace ShardingCore
|
||||
{
|
||||
|
@ -160,5 +162,15 @@ namespace ShardingCore
|
|||
{
|
||||
return (IEntityMetadataManager<TShardingDbContext>)GetRequiredEntityMetadataManager(typeof(TShardingDbContext));
|
||||
}
|
||||
|
||||
public static ITrackerManager GetTrackerManager(Type shardingDbContextType)
|
||||
{
|
||||
return (ITrackerManager)ServiceProvider.GetService(typeof(ITrackerManager<>).GetGenericType0(shardingDbContextType));
|
||||
}
|
||||
|
||||
public static IVirtualTableManager GetVirtualTableManager(Type shardingDbContextType)
|
||||
{
|
||||
return (IVirtualTableManager)ServiceProvider.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContextType));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<DefineConstants>TRACE;DEBUG;EFCORE6;</DefineConstants>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<RepositoryUrl>https://github.com/xuejmnet/sharding-core</RepositoryUrl>
|
||||
<RepositoryUrl>https://github.com/dotnetcore/sharding-core</RepositoryUrl>
|
||||
<PackageIcon>logo.png</PackageIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
|
@ -16,6 +16,11 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<LangVersion>latest</LangVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="Sharding\Abstractions\MergeParseContexts\**" />
|
||||
<EmbeddedResource Remove="Sharding\Abstractions\MergeParseContexts\**" />
|
||||
<None Remove="Sharding\Abstractions\MergeParseContexts\**" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\Logo\logo.png">
|
||||
<Pack>True</Pack>
|
||||
|
@ -24,12 +29,11 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Sharding\Abstractions\MergeParseContexts" />
|
||||
<Folder Include="Sharding\Visitors\GroupBys" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails;
|
||||
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||
using ShardingCore.Sharding.Abstractions;
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace ShardingCore.TableExists.Abstractions
|
||||
{
|
||||
|
|
|
@ -64,8 +64,8 @@ namespace ShardingCore.Test
|
|||
IVirtualDataSourceManager<ShardingDefaultDbContext> virtualDataSourceManager,
|
||||
IVirtualTableManager<ShardingDefaultDbContext> virtualTableManager,
|
||||
IShardingTableCreator<ShardingDefaultDbContext> shardingTableCreator,
|
||||
IShardingReadWriteManager shardingReadWriteManager,IRouteTailFactory routeTailFactory,
|
||||
IReadWriteConnectorFactory readWriteConnectorFactory,ITableRouteRuleEngineFactory<ShardingDefaultDbContext> tableRouteRuleEngineFactory)
|
||||
IShardingReadWriteManager shardingReadWriteManager, IRouteTailFactory routeTailFactory,
|
||||
IReadWriteConnectorFactory readWriteConnectorFactory, ITableRouteRuleEngineFactory<ShardingDefaultDbContext> tableRouteRuleEngineFactory)
|
||||
{
|
||||
_virtualDbContext = virtualDbContext;
|
||||
_shardingRouteManager = shardingRouteManager;
|
||||
|
@ -91,29 +91,29 @@ namespace ShardingCore.Test
|
|||
var xxxx = "202102";
|
||||
var queryable1 = _virtualDbContext.Set<SysUserSalary>().Where(o => o.DateOfMonth >= 202102);
|
||||
var routeParseExpression1 = ShardingUtil.GetRouteParseExpression(queryable1, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var queryable2 = _virtualDbContext.Set<SysUserSalary>().Where(ox => ox.DateOfMonth >= 202102);
|
||||
var routeParseExpression2 = ShardingUtil.GetRouteParseExpression(queryable2, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var xxxx1 = 202102;
|
||||
var queryable3 = _virtualDbContext.Set<SysUserSalary>().Where(ox => ox.DateOfMonth >= xxxx1);
|
||||
var routeParseExpression3 = ShardingUtil.GetRouteParseExpression(queryable3, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var queryable4 = _virtualDbContext.Set<SysUserSalary>().Where(o => o.DateOfMonth >= 202101);
|
||||
var routeParseExpression4 = ShardingUtil.GetRouteParseExpression(queryable4, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var queryable5 = _virtualDbContext.Set<SysUserSalary>().Where(o => o.DateOfMonth > 202101);
|
||||
var routeParseExpression5 = ShardingUtil.GetRouteParseExpression(queryable5, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var queryable6 = _virtualDbContext.Set<SysUserSalary>().Where(o => o.DateOfMonth == 202101);
|
||||
var routeParseExpression6 = ShardingUtil.GetRouteParseExpression(queryable6, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var queryable7 = _virtualDbContext.Set<SysUserSalary>().Where(o => 202101 <= o.DateOfMonth);
|
||||
var routeParseExpression7 = ShardingUtil.GetRouteParseExpression(queryable7, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
var queryable8 = _virtualDbContext.Set<SysUserSalary>().Where(o => 202101 == o.DateOfMonth);
|
||||
var routeParseExpression8 = ShardingUtil.GetRouteParseExpression(queryable8, virtualTableRoute.EntityMetadata,
|
||||
(i, op,propertyName) => virtualTableRoute.GetRouteFilter(i, op,propertyName), true);
|
||||
(i, op, propertyName) => virtualTableRoute.GetRouteFilter(i, op, propertyName), true);
|
||||
Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression2));
|
||||
Assert.Equal(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression3));
|
||||
Assert.NotEqual(expressionEqualityComparer.GetHashCode(routeParseExpression1), expressionEqualityComparer.GetHashCode(routeParseExpression4));
|
||||
|
@ -130,14 +130,14 @@ namespace ShardingCore.Test
|
|||
var a = new DefaultPhysicDataSource("aaa", "aaa", true);
|
||||
var b = new DefaultPhysicDataSource("aaa", "aaa1", false);
|
||||
Assert.Equal(a, b);
|
||||
var x = new EntityMetadata(typeof(LogDay), "aa", typeof(ShardingDefaultDbContext), new List<PropertyInfo>(),null);
|
||||
var y = new EntityMetadata(typeof(LogDay), "aa1", typeof(ShardingDefaultDbContext), new List<PropertyInfo>(),null);
|
||||
var x = new EntityMetadata(typeof(LogDay), "aa", typeof(ShardingDefaultDbContext), new List<PropertyInfo>(), null);
|
||||
var y = new EntityMetadata(typeof(LogDay), "aa1", typeof(ShardingDefaultDbContext), new List<PropertyInfo>(), null);
|
||||
Assert.Equal(x, y);
|
||||
var dateTime = new DateTime(2021, 1, 1);
|
||||
var logDays = Enumerable.Range(0, 100).Select(o => new LogDay() { Id = Guid.NewGuid(), LogLevel = "info", LogBody = o.ToString(), LogTime = dateTime.AddDays(o) }).ToList();
|
||||
|
||||
var bulkShardingTableEnumerable = _virtualDbContext.BulkShardingTableEnumerable(logDays);
|
||||
|
||||
|
||||
Assert.Equal(100, bulkShardingTableEnumerable.Count);
|
||||
var bulkShardingEnumerable = _virtualDbContext.BulkShardingEnumerable(logDays);
|
||||
Assert.Equal(1, bulkShardingEnumerable.Count);
|
||||
|
@ -191,7 +191,7 @@ namespace ShardingCore.Test
|
|||
Assert.True(bulkShardingExpression.ContainsKey("B"));
|
||||
|
||||
var bulkShardingTableExpression = _virtualDbContext.BulkShardingTableExpression<ShardingDefaultDbContext, SysUserMod>(o => o.Id == Guid.NewGuid().ToString());
|
||||
|
||||
|
||||
Assert.Equal(1, bulkShardingTableExpression.Count());
|
||||
|
||||
var noShardingExpression = _virtualDbContext.BulkShardingExpression<ShardingDefaultDbContext, LogNoSharding>(o => o.Id == "123");
|
||||
|
@ -210,12 +210,12 @@ namespace ShardingCore.Test
|
|||
var emptyTailIdentity = new SingleQueryRouteTail(string.Empty).GetRouteTailIdentity();
|
||||
var aTailIdentity = new SingleQueryRouteTail("a").GetRouteTailIdentity();
|
||||
var bTailIdentity = new SingleQueryRouteTail("b").GetRouteTailIdentity();
|
||||
var dics=new SortedDictionary<string, string>(new NoShardingFirstComparer());
|
||||
var dicTails=new List<string>() { emptyTailIdentity, aTailIdentity, bTailIdentity };
|
||||
var dics = new SortedDictionary<string, string>(new NoShardingFirstComparer());
|
||||
var dicTails = new List<string>() { emptyTailIdentity, aTailIdentity, bTailIdentity };
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
dics.Clear();
|
||||
var reOrderList=dicTails.OrderBy(o => Guid.NewGuid()).ToList();
|
||||
var reOrderList = dicTails.OrderBy(o => Guid.NewGuid()).ToList();
|
||||
foreach (var tail in reOrderList)
|
||||
{
|
||||
dics.Add(tail, null);
|
||||
|
@ -232,7 +232,7 @@ namespace ShardingCore.Test
|
|||
var succeedAddConnectionString = _shardingConnectionStringResolver.AddConnectionString("X", "Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;");
|
||||
Assert.True(succeedAddConnectionString);
|
||||
var connectionString = _shardingConnectionStringResolver.GetConnectionString("X");
|
||||
Assert.Equal("Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;",connectionString);
|
||||
Assert.Equal("Data Source=localhost;Initial Catalog=ShardingCoreDBC;Integrated Security=True;", connectionString);
|
||||
}
|
||||
|
||||
public class SequenceClass
|
||||
|
@ -381,16 +381,16 @@ namespace ShardingCore.Test
|
|||
public async Task ToList_Join_Test()
|
||||
{
|
||||
var list111 = await (from u in _virtualDbContext.Set<SysUserMod>()
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>()
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
u.Id,
|
||||
u.Age,
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
}).CountAsync();
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>()
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
u.Id,
|
||||
u.Age,
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
}).CountAsync();
|
||||
var list = await (from u in _virtualDbContext.Set<SysUserMod>()
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>()
|
||||
on u.Id equals salary.UserId
|
||||
|
@ -422,22 +422,22 @@ namespace ShardingCore.Test
|
|||
Assert.DoesNotContain(list1, o => o.Name != "name_300");
|
||||
|
||||
var queryable1 = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>().Where(o=>o.DateOfMonth==202005)
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
});
|
||||
join salary in _virtualDbContext.Set<SysUserSalary>().Where(o => o.DateOfMonth == 202005)
|
||||
on u.Id equals salary.UserId
|
||||
select new
|
||||
{
|
||||
Salary = salary.Salary,
|
||||
DateOfMonth = salary.DateOfMonth,
|
||||
Name = u.Name
|
||||
});
|
||||
var list3 = await queryable1.ToListAsync();
|
||||
Assert.Equal(1, list3.Count());
|
||||
Assert.Contains(list3, o => o.Name == "name_300");
|
||||
var firstOrDefaultAsync =await queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefaultAsync();
|
||||
var firstOrDefaultAsync = await queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefaultAsync();
|
||||
Assert.NotNull(firstOrDefaultAsync);
|
||||
var firstOrDefault = queryable1.OrderBy(o => o.DateOfMonth).FirstOrDefault();
|
||||
Assert.NotNull(firstOrDefault);
|
||||
Assert.Equal(firstOrDefaultAsync,firstOrDefault);
|
||||
Assert.Equal(firstOrDefaultAsync, firstOrDefault);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
@ -489,12 +489,12 @@ namespace ShardingCore.Test
|
|||
[Fact]
|
||||
public async Task ToList_Id_Not_Eq_Test()
|
||||
{
|
||||
var methodValue = new MethodValue(){AA = "7"};
|
||||
var mods123 = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id== methodValue.GetAa()).FirstOrDefaultAsync();
|
||||
var methodValue = new MethodValue() { AA = "7" };
|
||||
var mods123 = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == methodValue.GetAa()).FirstOrDefaultAsync();
|
||||
Assert.NotNull(mods123);
|
||||
Assert.Equal(mods123.Id,"7");
|
||||
var mods12 = await _virtualDbContext.Set<SysUserMod>().Where(o => new List<string>{"3","4"}.Contains(o.Id) ).ToListAsync();
|
||||
Assert.Contains(mods12, o => o.Id == "3"||o.Id=="4");
|
||||
Assert.Equal(mods123.Id, "7");
|
||||
var mods12 = await _virtualDbContext.Set<SysUserMod>().Where(o => new List<string> { "3", "4" }.Contains(o.Id)).ToListAsync();
|
||||
Assert.Contains(mods12, o => o.Id == "3" || o.Id == "4");
|
||||
var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").ToListAsync();
|
||||
Assert.Equal(999, mods.Count);
|
||||
Assert.DoesNotContain(mods, o => o.Id == "3");
|
||||
|
@ -578,8 +578,8 @@ namespace ShardingCore.Test
|
|||
var next = "1";
|
||||
var sysUserMod1 = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == next).FirstOrDefaultAsync();
|
||||
var sysUserModabxxx = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2").FirstOrDefaultAsync();
|
||||
var sysUserModabxxx11 = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2"|| o.Name == "name_3").FirstOrDefaultAsync();
|
||||
var x=new Object [] { "1", "2" };
|
||||
var sysUserModabxxx11 = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2" || o.Name == "name_3").FirstOrDefaultAsync();
|
||||
var x = new Object[] { "1", "2" };
|
||||
var sysUserModab = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id.Equals("1")).FirstOrDefaultAsync();
|
||||
Assert.NotNull(sysUserModab);
|
||||
Assert.True(sysUserModab.Id == "1");
|
||||
|
@ -590,9 +590,9 @@ namespace ShardingCore.Test
|
|||
Assert.NotNull(sysUserMod);
|
||||
Assert.True(sysUserMod.Id == "1");
|
||||
Assert.Equal(sysUserModaa, sysUserMod);
|
||||
var sysUserModxx = await _virtualDbContext.Set<SysUserMod>().Where(o =>x.Contains(o.Id)).FirstOrDefaultAsync();
|
||||
var sysUserModxx = await _virtualDbContext.Set<SysUserMod>().Where(o => x.Contains(o.Id)).FirstOrDefaultAsync();
|
||||
Assert.NotNull(sysUserModxx);
|
||||
Assert.True(x.Contains(sysUserModxx.Id) );
|
||||
Assert.True(x.Contains(sysUserModxx.Id));
|
||||
Assert.NotNull(sysUserMod);
|
||||
var userMod = _virtualDbContext.Set<SysUserMod>().Find("1");
|
||||
Assert.Equal(sysUserMod, userMod);
|
||||
|
@ -736,6 +736,49 @@ namespace ShardingCore.Test
|
|||
Assert.Equal(1120000, group[0].MinSalary);
|
||||
Assert.Equal(1140000, group[0].MaxSalary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Group_Test1()
|
||||
{
|
||||
var ids = new[] { "200", "300" };
|
||||
var dateOfMonths = new[] { 202111, 202110 };
|
||||
var dateTime = DateTime.Now;
|
||||
|
||||
var sql = from u in _virtualDbContext.Set<SysUserSalary>()
|
||||
group u by u.UserId
|
||||
into g
|
||||
select new
|
||||
{
|
||||
UI = g.Key,
|
||||
x=g.Sum(o=>o.SalaryDecimal),
|
||||
Now = dateTime
|
||||
};
|
||||
var listAsync = await sql.ToListAsync();
|
||||
var group = await (from u in _virtualDbContext.Set<SysUserSalary>()
|
||||
.Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
|
||||
group u by new
|
||||
{
|
||||
UId = u.UserId
|
||||
}
|
||||
into g
|
||||
select new
|
||||
{
|
||||
GroupUserId = g.Key.UId,
|
||||
Count = g.Count(),
|
||||
TotalSalary = g.Sum(o => o.Salary),
|
||||
AvgSalary = g.Average(o => o.Salary),
|
||||
AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
|
||||
MinSalary = g.Min(o => o.Salary),
|
||||
MaxSalary = g.Max(o => o.Salary)
|
||||
}).ToListAsync();
|
||||
Assert.Equal(2, group.Count);
|
||||
Assert.Equal(2, group[0].Count);
|
||||
Assert.Equal(2260000, group[0].TotalSalary);
|
||||
Assert.Equal(1130000, group[0].AvgSalary);
|
||||
Assert.Equal(11300, group[0].AvgSalaryDecimal);
|
||||
Assert.Equal(1120000, group[0].MinSalary);
|
||||
Assert.Equal(1140000, group[0].MaxSalary);
|
||||
}
|
||||
//[Fact]
|
||||
//public async Task Group_Recently_Test()
|
||||
//{
|
||||
|
@ -1401,29 +1444,29 @@ namespace ShardingCore.Test
|
|||
await tran.RollbackAsync();
|
||||
}
|
||||
}
|
||||
logNoSharding.Body = DateTime.Now.ToString("yyyyMMdd");
|
||||
_virtualDbContext.Update(logNoSharding);
|
||||
logNoSharding.Body = DateTime.Now.ToString("yyyyMMdd");
|
||||
_virtualDbContext.Update(logNoSharding);
|
||||
|
||||
logNoShardings.ForEach(o=>o.Body = DateTime.Now.ToString("yyyyMMdd"));
|
||||
_virtualDbContext.UpdateRange(logNoShardings);
|
||||
logNoShardings.ForEach(o => o.Body = DateTime.Now.ToString("yyyyMMdd"));
|
||||
_virtualDbContext.UpdateRange(logNoShardings);
|
||||
|
||||
logNoSharding1.Body = DateTime.Now.ToString("yyyyMMdd");
|
||||
_virtualDbContext.Set<LogNoSharding>().Update(logNoSharding1);
|
||||
logNoSharding1.Body = DateTime.Now.ToString("yyyyMMdd");
|
||||
_virtualDbContext.Set<LogNoSharding>().Update(logNoSharding1);
|
||||
|
||||
logNoSharding1s.ForEach(o=>o.Body = DateTime.Now.ToString("yyyyMMdd"));
|
||||
_virtualDbContext.Set<LogNoSharding>().UpdateRange(logNoSharding1s);
|
||||
await _virtualDbContext.SaveChangesAsync();
|
||||
logNoSharding1s.ForEach(o => o.Body = DateTime.Now.ToString("yyyyMMdd"));
|
||||
_virtualDbContext.Set<LogNoSharding>().UpdateRange(logNoSharding1s);
|
||||
await _virtualDbContext.SaveChangesAsync();
|
||||
|
||||
|
||||
_virtualDbContext.Remove(logNoSharding);
|
||||
_virtualDbContext.Remove(logNoSharding);
|
||||
|
||||
_virtualDbContext.RemoveRange(logNoShardings);
|
||||
_virtualDbContext.RemoveRange(logNoShardings);
|
||||
|
||||
_virtualDbContext.Set<LogNoSharding>().Remove(logNoSharding1);
|
||||
_virtualDbContext.Set<LogNoSharding>().Remove(logNoSharding1);
|
||||
|
||||
logNoSharding1s.ForEach(o => o.Body = DateTime.Now.ToString("yyyyMMdd"));
|
||||
_virtualDbContext.Set<LogNoSharding>().RemoveRange(logNoSharding1s);
|
||||
await _virtualDbContext.SaveChangesAsync();
|
||||
logNoSharding1s.ForEach(o => o.Body = DateTime.Now.ToString("yyyyMMdd"));
|
||||
_virtualDbContext.Set<LogNoSharding>().RemoveRange(logNoSharding1s);
|
||||
await _virtualDbContext.SaveChangesAsync();
|
||||
}
|
||||
[Fact]
|
||||
public async Task CrudTest1()
|
||||
|
@ -1457,7 +1500,7 @@ namespace ShardingCore.Test
|
|||
{
|
||||
await _virtualDbContext.AddAsync((object)logNoSharding);
|
||||
|
||||
await _virtualDbContext.AddRangeAsync(logNoShardings.Select(o=>(object)o).ToArray());
|
||||
await _virtualDbContext.AddRangeAsync(logNoShardings.Select(o => (object)o).ToArray());
|
||||
|
||||
await _virtualDbContext.SaveChangesAsync();
|
||||
await tran.CommitAsync();
|
||||
|
|
Loading…
Reference in New Issue