[#128 ]修复没有主键时的错误,[#127]修复查询排序属性未出现在select上的null错误提示.[#124]修复bug,[#125],[#121]

This commit is contained in:
xuejiaming 2022-03-04 15:35:30 +08:00
parent 60042f2597
commit 947d70f537
78 changed files with 1471 additions and 826 deletions

View File

@ -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

View File

@ -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]

View File

@ -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));

View File

@ -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>

View File

@ -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();
}
}
}

View File

@ -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>(); ;
}
}
}

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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}");
//设置标签

View File

@ -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))

View File

@ -1,9 +0,0 @@
using ShardingCore.Core.CustomerDatabaseProcessers;
namespace ShardingCore.Core.NotSupportShardingProviders.Abstractions
{
public interface INotSupportAccessor
{
NotSupportContext SqlSupportContext { get; set; }
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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);
}

View File

@ -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);
}
}
}

View File

@ -0,0 +1,7 @@
namespace ShardingCore.Core.UnionAllMergeShardingProviders.Abstractions
{
public interface IUnionAllMergeAccessor
{
UnionAllMergeContext SqlSupportContext { get; set; }
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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; }
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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,

View File

@ -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
}

View File

@ -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;

View File

@ -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();

View File

@ -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)

View File

@ -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;
}
}
}

View File

@ -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
{

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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
{
}
}

View File

@ -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
{
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}
}

View File

@ -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
{
}
}

View File

@ -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()
{

View File

@ -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]]

View File

@ -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)

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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()
{

View File

@ -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()

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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; }

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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));
}
}
}

View File

@ -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>

View File

@ -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
{

View File

@ -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();