support join multi entity query pass unit test

This commit is contained in:
xuejmnet 2021-08-22 16:43:26 +08:00
parent cb5b32c441
commit 2b4eaa6bd9
44 changed files with 739 additions and 492 deletions

2
.gitignore vendored
View File

@ -343,4 +343,4 @@ healthchecksdb
/src/Bd.ShopRent.Api/Properties/launchSettings.json /src/Bd.ShopRent.Api/Properties/launchSettings.json
/src/Bd.ShopRent.DTO/__autoDTOConfig.json /src/Bd.ShopRent.DTO/__autoDTOConfig.json
/src/Bd.ShopRent.DTO/Bd.ShopRent.Dto.csproj /src/Bd.ShopRent.DTO/Bd.ShopRent.Dto.csproj
Configs/DbConfig.json /test/ShardingCore.Test50/Configs/*

View File

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Sample.MySql.Domain.Maps; using Sample.MySql.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -21,6 +22,6 @@ namespace Sample.MySql.DbContexts
modelBuilder.ApplyConfiguration(new SysUserLogByMonthMap()); modelBuilder.ApplyConfiguration(new SysUserLogByMonthMap());
} }
public string ModelChangeKey { get; set; } public IRouteTail RouteTail { get; set; }
} }
} }

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Sample.SqlServer.Domain.Maps; using Sample.SqlServer.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -23,6 +24,6 @@ namespace Sample.SqlServer.DbContexts
modelBuilder.ApplyConfiguration(new SysTestMap()); modelBuilder.ApplyConfiguration(new SysTestMap());
} }
public string ModelChangeKey { get; set; } public IRouteTail RouteTail { get; set; }
} }
} }

View File

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Sample.SqlServer3x.Domain.Maps; using Sample.SqlServer3x.Domain.Maps;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -25,6 +26,6 @@ namespace Sample.SqlServer3x
modelBuilder.ApplyConfiguration(new SysUserModMap()); modelBuilder.ApplyConfiguration(new SysUserModMap());
} }
public string ModelChangeKey { get; set; } public IRouteTail RouteTail { get; set; }
} }
} }

View File

@ -10,10 +10,12 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage;
using ShardingCore; using ShardingCore;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables; using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts; using ShardingCore.DbContexts;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -21,9 +23,11 @@ namespace Samples.AbpSharding
{ {
public abstract class AbstractShardingAbpDbContext<T> : AbpDbContext, IShardingTableDbContext<T> where T : AbpDbContext, IShardingTableDbContext public abstract class AbstractShardingAbpDbContext<T> : AbpDbContext, IShardingTableDbContext<T> where T : AbpDbContext, IShardingTableDbContext
{ {
private readonly string EMPTY_SHARDING_TAIL_ID = ShardingConstant.EMPTY_SHARDING_TAIL_ID + Guid.NewGuid().ToString("n");
private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>(); private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>();
private readonly IVirtualTableManager _virtualTableManager; private readonly IVirtualTableManager _virtualTableManager;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IShardingDbContextFactory _shardingDbContextFactory;
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig; private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
private DbContextOptions<T> _dbContextOptions; private DbContextOptions<T> _dbContextOptions;
@ -34,6 +38,7 @@ namespace Samples.AbpSharding
{ {
_shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory>(); _shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>(); _virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
_shardingDbContextOptionsBuilderConfig = ShardingContainer _shardingDbContextOptionsBuilderConfig = ShardingContainer
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>() .GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType); .FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType);
@ -47,7 +52,7 @@ namespace Samples.AbpSharding
{ {
Type type = typeof(DbContextOptionsBuilder<>); Type type = typeof(DbContextOptionsBuilder<>);
type = type.MakeGenericType(ActualDbContextType); type = type.MakeGenericType(ActualDbContextType);
return (DbContextOptionsBuilder<T>)Activator.CreateInstance(type); return (DbContextOptionsBuilder<T>) Activator.CreateInstance(type);
} }
private DbContextOptions<T> CreateShareDbContextOptions() private DbContextOptions<T> CreateShareDbContextOptions()
@ -64,7 +69,7 @@ namespace Samples.AbpSharding
return dbContextOptionBuilder.Options; return dbContextOptionBuilder.Options;
} }
private ShardingDbContextOptions GetShareShardingDbContextOptions(string tail) private ShardingDbContextOptions GetShareShardingDbContextOptions(IRouteTail routeTail)
{ {
if (_dbContextOptions == null) if (_dbContextOptions == null)
{ {
@ -77,30 +82,34 @@ namespace Samples.AbpSharding
} }
} }
return new ShardingDbContextOptions(_dbContextOptions, tail); return new ShardingDbContextOptions(_dbContextOptions, routeTail);
} }
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(string tail) private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(IRouteTail routeTail)
{ {
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), tail); return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), routeTail);
} }
public DbContext GetDbContext(bool track, string tail) public DbContext GetDbContext(bool track, IRouteTail routeTail)
{ {
if (track) if (track)
{ {
if (!_dbContextCaches.TryGetValue(tail, out var dbContext)) if (routeTail.IsMultiEntityQuery())
throw new ShardingCoreException("multi route not support track");
if(!(routeTail is ISingleQueryRouteTail singleQueryRouteTail))
throw new ShardingCoreException("multi route not support track");
var cacheKey = routeTail.GetRouteTailIdenty();
if (!_dbContextCaches.TryGetValue(cacheKey, out var dbContext))
{ {
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail)); dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(routeTail));
_dbContextCaches.TryAdd(tail, dbContext); _dbContextCaches.TryAdd(cacheKey, dbContext);
} }
return dbContext; return dbContext;
} }
else else
{ {
var dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail)); return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(routeTail));
return dbContext;
} }
} }
@ -108,17 +117,15 @@ namespace Samples.AbpSharding
public DbContext CreateGenericDbContext<T>(T entity) where T : class public DbContext CreateGenericDbContext<T>(T entity) where T : class
{ {
var tail = EMPTY_SHARDING_TAIL_ID; var tail = string.Empty;
if (entity.IsShardingTable()) if (entity.IsShardingTable())
{ {
var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0]; var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0];
tail = physicTable.Tail; tail = physicTable.Tail;
} }
return GetDbContext(true, tail); return GetDbContext(true, _routeTailFactory.Create(tail));
} }
public override EntityEntry Add(object entity) public override EntityEntry Add(object entity)
{ {
return CreateGenericDbContext(entity).Add(entity); return CreateGenericDbContext(entity).Add(entity);

View File

@ -13,7 +13,6 @@ namespace ShardingCore.Core
*/ */
public class ShardingConstant public class ShardingConstant
{ {
public const string EMPTY_SHARDING_TAIL_ID = "EMPTY_SHARDING_TAIL_ID";
public const string MULTI_ENTITIES_QUERY = "MULTI_ENTITIES_QUERY"; public const string MULTI_ENTITIES_QUERY = "MULTI_ENTITIES_QUERY";
} }
} }

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:44:54
* @Email: 326308290@qq.com
*/
public interface IMultiQueryRouteTail:IRouteTail
{
/// <summary>
/// 获取对象类型的应该后缀
/// </summary>
/// <param name="entityType"></param>
/// <returns></returns>
string GetEntityTail(Type entityType);
ISet<Type> GetEntityTypes();
}
}

View File

@ -0,0 +1,16 @@
using System;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:39:19
* @Email: 326308290@qq.com
*/
public interface IRouteTail
{
string GetRouteTailIdenty();
bool IsMultiEntityQuery();
}
}

View File

@ -0,0 +1,17 @@
using System;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 14:58:19
* @Email: 326308290@qq.com
*/
public interface IRouteTailFactory
{
IRouteTail Create(string tail);
IRouteTail Create(RouteResult routeResult);
}
}

View File

@ -0,0 +1,19 @@
using System;
namespace ShardingCore.Core.VirtualRoutes.Abstractions
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:44:22
* @Email: 326308290@qq.com
*/
public interface ISingleQueryRouteTail:IRouteTail
{
/// <summary>
/// 获取当前查询的后缀
/// </summary>
/// <returns></returns>
string GetTail();
}
}

View File

@ -0,0 +1,32 @@
using System;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.RouteTails;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 14:58:58
* @Email: 326308290@qq.com
*/
public class RouteTailFactory:IRouteTailFactory
{
public IRouteTail Create(string tail)
{
return new SingleQueryRouteTail(tail);
}
public IRouteTail Create(RouteResult routeResult)
{
if (routeResult == null || routeResult.ReplaceTables.IsEmpty())
throw new ShardingCoreException("route result null or empty");
if (routeResult.ReplaceTables.Count == 1)
return new SingleQueryRouteTail(routeResult);
return new MultiQueryRouteTail(routeResult);
}
}
}

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes.RouteTails
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:59:22
* @Email: 326308290@qq.com
*/
public class MultiQueryRouteTail:IMultiQueryRouteTail
{
private const string RANDOM_MODEL_CACHE_KEY = "RANDOM_MODEL_CACHE_KEY";
private readonly RouteResult _routeResult;
private readonly string _modelCacheKey;
private readonly ISet<Type> _entityTypes;
public MultiQueryRouteTail(RouteResult routeResult)
{
if (routeResult.ReplaceTables.IsEmpty() || routeResult.ReplaceTables.Count <= 1) throw new ArgumentException("route result replace tables must greater than 1");
_routeResult = routeResult;
_modelCacheKey = RANDOM_MODEL_CACHE_KEY+Guid.NewGuid().ToString("n");
_entityTypes = routeResult.ReplaceTables.Select(o=>o.EntityType).ToHashSet();
}
public string GetRouteTailIdenty()
{
return _modelCacheKey;
}
public bool IsMultiEntityQuery()
{
return true;
}
public string GetEntityTail(Type entityType)
{
return _routeResult.ReplaceTables.Single(o => o.EntityType == entityType).Tail;
}
public ISet<Type> GetEntityTypes()
{
return _entityTypes;
}
}
}

View File

@ -0,0 +1,49 @@
using System;
using System.Linq;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Extensions;
namespace ShardingCore.Core.VirtualRoutes.RouteTails
{
/*
* @Author: xjm
* @Description:
* @Date: Sunday, 22 August 2021 09:46:07
* @Email: 326308290@qq.com
*/
public class SingleQueryRouteTail:ISingleQueryRouteTail
{
private readonly RouteResult _routeResult;
private readonly string _tail;
private readonly string _modelCacheKey;
public SingleQueryRouteTail(RouteResult routeResult)
{
if (routeResult.ReplaceTables.IsEmpty() || routeResult.ReplaceTables.Count > 1) throw new ArgumentException("route result replace tables must 1");
_routeResult = routeResult;
_tail= _routeResult.ReplaceTables.First().Tail;
_modelCacheKey = _tail.FormatRouteTail2ModelCacheKey();
}
public SingleQueryRouteTail(string tail)
{
_tail= tail;
_modelCacheKey = _tail.FormatRouteTail2ModelCacheKey();
}
public virtual string GetRouteTailIdenty()
{
return _modelCacheKey;
}
public virtual bool IsMultiEntityQuery()
{
return false;
}
public virtual string GetTail()
{
return _tail;
}
}
}

View File

@ -91,8 +91,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
//} //}
} }
private bool EnableMultiEntityQuery = false;
public IEnumerable<RouteResult> Route<T>(Type shardingDbContextType, RouteRuleContext<T> routeRuleContext) public IEnumerable<RouteResult> Route<T>(Type shardingDbContextType, RouteRuleContext<T> routeRuleContext)
{ {
Dictionary<IVirtualTable, ISet<IPhysicTable>> routeMaps = new Dictionary<IVirtualTable, ISet<IPhysicTable>>(); Dictionary<IVirtualTable, ISet<IPhysicTable>> routeMaps = new Dictionary<IVirtualTable, ISet<IPhysicTable>>();
@ -100,10 +98,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
var shardingEntities = queryEntities.Where(o => o.IsShardingTable()); var shardingEntities = queryEntities.Where(o => o.IsShardingTable());
if (shardingEntities.Count() > 1&& !EnableMultiEntityQuery)
{
throw new ShardingCoreException("not support multi entity query");
}
foreach (var shardingEntity in shardingEntities) foreach (var shardingEntity in shardingEntities)
{ {
var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntity); var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntity);

View File

@ -22,5 +22,6 @@ namespace ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine
} }
public ISet<IPhysicTable> ReplaceTables { get; } public ISet<IPhysicTable> ReplaceTables { get; }
} }
} }

View File

@ -14,6 +14,8 @@ using ShardingCore.TableCreator;
using System; using System;
using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.ShardingAccessors.Abstractions; using ShardingCore.Core.ShardingAccessors.Abstractions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore namespace ShardingCore
{ {
@ -81,6 +83,7 @@ namespace ShardingCore
//services.AddSingleton(typeof(IVirtualTable<>), typeof(OneDbVirtualTable<>)); //services.AddSingleton(typeof(IVirtualTable<>), typeof(OneDbVirtualTable<>));
services.AddSingleton<IShardingAccessor, ShardingAccessor>(); services.AddSingleton<IShardingAccessor, ShardingAccessor>();
services.AddSingleton<IShardingScopeFactory, ShardingScopeFactory>(); services.AddSingleton<IShardingScopeFactory, ShardingScopeFactory>();
services.AddSingleton<IRouteTailFactory, RouteTailFactory>();
return services; return services;
} }

View File

@ -34,12 +34,12 @@ namespace ShardingCore.DbContexts
throw new ShardingCoreException( throw new ShardingCoreException(
$"{shardingDbContextType.FullName} cant found DefaultShardingDbContextCreatorConfig<{shardingDbContextType.Name}> should use {nameof(DIExtension.AddShardingDbContext)}"); $"{shardingDbContextType.FullName} cant found DefaultShardingDbContextCreatorConfig<{shardingDbContextType.Name}> should use {nameof(DIExtension.AddShardingDbContext)}");
} }
var tail=shardingDbContextOptions.Tail; var routeTail=shardingDbContextOptions.RouteTail;
var dbContext = shardingDbContextCreatorConfig.Creator(shardingDbContextOptions); var dbContext = shardingDbContextCreatorConfig.Creator(shardingDbContextOptions);
if (!string.IsNullOrWhiteSpace(tail) && dbContext is IShardingTableDbContext shardingTableDbContext) if (dbContext is IShardingTableDbContext shardingTableDbContext)
{ {
shardingTableDbContext.SetShardingTableDbContextTail(tail); shardingTableDbContext.RouteTail = routeTail;
} }
var dbContextModel = dbContext.Model; var dbContextModel = dbContext.Model;
return dbContext; return dbContext;

View File

@ -1,5 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.DbContexts.ShardingDbContexts namespace ShardingCore.DbContexts.ShardingDbContexts
{ {
@ -12,13 +14,13 @@ namespace ShardingCore.DbContexts.ShardingDbContexts
public class ShardingDbContextOptions public class ShardingDbContextOptions
{ {
public ShardingDbContextOptions(DbContextOptions dbContextOptions, string tail) public ShardingDbContextOptions(DbContextOptions dbContextOptions, IRouteTail routeTail)
{ {
RouteTail = routeTail;
DbContextOptions = dbContextOptions; DbContextOptions = dbContextOptions;
Tail = tail;
} }
public IRouteTail RouteTail{ get; }
public DbContextOptions DbContextOptions { get; } public DbContextOptions DbContextOptions { get; }
public string Tail { get; }
} }
} }

View File

@ -17,10 +17,10 @@ namespace ShardingCore.EFCores
{ {
public object Create(DbContext context) public object Create(DbContext context)
{ {
if (context is IShardingTableDbContext shardingTableDbContext&&!string.IsNullOrWhiteSpace(shardingTableDbContext.ModelChangeKey)) if (context is IShardingTableDbContext shardingTableDbContext&&!string.IsNullOrWhiteSpace(shardingTableDbContext.RouteTail.GetRouteTailIdenty()))
{ {
return $"{context.GetType()}_{shardingTableDbContext.ModelChangeKey}"; return $"{context.GetType()}_{shardingTableDbContext.RouteTail.GetRouteTailIdenty()}";
} }
else else
{ {

View File

@ -6,6 +6,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using ShardingCore.Core.ShardingAccessors.Abstractions; using ShardingCore.Core.ShardingAccessors.Abstractions;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualTables; using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Extensions; using ShardingCore.Extensions;
@ -21,9 +22,10 @@ namespace ShardingCore.EFCores
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class ShardingModelCustomizer<TShardingDbContext>: ModelCustomizer where TShardingDbContext:DbContext,IShardingDbContext public class ShardingModelCustomizer<TShardingDbContext> : ModelCustomizer where TShardingDbContext : DbContext, IShardingDbContext
{ {
private Type _shardingDbContextType => typeof(TShardingDbContext); private Type _shardingDbContextType => typeof(TShardingDbContext);
public ShardingModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies) public ShardingModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies)
{ {
} }
@ -33,12 +35,11 @@ namespace ShardingCore.EFCores
base.Customize(modelBuilder, context); base.Customize(modelBuilder, context);
if (context is IShardingTableDbContext shardingTableDbContext) if (context is IShardingTableDbContext shardingTableDbContext)
{ {
var tail = shardingTableDbContext.GetShardingTableDbContextTail(); var isMultiEntityQuery = shardingTableDbContext.RouteTail.IsMultiEntityQuery();
//if (tail.StartsWith("EMPTY_SHARDING_TAIL_ID")) if (!isMultiEntityQuery)
// tail = null;
if (!string.IsNullOrWhiteSpace(tail))
{ {
var singleQueryRouteTail = (ISingleQueryRouteTail) shardingTableDbContext.RouteTail;
var tail = singleQueryRouteTail.GetTail();
var virtualTableManager = ShardingContainer.Services.GetService<IVirtualTableManager>(); var virtualTableManager = ShardingContainer.Services.GetService<IVirtualTableManager>();
var typeMap = virtualTableManager.GetAllVirtualTables(_shardingDbContextType).Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet(); var typeMap = virtualTableManager.GetAllVirtualTables(_shardingDbContextType).Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet();
@ -49,26 +50,24 @@ namespace ShardingCore.EFCores
MappingToTable(entityType.ClrType, modelBuilder, tail); MappingToTable(entityType.ClrType, modelBuilder, tail);
} }
} }
//else else
//{ {
var multiQueryRouteTail = (IMultiQueryRouteTail) shardingTableDbContext.RouteTail;
// var shardingAccessor = ShardingContainer.Services.GetService<IShardingAccessor>(); var entityTypes = multiQueryRouteTail.GetEntityTypes();
// if (shardingAccessor?.ShardingContext != null) var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable() && entityTypes.Contains(o.ClrType)).ToArray();
// { foreach (var entityType in mutableEntityTypes)
// var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable()).ToArray(); {
// foreach (var entityType in mutableEntityTypes) var queryTail = multiQueryRouteTail.GetEntityTail(entityType.ClrType);
// { if (queryTail != null)
// var queryTail = shardingAccessor.ShardingContext.GetContextQueryTail(entityType.ClrType); {
// if (queryTail != null) MappingToTable(entityType.ClrType, modelBuilder, queryTail);
// { }
// MappingToTable(entityType.ClrType,modelBuilder, queryTail); }
// } }
// }
// }
//}
} }
} }
private void MappingToTable(Type clrType,ModelBuilder modelBuilder,string tail)
private void MappingToTable(Type clrType, ModelBuilder modelBuilder, string tail)
{ {
var shardingEntityConfig = ShardingKeyUtil.Parse(clrType); var shardingEntityConfig = ShardingKeyUtil.Parse(clrType);
var shardingEntity = shardingEntityConfig.ShardingEntityType; var shardingEntity = shardingEntityConfig.ShardingEntityType;
@ -83,4 +82,4 @@ namespace ShardingCore.EFCores
entity.ToTable($"{tableName}{tailPrefix}{tail}"); entity.ToTable($"{tableName}{tailPrefix}{tail}");
} }
} }
} }

View File

@ -104,9 +104,9 @@ namespace ShardingCore.EFCores
case nameof(Enumerable.All): case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Max): case nameof(Enumerable.Max):
return GenericMergeExecute<TResult>(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Min): case nameof(Enumerable.Min):
return EnsureMergeExecute<TResult>(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, default); return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Sum): case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default); return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, default);
case nameof(Enumerable.Average): case nameof(Enumerable.Average):
@ -177,9 +177,9 @@ namespace ShardingCore.EFCores
case nameof(Enumerable.All): case nameof(Enumerable.All):
return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); return EnsureMergeExecute<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max): case nameof(Enumerable.Max):
return GenericMergeExecute<TResult>(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); return GenericMergeExecute2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min): case nameof(Enumerable.Min):
return EnsureMergeExecute<TResult>(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); return GenericMergeExecute2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum): case nameof(Enumerable.Sum):
return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken); return EnsureMergeExecute2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Average): case nameof(Enumerable.Average):
@ -224,13 +224,27 @@ namespace ShardingCore.EFCores
private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken) private TResult GenericMergeExecute<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{ {
var queryEntityType = query.GetQueryEntityType(); var queryEntityType = query.GetQueryEntityType();
var resultEntityType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType); streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext); var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult)); var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null) if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]"); throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0]; var @params = async ? new object[] { cancellationToken } : new object[0];
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { queryEntityType }).Invoke(streamEngine, @params); return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultEntityType }).Invoke(streamEngine, @params);
}
private TResult GenericMergeExecute2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType,resultType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
//typeof(TResult)==?resultType
return (TResult)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
} }
@ -323,6 +337,19 @@ namespace ShardingCore.EFCores
var @params = async ? new object[] { cancellationToken } : new object[0]; var @params = async ? new object[] { cancellationToken } : new object[0];
return (Task<TResult>)streamEngineMethod.Invoke(streamEngine, @params); return (Task<TResult>)streamEngineMethod.Invoke(streamEngine, @params);
} }
private Task<TResult> GenericMergeExecuteAsync2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, bool async, CancellationToken cancellationToken)
{
var queryEntityType = query.GetQueryEntityType();
var resultType = query.GetResultType();
streamMergeEngineType = streamMergeEngineType.MakeGenericType(queryEntityType,resultType);
var streamEngine = Activator.CreateInstance(streamMergeEngineType, query, shardingDbContext);
var streamEngineMethod = streamMergeEngineType.GetMethod(async ? nameof(IGenericMergeResult.MergeResultAsync) : nameof(IGenericMergeResult.MergeResult));
if (streamEngineMethod == null)
throw new ShardingCoreException("cant found InMemoryAsyncStreamMergeEngine method [DoExecuteAsync]");
var @params = async ? new object[] { cancellationToken } : new object[0];
return (Task<TResult>)streamEngineMethod.MakeGenericMethod(new Type[] { resultType }).Invoke(streamEngine, @params);
}
private Task<TResult> EnsureMergeExecuteAsync2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, CancellationToken cancellationToken) private Task<TResult> EnsureMergeExecuteAsync2<TResult>(Type streamMergeEngineType, IShardingDbContext shardingDbContext, MethodCallExpression query, CancellationToken cancellationToken)
{ {
@ -392,9 +419,9 @@ namespace ShardingCore.EFCores
case nameof(Enumerable.All): case nameof(Enumerable.All):
return EnsureMergeExecuteAsync<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); return EnsureMergeExecuteAsync<TResult>(typeof(AllAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Max): case nameof(Enumerable.Max):
return GenericMergeExecuteAsync<TResult>(typeof(MaxAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); return GenericMergeExecuteAsync2<TResult>(typeof(MaxAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Min): case nameof(Enumerable.Min):
return EnsureMergeExecuteAsync<TResult>(typeof(MinAsyncInMemoryMergeEngine<>), shardingDbContext, methodCallExpression, async, cancellationToken); return GenericMergeExecuteAsync2<TResult>(typeof(MinAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, async, cancellationToken);
case nameof(Enumerable.Sum): case nameof(Enumerable.Sum):
return EnsureMergeExecuteAsync2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken); return EnsureMergeExecuteAsync2<TResult>(typeof(SumAsyncInMemoryMergeEngine<,>), shardingDbContext, methodCallExpression, cancellationToken);
case nameof(Enumerable.Average): case nameof(Enumerable.Average):

View File

@ -18,11 +18,24 @@ namespace ShardingCore.Extensions
{ {
public static Type GetQueryEntityType(this MethodCallExpression expression) public static Type GetQueryEntityType(this MethodCallExpression expression)
{ {
var rootQuery = expression.Arguments.FirstOrDefault(o => typeof(IQueryable).IsAssignableFrom(o.Type)); var rootQuery = expression.Arguments.FirstOrDefault(o => typeof(IQueryable).IsAssignableFrom(o.Type));
if (rootQuery == null) if (rootQuery == null)
throw new ShardingCoreException("expression error"); throw new ShardingCoreException("expression error");
return rootQuery.Type.GetSequenceType(); return rootQuery.Type.GetSequenceType();
}
public static Type GetResultType(this MethodCallExpression expression)
{
if (expression.Arguments.Count == 1)
return expression.GetQueryEntityType();
var otherExpression = expression.Arguments.FirstOrDefault(o => !typeof(IQueryable).IsAssignableFrom(o.Type));
if (otherExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression)
{
return lambdaExpression.ReturnType;
}
throw new ShardingCoreException("expression error");
} }
} }
} }

View File

@ -19,26 +19,32 @@ namespace ShardingCore.Extensions
public static class ShardingExtension public static class ShardingExtension
{ {
private static readonly string ShardingTableDbContextFormat = $"sharding_{Guid.NewGuid():n}_"; private static readonly string ShardingTableDbContextFormat = $"sharding_{Guid.NewGuid():n}_";
/// <summary> // /// <summary>
/// 获取分表的tail // /// 获取分表的tail
/// </summary> // /// </summary>
/// <param name="dbContext"></param> // /// <param name="dbContext"></param>
/// <returns></returns> // /// <returns></returns>
public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext) // public static string GetShardingTableDbContextTail(this IShardingTableDbContext dbContext)
{ // {
return dbContext.ModelChangeKey?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty; // return dbContext.RouteTail?.Replace(ShardingTableDbContextFormat, string.Empty)??string.Empty;
//
// }
// /// <summary>
// /// 设置分表的tail
// /// </summary>
// /// <param name="dbContext"></param>
// /// <param name="tail"></param>
// public static void SetShardingTableDbContextTail(this IShardingTableDbContext dbContext, string tail)
// {
// if (!string.IsNullOrWhiteSpace(dbContext.ModelChangeKey))
// throw new ShardingCoreException($"repeat set ModelChangeKey in {dbContext.GetType().FullName}");
// dbContext.ModelChangeKey = tail.FormatRouteTail();
// }
} public static string FormatRouteTail2ModelCacheKey(this string originalTail)
/// <summary>
/// 设置分表的tail
/// </summary>
/// <param name="dbContext"></param>
/// <param name="tail"></param>
public static void SetShardingTableDbContextTail(this IShardingTableDbContext dbContext, string tail)
{ {
if (!string.IsNullOrWhiteSpace(dbContext.ModelChangeKey)) return $"{ShardingTableDbContextFormat}{originalTail}";
throw new ShardingCoreException($"repeat set ModelChangeKey in {dbContext.GetType().FullName}"); ;
dbContext.ModelChangeKey = $"{ShardingTableDbContextFormat}{tail}";
} }
} }
} }

View File

@ -11,11 +11,15 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.RouteTails;
using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables; using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts; using ShardingCore.DbContexts;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.EFCores; using ShardingCore.EFCores;
using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
@ -33,9 +37,9 @@ namespace ShardingCore.Sharding
/// <typeparam name="T"></typeparam> /// <typeparam name="T"></typeparam>
public abstract class AbstractShardingDbContext<T> : DbContext, IShardingTableDbContext<T> where T : DbContext, IShardingTableDbContext public abstract class AbstractShardingDbContext<T> : DbContext, IShardingTableDbContext<T> where T : DbContext, IShardingTableDbContext
{ {
private readonly string EMPTY_SHARDING_TAIL_ID = ShardingConstant.EMPTY_SHARDING_TAIL_ID+ Guid.NewGuid().ToString("n");
private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>(); private readonly ConcurrentDictionary<string, DbContext> _dbContextCaches = new ConcurrentDictionary<string, DbContext>();
private readonly IVirtualTableManager _virtualTableManager; private readonly IVirtualTableManager _virtualTableManager;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IShardingDbContextFactory _shardingDbContextFactory;
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig; private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
private DbContextOptions<T> _dbContextOptions; private DbContextOptions<T> _dbContextOptions;
@ -46,6 +50,7 @@ namespace ShardingCore.Sharding
{ {
_shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory>(); _shardingDbContextFactory = ShardingContainer.GetService<IShardingDbContextFactory>();
_virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>(); _virtualTableManager = ShardingContainer.GetService<IVirtualTableManager>();
_routeTailFactory = ShardingContainer.GetService<IRouteTailFactory>();
_shardingDbContextOptionsBuilderConfig = ShardingContainer _shardingDbContextOptionsBuilderConfig = ShardingContainer
.GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>() .GetService<IEnumerable<IShardingDbContextOptionsBuilderConfig>>()
.FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType); .FirstOrDefault(o => o.ShardingDbContextType == ShardingDbContextType);
@ -76,7 +81,7 @@ namespace ShardingCore.Sharding
return dbContextOptionBuilder.Options; return dbContextOptionBuilder.Options;
} }
private ShardingDbContextOptions GetShareShardingDbContextOptions(string tail) private ShardingDbContextOptions GetShareShardingDbContextOptions(IRouteTail routeTail)
{ {
if (_dbContextOptions == null) if (_dbContextOptions == null)
{ {
@ -89,29 +94,34 @@ namespace ShardingCore.Sharding
} }
} }
return new ShardingDbContextOptions(_dbContextOptions, tail); return new ShardingDbContextOptions(_dbContextOptions, routeTail);
} }
private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(string tail) private ShardingDbContextOptions CetMonopolyShardingDbContextOptions(IRouteTail routeTail)
{ {
return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), tail); return new ShardingDbContextOptions(CreateMonopolyDbContextOptions(), routeTail);
} }
public DbContext GetDbContext(bool track, string tail) public DbContext GetDbContext(bool track, IRouteTail routeTail)
{ {
if (track) if (track)
{ {
if (!_dbContextCaches.TryGetValue(tail, out var dbContext)) if (routeTail.IsMultiEntityQuery())
throw new ShardingCoreException("multi route not support track");
if(!(routeTail is ISingleQueryRouteTail singleQueryRouteTail))
throw new ShardingCoreException("multi route not support track");
var cacheKey = routeTail.GetRouteTailIdenty();
if (!_dbContextCaches.TryGetValue(cacheKey, out var dbContext))
{ {
dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail)); dbContext = _shardingDbContextFactory.Create(ShardingDbContextType, GetShareShardingDbContextOptions(routeTail));
_dbContextCaches.TryAdd(tail, dbContext); _dbContextCaches.TryAdd(cacheKey, dbContext);
} }
return dbContext; return dbContext;
} }
else else
{ {
return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(tail == EMPTY_SHARDING_TAIL_ID ? string.Empty : tail)); return _shardingDbContextFactory.Create(ShardingDbContextType, CetMonopolyShardingDbContextOptions(routeTail));
} }
} }
@ -119,14 +129,14 @@ namespace ShardingCore.Sharding
public DbContext CreateGenericDbContext<T>(T entity) where T : class public DbContext CreateGenericDbContext<T>(T entity) where T : class
{ {
var tail = EMPTY_SHARDING_TAIL_ID; var tail = string.Empty;
if (entity.IsShardingTable()) if (entity.IsShardingTable())
{ {
var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0]; var physicTable = _virtualTableManager.GetVirtualTable(ShardingDbContextType, entity.GetType()).RouteTo(new TableRouteConfig(null, entity as IShardingTable, null))[0];
tail = physicTable.Tail; tail = physicTable.Tail;
} }
return GetDbContext(true, tail); return GetDbContext(true, _routeTailFactory.Create(tail));
} }

View File

@ -2,6 +2,8 @@ using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding.Abstractions namespace ShardingCore.Sharding.Abstractions
{ {
@ -19,12 +21,12 @@ namespace ShardingCore.Sharding.Abstractions
/// </summary> /// </summary>
Type ActualDbContextType { get;} Type ActualDbContextType { get;}
/// <summary> /// <summary>
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD>DbContext /// create DbContext
/// </summary> /// </summary>
/// <param name="track">true not care dbcontext life, false need call dispose()</param> /// <param name="track">true not care dbcontext life, false need call dispose()</param>
/// <param name="tail"></param> /// <param name="routeTail"></param>
/// <returns></returns> /// <returns></returns>
DbContext GetDbContext(bool track,string tail); DbContext GetDbContext(bool track,IRouteTail routeTail);
/// <summary> /// <summary>
/// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><E5B4B4>db context /// <20><><EFBFBD><EFBFBD>ʵ<EFBFBD><EFBFBD><E5B4B4>db context
/// </summary> /// </summary>

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding.Abstractions namespace ShardingCore.Sharding.Abstractions
{ {
@ -14,6 +15,6 @@ namespace ShardingCore.Sharding.Abstractions
*/ */
public interface IShardingTableDbContext public interface IShardingTableDbContext
{ {
string ModelChangeKey { get; set; } IRouteTail RouteTail { get; set; }
} }
} }

View File

@ -1,11 +1,10 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ShardingCore.Core.Internal.PriorityQueues; using ShardingCore.Core.Internal.PriorityQueues;
namespace ShardingCore.Sharding.Enumerators namespace ShardingCore.Sharding.Enumerators.StreamMergeAsync
{ {
/* /*
* @Author: xjm * @Author: xjm

View File

@ -8,6 +8,8 @@ using ShardingCore.Sharding.Abstractions;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding namespace ShardingCore.Sharding
@ -24,7 +26,7 @@ namespace ShardingCore.Sharding
private readonly IQueryable<T> _source; private readonly IQueryable<T> _source;
private readonly IShardingDbContext _shardingDbContext; private readonly IShardingDbContext _shardingDbContext;
private readonly IRoutingRuleEngineFactory _tableRoutingRuleEngineFactory; private readonly IRoutingRuleEngineFactory _tableRoutingRuleEngineFactory;
private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IRouteTailFactory _routeTailFactory;
private readonly IQueryable<T> _reWriteSource; private readonly IQueryable<T> _reWriteSource;
//public IEnumerable<RouteResult> RouteResults { get; } //public IEnumerable<RouteResult> RouteResults { get; }
@ -36,13 +38,13 @@ namespace ShardingCore.Sharding
public SelectContext SelectContext { get;} public SelectContext SelectContext { get;}
public GroupByContext GroupByContext { get; } public GroupByContext GroupByContext { get; }
public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IShardingScopeFactory shardingScopeFactory) public StreamMergeContext(IQueryable<T> source,IShardingDbContext shardingDbContext,IRoutingRuleEngineFactory tableRoutingRuleEngineFactory, IRouteTailFactory routeTailFactory)
{ {
//_shardingScopeFactory = shardingScopeFactory; //_shardingScopeFactory = shardingScopeFactory;
_source = source; _source = source;
_shardingDbContext = shardingDbContext; _shardingDbContext = shardingDbContext;
_tableRoutingRuleEngineFactory = tableRoutingRuleEngineFactory; _tableRoutingRuleEngineFactory = tableRoutingRuleEngineFactory;
_shardingScopeFactory = shardingScopeFactory; _routeTailFactory = routeTailFactory;
var reWriteResult = new ReWriteEngine<T>(source).ReWrite(); var reWriteResult = new ReWriteEngine<T>(source).ReWrite();
Skip = reWriteResult.Skip; Skip = reWriteResult.Skip;
Take = reWriteResult.Take; Take = reWriteResult.Take;
@ -67,18 +69,19 @@ namespace ShardingCore.Sharding
// _reWriteSource = reWriteResult.ReWriteQueryable; // _reWriteSource = reWriteResult.ReWriteQueryable;
//} //}
public DbContext CreateDbContext(string tail) public DbContext CreateDbContext(RouteResult routeResult)
{ {
return _shardingDbContext.GetDbContext(false, tail); var routeTail = _routeTailFactory.Create(routeResult);
return _shardingDbContext.GetDbContext(false, routeTail);
} }
public IEnumerable<RouteResult> GetRouteResults() public IEnumerable<RouteResult> GetRouteResults()
{ {
return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source); return _tableRoutingRuleEngineFactory.Route(_shardingDbContext.GetType(),_source);
} }
public ShardingScope CreateScope() public IRouteTail Create(RouteResult routeResult)
{ {
return _shardingScopeFactory.CreateScope(); return _routeTailFactory.Create(routeResult);
} }
public IQueryable<T> GetReWriteQueryable() public IQueryable<T> GetReWriteQueryable()

View File

@ -2,6 +2,7 @@ using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using System.Linq; using System.Linq;
using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes.Abstractions;
namespace ShardingCore.Sharding namespace ShardingCore.Sharding
{ {
@ -14,17 +15,17 @@ namespace ShardingCore.Sharding
public class StreamMergeContextFactory:IStreamMergeContextFactory public class StreamMergeContextFactory:IStreamMergeContextFactory
{ {
private readonly IRoutingRuleEngineFactory _routingRuleEngineFactory; private readonly IRoutingRuleEngineFactory _routingRuleEngineFactory;
private readonly IShardingScopeFactory _shardingScopeFactory; private readonly IRouteTailFactory _routeTailFactory;
public StreamMergeContextFactory( public StreamMergeContextFactory(
IRoutingRuleEngineFactory routingRuleEngineFactory,IShardingScopeFactory shardingScopeFactory) IRoutingRuleEngineFactory routingRuleEngineFactory,IRouteTailFactory routeTailFactory)
{ {
_routingRuleEngineFactory = routingRuleEngineFactory; _routingRuleEngineFactory = routingRuleEngineFactory;
_shardingScopeFactory = shardingScopeFactory; _routeTailFactory = routeTailFactory;
} }
public StreamMergeContext<T> Create<T>(IQueryable<T> queryable,IShardingDbContext shardingDbContext) public StreamMergeContext<T> Create<T>(IQueryable<T> queryable,IShardingDbContext shardingDbContext)
{ {
return new StreamMergeContext<T>(queryable,shardingDbContext, _routingRuleEngineFactory, _shardingScopeFactory); return new StreamMergeContext<T>(queryable,shardingDbContext, _routingRuleEngineFactory, _routeTailFactory);
} }
} }
} }

View File

@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public abstract class AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TResult>: AbstractEnsureMethodCallInMemoryAsyncMergeEngine<TEntity, TResult> public abstract class AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TResult,TSelect>: AbstractEnsureMethodCallInMemoryAsyncMergeEngine<TEntity, TResult>
{ {
protected AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) protected AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
@ -26,7 +26,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractEnsureEx
var secondExpression = GetSecondExpression(); var secondExpression = GetSecondExpression();
if (secondExpression != null) if (secondExpression != null)
{ {
if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TResult>> selector) if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TSelect>> selector)
{ {
return queryable.Select(selector); return queryable.Select(selector);
} }

View File

@ -14,7 +14,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public abstract class AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity>:AbstractGenericMethodCallInMemoryAsyncMergeEngine<TEntity> public abstract class AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TSelect>:AbstractGenericMethodCallInMemoryAsyncMergeEngine<TEntity>
{ {
public AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) public AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{ {
@ -25,7 +25,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions.AbstractGenericE
var secondExpression = GetSecondExpression(); var secondExpression = GetSecondExpression();
if (secondExpression != null) if (secondExpression != null)
{ {
if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TResult>> selector) if (secondExpression is UnaryExpression unaryExpression && unaryExpression.Operand is LambdaExpression lambdaExpression && lambdaExpression is Expression<Func<TEntity, TSelect>> selector)
{ {
return queryable.Select(selector); return queryable.Select(selector);
} }

View File

@ -6,13 +6,9 @@ using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using ShardingCore.Core.ShardingAccessors;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{ {
@ -52,7 +48,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{ {
if (methodCallExpression.Arguments.Count == 2) if (methodCallExpression.Arguments.Count == 2)
{ {
#if !EFCORE2 #if !EFCORE2
throw new InvalidOperationException(methodCallExpression.Print()); throw new InvalidOperationException(methodCallExpression.Print());
#endif #endif
@ -68,30 +63,27 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
protected abstract IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression); protected abstract IQueryable<TEntity> ProcessSecondExpression(IQueryable<TEntity> queryable, Expression secondExpression);
private IQueryable CreateAsyncExecuteQueryable<TResult>(RouteResult routeResult)
{
var shardingDbContext = _mergeContext.CreateDbContext(routeResult);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<TEntity>) GetStreamMergeContext().GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
return newFilterQueryable;
}
public async Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken()) public async Task<List<TResult>> ExecuteAsync<TResult>(Func<IQueryable, Task<TResult>> efQuery, CancellationToken cancellationToken = new CancellationToken())
{ {
var tableResult = _mergeContext.GetRouteResults(); var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult => var enumeratorTasks = tableResult.Select(routeResult =>
{ {
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(async () => return Task.Run(async () =>
{ {
try try
{ {
//using (var scope = _mergeContext.CreateScope()) var asyncExecuteQueryable = CreateAsyncExecuteQueryable<TResult>(routeResult);
//{ return await efQuery(asyncExecuteQueryable);
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<TEntity>)GetStreamMergeContext().GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable);
return await efQuery(newFilterQueryable);
//} //}
} }
catch (Exception e) catch (Exception e)
@ -104,39 +96,26 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
return (await Task.WhenAll(enumeratorTasks)).ToList(); return (await Task.WhenAll(enumeratorTasks)).ToList();
} }
public List<TResult> Execute<TResult>(Func<IQueryable, TResult> efQuery, CancellationToken cancellationToken = new CancellationToken()) public List<TResult> Execute<TResult>(Func<IQueryable, TResult> efQuery, CancellationToken cancellationToken = new CancellationToken())
{ {
var tableResult = _mergeContext.GetRouteResults(); var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult => var enumeratorTasks = tableResult.Select(routeResult =>
{ {
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(() => return Task.Run(() =>
{ {
try try
{ {
//using (var scope = _mergeContext.CreateScope()) var asyncExecuteQueryable = CreateAsyncExecuteQueryable<TResult>(routeResult);
//{ var query = efQuery(asyncExecuteQueryable);
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult); return query;
var shardingDbContext = _mergeContext.CreateDbContext(tail); }
_parllelDbbContexts.Add(shardingDbContext); catch (Exception e)
var newQueryable = (IQueryable<TEntity>)GetStreamMergeContext().GetReWriteQueryable() {
.ReplaceDbContextQueryable(shardingDbContext); Console.WriteLine(e);
var newFilterQueryable = EFQueryAfterFilter<TResult>(newQueryable); throw;
var query = efQuery(newFilterQueryable); }
return query; });
//}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
});
}).ToArray(); }).ToArray();
return Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult().ToList(); return Task.WhenAll(enumeratorTasks).GetAwaiter().GetResult().ToList();
} }
@ -151,6 +130,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{ {
return _mergeContext; return _mergeContext;
} }
public IQueryable<TEntity> GetQueryable() public IQueryable<TEntity> GetQueryable()
{ {
return _queryable; return _queryable;
@ -165,6 +145,5 @@ namespace ShardingCore.Sharding.StreamMergeEngines.Abstractions
{ {
return _secondExpression; return _secondExpression;
} }
} }
} }

View File

@ -23,7 +23,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class AverageAsyncInMemoryMergeEngine<TEntity, TEnsureResult> : public class AverageAsyncInMemoryMergeEngine<TEntity, TEnsureResult> :
AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult> AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult,TEnsureResult>
{ {
public AverageAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, public AverageAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression,
IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)

View File

@ -19,7 +19,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class MaxAsyncInMemoryMergeEngine<TEntity>: AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity> public class MaxAsyncInMemoryMergeEngine<TEntity,TSelect>: AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TSelect>
{ {
public MaxAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) public MaxAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{ {

View File

@ -20,7 +20,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class MinAsyncInMemoryMergeEngine<TEntity> : AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity> public class MinAsyncInMemoryMergeEngine<TEntity,TSelect> : AbstractGenericMethodCallSelectorInMemoryAsyncMergeEngine<TEntity,TSelect>
{ {
public MinAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) public MinAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{ {

View File

@ -22,7 +22,7 @@ namespace ShardingCore.Sharding.StreamMergeEngines.AggregateMergeEngines
* @Ver: 1.0 * @Ver: 1.0
* @Email: 326308290@qq.com * @Email: 326308290@qq.com
*/ */
public class SumAsyncInMemoryMergeEngine<TEntity, TEnsureResult> : AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult> public class SumAsyncInMemoryMergeEngine<TEntity, TEnsureResult> : AbstractEnsureMethodCallSelectorInMemoryAsyncMergeEngine<TEntity, TEnsureResult,TEnsureResult>
{ {
public SumAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext) public SumAsyncInMemoryMergeEngine(MethodCallExpression methodCallExpression, IShardingDbContext shardingDbContext) : base(methodCallExpression, shardingDbContext)
{ {

View File

@ -5,7 +5,7 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.ShardingAccessors; using ShardingCore.Core.VirtualRoutes.TableRoutes.RoutingRuleEngine;
using ShardingCore.Exceptions; using ShardingCore.Exceptions;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.Sharding.Enumerators; using ShardingCore.Sharding.Enumerators;
@ -26,7 +26,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines
*/ */
public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>, IDisposable public class AsyncEnumerableStreamMergeEngine<T> : IAsyncEnumerable<T>, IEnumerable<T>, IDisposable
{ {
private readonly StreamMergeContext<T> _mergeContext; private readonly StreamMergeContext<T> _mergeContext;
private readonly ICollection<DbContext> _parllelDbbContexts; private readonly ICollection<DbContext> _parllelDbbContexts;
@ -47,7 +46,6 @@ namespace ShardingCore.Sharding.StreamMergeEngines
} }
#endif #endif
#if EFCORE2 #if EFCORE2
private async Task<IAsyncEnumerator<T>> GetAsyncEnumerator(IQueryable<T> newQueryable) private async Task<IAsyncEnumerator<T>> GetAsyncEnumerator(IQueryable<T> newQueryable)
{ {
var enumator = newQueryable.AsAsyncEnumerable().GetEnumerator(); var enumator = newQueryable.AsAsyncEnumerable().GetEnumerator();
@ -64,38 +62,34 @@ namespace ShardingCore.Sharding.StreamMergeEngines
#endif #endif
#if EFCORE2 #if EFCORE2
IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator() IAsyncEnumerator<T> IAsyncEnumerable<T>.GetEnumerator()
{ {
return GetShardingEnumerator(); return GetShardingEnumerator();
} }
#endif #endif
private IQueryable<T> CreateAsyncExecuteQueryable(RouteResult routeResult)
{
var shardingDbContext = _mergeContext.CreateDbContext(routeResult);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<T>) _mergeContext.GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
return newQueryable;
}
private IAsyncEnumerator<T> GetShardingEnumerator() private IAsyncEnumerator<T> GetShardingEnumerator()
{ {
var tableResult = _mergeContext.GetRouteResults(); var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult => var enumeratorTasks = tableResult.Select(routeResult =>
{ {
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(async () => return Task.Run(async () =>
{ {
try try
{ {
//using (var scope = _mergeContext.CreateScope()) var newQueryable = CreateAsyncExecuteQueryable(routeResult);
//{
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<T>)_mergeContext.GetReWriteQueryable()
.ReplaceDbContextQueryable(shardingDbContext);
var asyncEnumerator = await GetAsyncEnumerator(newQueryable); var asyncEnumerator = await GetAsyncEnumerator(newQueryable);
return new StreamMergeAsyncEnumerator<T>(asyncEnumerator); return new StreamMergeAsyncEnumerator<T>(asyncEnumerator);
//}
} }
catch (Exception e) catch (Exception e)
{ {
@ -126,27 +120,14 @@ namespace ShardingCore.Sharding.StreamMergeEngines
var tableResult = _mergeContext.GetRouteResults(); var tableResult = _mergeContext.GetRouteResults();
var enumeratorTasks = tableResult.Select(routeResult => var enumeratorTasks = tableResult.Select(routeResult =>
{ {
if (routeResult.ReplaceTables.Count > 1)
throw new ShardingCoreException("route found more than 1 table name s");
var tail = string.Empty;
if (routeResult.ReplaceTables.Count == 1)
tail = routeResult.ReplaceTables.First().Tail;
return Task.Run(() => return Task.Run(() =>
{ {
try try
{ {
//using (var scope = _mergeContext.CreateScope()) var newQueryable = CreateAsyncExecuteQueryable(routeResult);
//{
// scope.ShardingAccessor.ShardingContext = ShardingContext.Create(routeResult);
var shardingDbContext = _mergeContext.CreateDbContext(tail);
_parllelDbbContexts.Add(shardingDbContext);
var newQueryable = (IQueryable<T>)_mergeContext.GetReWriteQueryable() var enumerator = GetEnumerator(newQueryable);
.ReplaceDbContextQueryable(shardingDbContext); return new StreamMergeEnumerator<T>(enumerator);
var enumerator = GetEnumerator(newQueryable);
return new StreamMergeEnumerator<T>(enumerator);
//}
} }
catch (Exception e) catch (Exception e)
{ {
@ -187,4 +168,4 @@ namespace ShardingCore.Sharding.StreamMergeEngines
} }
} }
} }
} }

View File

@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ShardingCore.Core.PhysicTables; using ShardingCore.Core.PhysicTables;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualRoutes.TableRoutes; using ShardingCore.Core.VirtualRoutes.TableRoutes;
using ShardingCore.Core.VirtualTables; using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts; using ShardingCore.DbContexts;
@ -31,12 +32,13 @@ namespace ShardingCore
private readonly IVirtualTableManager _virtualTableManager; private readonly IVirtualTableManager _virtualTableManager;
private readonly IShardingTableCreator _tableCreator; private readonly IShardingTableCreator _tableCreator;
private readonly ILogger<ShardingBootstrapper> _logger; private readonly ILogger<ShardingBootstrapper> _logger;
private readonly IRouteTailFactory _routeTailFactory;
private readonly IShardingDbContextFactory _shardingDbContextFactory; private readonly IShardingDbContextFactory _shardingDbContextFactory;
public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions, public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions,
IVirtualTableManager virtualTableManager IVirtualTableManager virtualTableManager
, IShardingTableCreator tableCreator, ILogger<ShardingBootstrapper> logger, , IShardingTableCreator tableCreator, ILogger<ShardingBootstrapper> logger,
IShardingDbContextFactory shardingDbContextFactory) IShardingDbContextFactory shardingDbContextFactory,IRouteTailFactory routeTailFactory)
{ {
ShardingContainer.SetServices(serviceProvider); ShardingContainer.SetServices(serviceProvider);
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
@ -44,6 +46,7 @@ namespace ShardingCore
_virtualTableManager = virtualTableManager; _virtualTableManager = virtualTableManager;
_tableCreator = tableCreator; _tableCreator = tableCreator;
_logger = logger; _logger = logger;
_routeTailFactory = routeTailFactory;
_shardingDbContextFactory = shardingDbContextFactory; _shardingDbContextFactory = shardingDbContextFactory;
} }
@ -122,7 +125,7 @@ namespace ShardingCore
{ {
if (context is IShardingDbContext shardingDbContext) if (context is IShardingDbContext shardingDbContext)
{ {
var dbContext = shardingDbContext.GetDbContext(false,string.Empty); var dbContext = shardingDbContext.GetDbContext(false,_routeTailFactory.Create(string.Empty));
var modelCacheSyncObject = dbContext.GetModelCacheSyncObject(); var modelCacheSyncObject = dbContext.GetModelCacheSyncObject();
lock (modelCacheSyncObject) lock (modelCacheSyncObject)

View File

@ -7,6 +7,7 @@ using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using ShardingCore.Core; using ShardingCore.Core;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Core.VirtualTables; using ShardingCore.Core.VirtualTables;
using ShardingCore.DbContexts; using ShardingCore.DbContexts;
using ShardingCore.DbContexts.Abstractions; using ShardingCore.DbContexts.Abstractions;
@ -31,15 +32,17 @@ namespace ShardingCore.TableCreator
private readonly IVirtualTableManager _virtualTableManager; private readonly IVirtualTableManager _virtualTableManager;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IEnumerable<IShardingConfigOption> _shardingConfigOptions; private readonly IEnumerable<IShardingConfigOption> _shardingConfigOptions;
private readonly IRouteTailFactory _routeTailFactory;
public ShardingTableCreator(ILogger<ShardingTableCreator> logger, IShardingDbContextFactory shardingDbContextFactory, public ShardingTableCreator(ILogger<ShardingTableCreator> logger, IShardingDbContextFactory shardingDbContextFactory,
IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions) IVirtualTableManager virtualTableManager, IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions,IRouteTailFactory routeTailFactory)
{ {
_logger = logger; _logger = logger;
_shardingDbContextFactory = shardingDbContextFactory; _shardingDbContextFactory = shardingDbContextFactory;
_virtualTableManager = virtualTableManager; _virtualTableManager = virtualTableManager;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_shardingConfigOptions = shardingConfigOptions; _shardingConfigOptions = shardingConfigOptions;
_routeTailFactory = routeTailFactory;
} }
public void CreateTable<TShardingDbContext, T>(string tail) where TShardingDbContext : DbContext, IShardingDbContext where T : class, IShardingTable public void CreateTable<TShardingDbContext, T>(string tail) where TShardingDbContext : DbContext, IShardingDbContext where T : class, IShardingTable
@ -69,7 +72,7 @@ namespace ShardingCore.TableCreator
var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntityType); var virtualTable = _virtualTableManager.GetVirtualTable(shardingDbContextType, shardingEntityType);
var dbContext = (DbContext)serviceScope.ServiceProvider.GetService(shardingDbContextType); var dbContext = (DbContext)serviceScope.ServiceProvider.GetService(shardingDbContextType);
var shardingDbContext = (IShardingDbContext)dbContext; var shardingDbContext = (IShardingDbContext)dbContext;
var context = shardingDbContext.GetDbContext(false,tail); var context = shardingDbContext.GetDbContext(false,_routeTailFactory.Create(tail));
var modelCacheSyncObject = context.GetModelCacheSyncObject(); var modelCacheSyncObject = context.GetModelCacheSyncObject();

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50.MySql.Domain.Maps; using ShardingCore.Test50.MySql.Domain.Maps;
@ -26,6 +27,6 @@ namespace ShardingCore.Test50.MySql
modelBuilder.ApplyConfiguration(new SysUserSalaryMap()); modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
} }
public string ModelChangeKey { get; set; } public IRouteTail RouteTail { get; set; }
} }
} }

View File

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.DbContexts.ShardingDbContexts; using ShardingCore.DbContexts.ShardingDbContexts;
using ShardingCore.Sharding.Abstractions; using ShardingCore.Sharding.Abstractions;
using ShardingCore.Test50.Domain.Maps; using ShardingCore.Test50.Domain.Maps;
@ -26,6 +27,6 @@ namespace ShardingCore.Test50
modelBuilder.ApplyConfiguration(new SysUserSalaryMap()); modelBuilder.ApplyConfiguration(new SysUserSalaryMap());
} }
public string ModelChangeKey { get; set; } public IRouteTail RouteTail { get; set; }
} }
} }

View File

@ -22,6 +22,8 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content> </Content>
<None Remove="Configs\MacDbConfig.json" />
<Content Include="Configs\MacDbConfig.json" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\ShardingCore\ShardingCore.csproj" /> <ProjectReference Include="..\..\src\ShardingCore\ShardingCore.csproj" />

View File

@ -67,307 +67,307 @@ namespace ShardingCore.Test50
} }
} }
//[Fact] [Fact]
//public async Task ToList_Join_Test() public async Task ToList_Join_Test()
//{ {
// var list = await (from u in _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="1" || o.Id=="1000") var list = await (from u in _virtualDbContext.Set<SysUserMod>()
// join salary in _virtualDbContext.Set<SysUserSalary>() join salary in _virtualDbContext.Set<SysUserSalary>()
// on u.Id equals salary.UserId on u.Id equals salary.UserId
// select new select new
// { {
// u.Id, u.Id,
// u.Age, u.Age,
// Salary = salary.Salary, Salary = salary.Salary,
// DateOfMonth = salary.DateOfMonth, DateOfMonth = salary.DateOfMonth,
// Name = u.Name Name = u.Name
// }).ToListAsync(); }).ToListAsync();
// var list2 = list.OrderBy(o=>o.Age).ToList(); var list2 = list.OrderBy(o=>o.Age).Select(o=>o.Age).Distinct().ToList();
// Assert.Equal(24000, list.Count()); Assert.Equal(24000, list.Count());
// Assert.Equal(24, list.Count(o => o.Name == "name_200")); Assert.Equal(24, list.Count(o => o.Name == "name_200"));
// var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300") var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
// join salary in _virtualDbContext.Set<SysUserSalary>() join salary in _virtualDbContext.Set<SysUserSalary>()
// on u.Id equals salary.UserId on u.Id equals salary.UserId
// select new select new
// { {
// Salary = salary.Salary, Salary = salary.Salary,
// DateOfMonth = salary.DateOfMonth, DateOfMonth = salary.DateOfMonth,
// Name = u.Name Name = u.Name
// }); });
// var list1 = await queryable.ToListAsync(); var list1 = await queryable.ToListAsync();
// Assert.Equal(24, list1.Count()); Assert.Equal(24, list1.Count());
// Assert.DoesNotContain(list1, o => o.Name != "name_300"); Assert.DoesNotContain(list1, o => o.Name != "name_300");
//} }
//[Fact] [Fact]
//public async Task ToList_OrderBy_Asc_Desc_Test() public async Task ToList_OrderBy_Asc_Desc_Test()
//{ {
// var modascs = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToShardingListAsync(); var modascs = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ToListAsync();
// Assert.Equal(1000, modascs.Count); Assert.Equal(1000, modascs.Count);
// var i = 1; var i = 1;
// foreach (var age in modascs) foreach (var age in modascs)
// { {
// Assert.Equal(i, age.Age); Assert.Equal(i, age.Age);
// i++; i++;
// } }
// var moddescs = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToShardingListAsync(); var moddescs = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ToListAsync();
// Assert.Equal(1000, moddescs.Count); Assert.Equal(1000, moddescs.Count);
// var j = 1000; var j = 1000;
// foreach (var age in moddescs) foreach (var age in moddescs)
// { {
// Assert.Equal(j, age.Age); Assert.Equal(j, age.Age);
// j--; j--;
// } }
//} }
//[Fact] [Fact]
//public async Task ToList_Id_In_Test() public async Task ToList_Id_In_Test()
//{ {
// var ids = new[] {"1", "2", "3", "4"}; var ids = new[] {"1", "2", "3", "4"};
// var sysUserMods = await _virtualDbContext.Set<SysUserMod>().Where(o => ids.Contains(o.Id)).ToShardingListAsync(); var sysUserMods = await _virtualDbContext.Set<SysUserMod>().Where(o => ids.Contains(o.Id)).ToListAsync();
// foreach (var id in ids) foreach (var id in ids)
// { {
// Assert.Contains(sysUserMods, o => o.Id == id); Assert.Contains(sysUserMods, o => o.Id == id);
// } }
// Assert.DoesNotContain(sysUserMods, o => o.Age > 4); Assert.DoesNotContain(sysUserMods, o => o.Age > 4);
//} }
//[Fact] [Fact]
//public async Task ToList_Id_Eq_Test() public async Task ToList_Id_Eq_Test()
//{ {
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "3").ToShardingListAsync(); var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "3").ToListAsync();
// Assert.Single(mods); Assert.Single(mods);
// Assert.Equal("3", mods[0].Id); Assert.Equal("3", mods[0].Id);
//} }
//[Fact] [Fact]
//public async Task ToList_Id_Not_Eq_Test() public async Task ToList_Id_Not_Eq_Test()
//{ {
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").ToShardingListAsync(); var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").ToListAsync();
// Assert.Equal(999, mods.Count); Assert.Equal(999, mods.Count);
// Assert.DoesNotContain(mods, o => o.Id == "3"); Assert.DoesNotContain(mods, o => o.Id == "3");
//} }
//[Fact] [Fact]
//public async Task ToList_Id_Not_Eq_Skip_Test() public async Task ToList_Id_Not_Eq_Skip_Test()
//{ {
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderBy(o => o.Age).Skip(2).ToShardingListAsync(); var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderBy(o => o.Age).Skip(2).ToListAsync();
// Assert.Equal(997, mods.Count); Assert.Equal(997, mods.Count);
// Assert.DoesNotContain(mods, o => o.Id == "3"); Assert.DoesNotContain(mods, o => o.Id == "3");
// Assert.Equal(4, mods[0].Age); Assert.Equal(4, mods[0].Age);
// Assert.Equal(5, mods[1].Age); Assert.Equal(5, mods[1].Age);
// var modsDesc = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderByDescending(o => o.Age).Skip(13).ToShardingListAsync(); var modsDesc = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "3").OrderByDescending(o => o.Age).Skip(13).ToListAsync();
// Assert.Equal(986, modsDesc.Count); Assert.Equal(986, modsDesc.Count);
// Assert.DoesNotContain(mods, o => o.Id == "3"); Assert.DoesNotContain(mods, o => o.Id == "3");
// Assert.Equal(987, modsDesc[0].Age); Assert.Equal(987, modsDesc[0].Age);
// Assert.Equal(986, modsDesc[1].Age); Assert.Equal(986, modsDesc[1].Age);
//} }
//[Fact] [Fact]
//public async Task ToList_Name_Eq_Test() public async Task ToList_Name_Eq_Test()
//{ {
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_3").ToShardingListAsync(); var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_3").ToListAsync();
// Assert.Single(mods); Assert.Single(mods);
// Assert.Equal("3", mods[0].Id); Assert.Equal("3", mods[0].Id);
//} }
//[Fact] [Fact]
//public async Task ToList_Id_Eq_Not_In_Db_Test() public async Task ToList_Id_Eq_Not_In_Db_Test()
//{ {
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1001").ToShardingListAsync(); var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1001").ToListAsync();
// Assert.Empty(mods); Assert.Empty(mods);
//} }
//[Fact] [Fact]
//public async Task ToList_Name_Eq_Not_In_Db_Test() public async Task ToList_Name_Eq_Not_In_Db_Test()
//{ {
// var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ToShardingListAsync(); var mods = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ToListAsync();
// Assert.Empty(mods); Assert.Empty(mods);
//} }
//[Fact] [Fact]
//public async Task FirstOrDefault_Order_By_Id_Test() public async Task FirstOrDefault_Order_By_Id_Test()
//{ {
// var sysUserModAge = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).ShardingFirstOrDefaultAsync(); var sysUserModAge = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Age).FirstOrDefaultAsync();
// Assert.True(sysUserModAge != null && sysUserModAge.Id == "1"); Assert.True(sysUserModAge != null && sysUserModAge.Id == "1");
// var sysUserModAgeDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).ShardingFirstOrDefaultAsync(); var sysUserModAgeDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Age).FirstOrDefaultAsync();
// Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000"); Assert.True(sysUserModAgeDesc != null && sysUserModAgeDesc.Id == "1000");
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Id).ShardingFirstOrDefaultAsync(); var sysUserMod = await _virtualDbContext.Set<SysUserMod>().OrderBy(o => o.Id).FirstOrDefaultAsync();
// Assert.True(sysUserMod != null && sysUserMod.Id == "1"); Assert.True(sysUserMod != null && sysUserMod.Id == "1");
// var sysUserModDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Id).ShardingFirstOrDefaultAsync(); var sysUserModDesc = await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o => o.Id).FirstOrDefaultAsync();
// Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999"); Assert.True(sysUserModDesc != null && sysUserModDesc.Id == "999");
//} }
//[Fact] [Fact]
//public async Task FirstOrDefault2() public async Task FirstOrDefault2()
//{ {
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1").ShardingFirstOrDefaultAsync(); var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "1").FirstOrDefaultAsync();
// Assert.NotNull(sysUserMod); Assert.NotNull(sysUserMod);
// Assert.True(sysUserMod.Id == "1"); Assert.True(sysUserMod.Id == "1");
//} }
//[Fact] [Fact]
//public async Task FirstOrDefault3() public async Task FirstOrDefault3()
//{ {
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2").ShardingFirstOrDefaultAsync(); var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_2").FirstOrDefaultAsync();
// Assert.NotNull(sysUserMod); Assert.NotNull(sysUserMod);
// Assert.Equal("2", sysUserMod.Id); Assert.Equal("2", sysUserMod.Id);
//} }
//[Fact] [Fact]
//public async Task FirstOrDefault4() public async Task FirstOrDefault4()
//{ {
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "1").ShardingFirstOrDefaultAsync(); var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Id != "1").FirstOrDefaultAsync();
// Assert.NotNull(sysUserMod); Assert.NotNull(sysUserMod);
// Assert.True(sysUserMod.Id != "1"); Assert.True(sysUserMod.Id != "1");
//} }
//[Fact] [Fact]
//public async Task FirstOrDefault5() public async Task FirstOrDefault5()
//{ {
// var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").ShardingFirstOrDefaultAsync(); var sysUserMod = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1001").FirstOrDefaultAsync();
// Assert.Null(sysUserMod); Assert.Null(sysUserMod);
//} }
//[Fact] [Fact]
//public async Task Count_Test() public async Task Count_Test()
//{ {
// var a = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1000").ShardingCountAsync(); var a = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name == "name_1000").CountAsync();
// Assert.Equal(1, a); Assert.Equal(1, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").ShardingCountAsync(); var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").CountAsync();
// Assert.Equal(999, b); Assert.Equal(999, b);
//} }
//[Fact] [Fact]
//public async Task Sum_Test() public async Task Sum_Test()
//{ {
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingSumAsync(o => o.Age); var a = await _virtualDbContext.Set<SysUserMod>().SumAsync(o => o.Age);
// var expected = 0; var expected = 0;
// for (int i = 1; i <= 1000; i++) for (int i = 1; i <= 1000; i++)
// { {
// expected += i; expected += i;
// } }
// Assert.Equal(expected, a); Assert.Equal(expected, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").ShardingSumAsync(o => o.Age); var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").SumAsync(o => o.Age);
// Assert.Equal(expected - 1000, b); Assert.Equal(expected - 1000, b);
//} }
//[Fact] [Fact]
//public async Task Max_Test() public async Task Max_Test()
//{ {
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingMaxAsync(o => o.Age); var a = await _virtualDbContext.Set<SysUserMod>().MaxAsync(o => o.Age);
// Assert.Equal(1000, a); Assert.Equal(1000, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").ShardingMaxAsync(o => o.Age); var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1000").MaxAsync(o => o.Age);
// Assert.Equal(999, b); Assert.Equal(999, b);
// var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age < 500).ShardingMaxAsync(o => o.Age); var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age < 500).MaxAsync(o => o.Age);
// Assert.Equal(499, c); Assert.Equal(499, c);
// var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age <= 500).ShardingMaxAsync(o => o.Age); var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age <= 500).MaxAsync(o => o.Age);
// Assert.Equal(500, e); Assert.Equal(500, e);
//} }
//[Fact] [Fact]
//public async Task Max_Join_Test() public async Task Max_Join_Test()
//{ {
// var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300") var queryable = (from u in _virtualDbContext.Set<SysUserMod>().Where(o => o.Id == "300")
// join salary in _virtualDbContext.Set<SysUserSalary>() join salary in _virtualDbContext.Set<SysUserSalary>()
// on u.Id equals salary.UserId on u.Id equals salary.UserId
// select new select new
// { {
// Salary = salary.Salary, Salary = salary.Salary,
// DateOfMonth = salary.DateOfMonth, DateOfMonth = salary.DateOfMonth,
// Name = u.Name Name = u.Name
// }); });
// var maxSalary = await queryable.ShardingMaxAsync(o => o.Salary); var maxSalary = await queryable.MaxAsync(o => o.Salary);
// Assert.Equal(1390000, maxSalary); Assert.Equal(1390000, maxSalary);
//} }
//[Fact] [Fact]
//public async Task Min_Test() public async Task Min_Test()
//{ {
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingMinAsync(o => o.Age); var a = await _virtualDbContext.Set<SysUserMod>().MinAsync(o => o.Age);
// Assert.Equal(1, a); Assert.Equal(1, a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").ShardingMinAsync(o => o.Age); var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").MinAsync(o => o.Age);
// Assert.Equal(2, b); Assert.Equal(2, b);
// var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).ShardingMinAsync(o => o.Age); var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).MinAsync(o => o.Age);
// Assert.Equal(501, c); Assert.Equal(501, c);
// var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).ShardingMinAsync(o => o.Age); var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).MinAsync(o => o.Age);
// Assert.Equal(500, e); Assert.Equal(500, e);
//} }
//[Fact] [Fact]
//public async Task Any_Test() public async Task Any_Test()
//{ {
// var a = await _virtualDbContext.Set<SysUserMod>().ShardingAnyAsync(o => o.Age == 100); var a = await _virtualDbContext.Set<SysUserMod>().AnyAsync(o => o.Age == 100);
// Assert.True(a); Assert.True(a);
// var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").ShardingAnyAsync(o => o.Age == 1); var b = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Name != "name_1").AnyAsync(o => o.Age == 1);
// Assert.False(b); Assert.False(b);
// var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).ShardingAnyAsync(o => o.Age <= 500); var c = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age > 500).AnyAsync(o => o.Age <= 500);
// Assert.False(c); Assert.False(c);
// var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).ShardingAnyAsync(o => o.Age <= 500); var e = await _virtualDbContext.Set<SysUserMod>().Where(o => o.Age >= 500).AnyAsync(o => o.Age <= 500);
// Assert.True(e); Assert.True(e);
//} }
//[Fact] [Fact]
//public async Task Group_Test() public async Task Group_Test()
//{ {
// var ids = new[] {"200", "300"}; var ids = new[] {"200", "300"};
// var dateOfMonths = new[] {202111, 202110}; var dateOfMonths = new[] {202111, 202110};
// var group = await (from u in _virtualDbContext.Set<SysUserSalary>() var group = await (from u in _virtualDbContext.Set<SysUserSalary>()
// .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth)) .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
// group u by new group u by new
// { {
// UId = u.UserId UId = u.UserId
// } }
// into g into g
// select new select new
// { {
// GroupUserId = g.Key.UId, GroupUserId = g.Key.UId,
// Count = g.Count(), Count = g.Count(),
// TotalSalary = g.Sum(o => o.Salary), TotalSalary = g.Sum(o => o.Salary),
// AvgSalary = g.Average(o => o.Salary), AvgSalary = g.Average(o => o.Salary),
// AvgSalaryDecimal = g.Average(o => o.SalaryDecimal), AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
// MinSalary = g.Min(o => o.Salary), MinSalary = g.Min(o => o.Salary),
// MaxSalary = g.Max(o => o.Salary) MaxSalary = g.Max(o => o.Salary)
// }).ToShardingListAsync(); }).ToListAsync();
// Assert.Equal(2, group.Count); Assert.Equal(2, group.Count);
// Assert.Equal(2, group[0].Count); Assert.Equal(2, group[0].Count);
// Assert.Equal(2260000, group[0].TotalSalary); Assert.Equal(2260000, group[0].TotalSalary);
// Assert.Equal(1130000, group[0].AvgSalary); Assert.Equal(1130000, group[0].AvgSalary);
// Assert.Equal(11300, group[0].AvgSalaryDecimal); Assert.Equal(11300, group[0].AvgSalaryDecimal);
// Assert.Equal(1120000, group[0].MinSalary); Assert.Equal(1120000, group[0].MinSalary);
// Assert.Equal(1140000, group[0].MaxSalary); Assert.Equal(1140000, group[0].MaxSalary);
//} }
//[Fact] // [Fact]
//public async Task Group_API_Test() // public async Task Group_API_Test()
//{ // {
// var ids = new[] {"200", "300"}; // var ids = new[] {"200", "300"};
// var dateOfMonths = new[] {202111, 202110}; // var dateOfMonths = new[] {202111, 202110};
// var group = await _virtualDbContext.Set<SysUserSalary>() // var group = await _virtualDbContext.Set<SysUserSalary>()
// .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth)) // .Where(o => ids.Contains(o.UserId) && dateOfMonths.Contains(o.DateOfMonth))
// .ShardingGroupByAsync(g => new {UId = g.UserId}, g => new // .ShardingGroupByAsync(g => new {UId = g.UserId}, g => new
// { // {
//
// GroupUserId = g.Key.UId, // GroupUserId = g.Key.UId,
// Count = g.Count(), // Count = g.Count(),
// TotalSalary = g.Sum(o => o.Salary), // TotalSalary = g.Sum(o => o.Salary),
// AvgSalary = g.Average(o => o.Salary), // AvgSalary = g.Average(o => o.Salary),
// AvgSalaryDecimal = g.Average(o => o.SalaryDecimal), // AvgSalaryDecimal = g.Average(o => o.SalaryDecimal),
// MinSalary = g.Min(o => o.Salary), // MinSalary = g.Min(o => o.Salary),
// MaxSalary = g.Max(o => o.Salary) // MaxSalary = g.Max(o => o.Salary)
// }); // });
// Assert.Equal(2, group.Count); // Assert.Equal(2, group.Count);
// Assert.Equal(2, group[0].Count); // Assert.Equal(2, group[0].Count);
// Assert.Equal(2260000, group[0].TotalSalary); // Assert.Equal(2260000, group[0].TotalSalary);
// Assert.Equal(1130000, group[0].AvgSalary); // Assert.Equal(1130000, group[0].AvgSalary);
// Assert.Equal(11300, group[0].AvgSalaryDecimal); // Assert.Equal(11300, group[0].AvgSalaryDecimal);
// Assert.Equal(1120000, group[0].MinSalary); // Assert.Equal(1120000, group[0].MinSalary);
// Assert.Equal(1140000, group[0].MaxSalary); // Assert.Equal(1140000, group[0].MaxSalary);
//} // }
} }
} }

View File

@ -38,6 +38,7 @@ namespace ShardingCore.Test50
.ConfigureAppConfiguration(builder => .ConfigureAppConfiguration(builder =>
{ {
builder.AddJsonFile("Configs/DbConfig.json"); builder.AddJsonFile("Configs/DbConfig.json");
builder.AddJsonFile("Configs/MacDbConfig.json");
}); });
} }
@ -47,13 +48,13 @@ namespace ShardingCore.Test50
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) // ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
{ {
services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]) services.AddShardingDbContext<ShardingDefaultDbContext, DefaultDbContext>(o => o.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServerMac")["ConnectionString"])
,op => ,op =>
{ {
op.EnsureCreatedWithOutShardingTable = false; op.EnsureCreatedWithOutShardingTable = false;
op.CreateShardingTableOnStart = false; op.CreateShardingTableOnStart = false;
op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger), op.UseShardingOptionsBuilder((connection, builder) => builder.UseSqlServer(connection).UseLoggerFactory(efLogger),
builder=> builder.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]).UseLoggerFactory(efLogger)); builder=> builder.UseSqlServer(hostBuilderContext.Configuration.GetSection("SqlServerMac")["ConnectionString"]).UseLoggerFactory(efLogger));
op.AddShardingTableRoute<SysUserModVirtualTableRoute>(); op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>(); op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
}); });