修复多IShardingRuntimeContext只对应一个ServiceProvider的bug

This commit is contained in:
xuejiaming 2022-07-20 13:44:52 +08:00
parent 3fa09c8237
commit 8729d346a2
33 changed files with 369 additions and 137 deletions

View File

@ -35,7 +35,9 @@ namespace Sample.MySql.Controllers
var resultX = await _defaultTableDbContext.Set<SysUserMod>()
.Where(o => o.Id == "2" || o.Id == "3").FirstOrDefaultAsync();
var resultY = await _defaultTableDbContext.Set<SysUserMod>().FirstOrDefaultAsync(o => o.Id == "2" || o.Id == "3");
var shardingFirstOrDefaultAsyncxxx = await _defaultTableDbContext.Set<SysUserLogByMonth>().Where(o=>o.Time==DateTime.Now).ToListAsync();
var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync();
var result22 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2"&&o.Name=="ds1").ToListAsync();
var result1 = await _defaultTableDbContext.Set<SysUserMod>().Where(o => o.Id == "2" || o.Id == "3").ToListAsync();
var result2 = await _defaultTableDbContext.Set<SysUserLogByMonth>().Skip(1).Take(10).ToListAsync();
var shardingFirstOrDefaultAsync = await _defaultTableDbContext.Set<SysUserLogByMonth>().ToListAsync();

View File

@ -5,6 +5,8 @@ using Sample.MySql.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore.Internal;
using Sample.MySql.multi;
using ShardingCore.Bootstrappers;
namespace Sample.MySql
@ -21,6 +23,8 @@ namespace Sample.MySql
{
using (var scope=app.ApplicationServices.CreateScope())
{
var otherDbContext =scope.ServiceProvider.GetService<OtherDbContext>();
var any = otherDbContext.MyUsers.Any();
var virtualDbContext =scope.ServiceProvider.GetService<DefaultShardingDbContext>();
if (!virtualDbContext.Set<SysUserMod>().Any())
{
@ -51,6 +55,13 @@ namespace Sample.MySql
}
}
// using (var scope=app.ApplicationServices.CreateScope())
// {
//
// var virtualDbContext =scope.ServiceProvider.GetService<DefaultShardingDbContext>();
// var any = virtualDbContext.Set<SysUserMod>().Any();
// }
//using (var scope = app.ApplicationServices.CreateScope())
//{
// var dbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();

View File

@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.6">
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.7">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>

View File

@ -3,6 +3,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Sample.MySql.DbContexts;
using Sample.MySql.Domain.Entities;
using Sample.MySql.multi;
using Sample.MySql.Shardings;
using ShardingCore;
using ShardingCore.Bootstrappers;
@ -11,6 +12,7 @@ using ShardingCore.Core.RuntimeContexts;
using ShardingCore.EFCores;
using ShardingCore.Extensions;
using ShardingCore.Helpers;
using ShardingCore.Sharding.ReadWriteConfigurations;
using ShardingCore.TableExists;
using ShardingCore.TableExists.Abstractions;
@ -37,8 +39,10 @@ namespace Sample.MySql
{
public static readonly ILoggerFactory efLogger = LoggerFactory.Create(builder =>
{
builder.AddFilter((category, level) => category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
builder.AddFilter((category, level) =>
category == DbLoggerCategory.Database.Command.Name && level == LogLevel.Information).AddConsole();
});
public Startup(IConfiguration configuration)
{
Configuration = configuration;
@ -61,52 +65,90 @@ namespace Sample.MySql
// op.AddShardingTableRoute<SysUserModVirtualTableRoute>();
// op.AddShardingTableRoute<SysUserSalaryVirtualTableRoute>();
// });
services.AddMultiShardingDbContext<OtherDbContext>()
.UseRouteConfig(op => { op.AddShardingTableRoute<MyUserRoute>(); })
.UseConfig(o =>
{
o.ThrowIfQueryRouteNotMatch = false;
o.UseShardingQuery((conStr, builder) =>
{
builder.UseMySql(conStr, new MySqlServerVersion(new Version()))
.UseLoggerFactory(efLogger)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});
o.UseShardingTransaction((connection, builder) =>
{
builder
.UseMySql(connection, new MySqlServerVersion(new Version()))
.UseLoggerFactory(efLogger)
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});
o.UseShardingMigrationConfigure(b =>
{
b.ReplaceService<IMigrationsSqlGenerator, ShardingMySqlMigrationsSqlGenerator>();
});
o.AddDefaultDataSource("ds0",
"server=127.0.0.1;port=3306;database=dbdbdx;userid=root;password=root;");
}).AddShardingCore();
services.AddSingleton<IShardingRuntimeContext>(sp =>
{
Stopwatch stopwatch=Stopwatch.StartNew();
Stopwatch stopwatch = Stopwatch.StartNew();
var shardingRuntimeContext = new ShardingRuntimeBuilder<DefaultShardingDbContext>()
.UseRouteConfig(o =>
{
o.AddShardingTableRoute<SysUserLogByMonthRoute>();
o.AddShardingTableRoute<SysUserModVirtualTableRoute>();
o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
o.AddShardingDataSourceRoute<SysUserModVirtualDataSourceRoute>();
}).UseConfig(o =>
{
o.ThrowIfQueryRouteNotMatch = false;
o.UseShardingQuery((conStr,builder)=>
o.UseShardingQuery((conStr, builder) =>
{
builder.UseMySql(conStr, new MySqlServerVersion(new Version()))
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.UseLoggerFactory(efLogger)
.EnableSensitiveDataLogging();
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});
o.UseShardingTransaction((connection, builder) =>
{
builder
.UseMySql(connection, new MySqlServerVersion(new Version())).
UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.UseMySql(connection, new MySqlServerVersion(new Version()))
.UseLoggerFactory(efLogger)
.EnableSensitiveDataLogging();
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
});
o.AddDefaultDataSource("ds0", "server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
o.AddExtraDataSource(sp=>new Dictionary<string, string>()
o.AddDefaultDataSource("ds0",
"server=127.0.0.1;port=3306;database=dbdbd0;userid=root;password=root;");
o.AddExtraDataSource(sp => new Dictionary<string, string>()
{
{"ds1", "server=127.0.0.1;port=3306;database=dbdbd1;userid=root;password=root;"},
{"ds2", "server=127.0.0.1;port=3306;database=dbdbd2;userid=root;password=root;"}
{ "ds1", "server=127.0.0.1;port=3306;database=dbdbd1;userid=root;password=root;" },
{ "ds2", "server=127.0.0.1;port=3306;database=dbdbd2;userid=root;password=root;" }
});
o.AddReadWriteSeparation(sp =>
{
return new Dictionary<string, IEnumerable<string>>()
{
{
"ds0",
new[]
{
"server=127.0.0.1;port=3306;database=dbdbd0_0;userid=root;password=root;"
}
}
};
}, defaultEnable: true, readStrategyEnum: ReadStrategyEnum.Loop,
readConnStringGetStrategy: ReadConnStringGetStrategyEnum.LatestEveryTime);
o.UseShardingMigrationConfigure(b =>
{
b.ReplaceService<IMigrationsSqlGenerator, ShardingMySqlMigrationsSqlGenerator>();
});
}).ReplaceService<ITableEnsureManager,MySqlTableEnsureManager>(ServiceLifetime.Singleton)
})//.ReplaceService<ITableEnsureManager, MySqlTableEnsureManager>(ServiceLifetime.Singleton)
.Build(sp);
stopwatch.Stop();
Console.WriteLine("ShardingRuntimeContext build:"+stopwatch.ElapsedMilliseconds);
Console.WriteLine("ShardingRuntimeContext build:" + stopwatch.ElapsedMilliseconds);
return shardingRuntimeContext;
});
services.AddDbContext<DefaultShardingDbContext>(ShardingCoreExtension.UseDefaultSharding<DefaultShardingDbContext>);
services.AddDbContext<DefaultShardingDbContext>(ShardingCoreExtension
.UseMutliDefaultSharding<DefaultShardingDbContext>);
// services.AddShardingDbContext<DefaultShardingDbContext>()
// .AddEntityConfig(o =>
// {
@ -151,29 +193,56 @@ namespace Sample.MySql
{
app.UseDeveloperExceptionPage();
}
app.ApplicationServices.UseAutoShardingCreate();
var shardingRuntimeContext = app.ApplicationServices.GetRequiredService<IShardingRuntimeContext>();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
var entityMetadata = entityMetadataManager.TryGet<SysUserMod>();
using (var scope = app.ApplicationServices.CreateScope())
{
var defaultShardingDbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
// if (defaultShardingDbContext.Database.GetPendingMigrations().Any())
{
defaultShardingDbContext.Database.Migrate();
}
}
app.ApplicationServices.UseAutoTryCompensateTable(12);
var shardingRuntimeContextManager = app.ApplicationServices.GetRequiredService<IShardingRuntimeContextManager>();
var shardingRuntimeContexts = shardingRuntimeContextManager.GetAll();
foreach (var keyValuePair in shardingRuntimeContexts)
{
keyValuePair.Value.UseAutoShardingCreate();
keyValuePair.Value.UseAutoTryCompensateTable();
}
// app.ApplicationServices.UseAutoShardingCreate();
// var shardingRuntimeContext = app.ApplicationServices.GetRequiredService<IShardingRuntimeContext>();
// var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
// var entityMetadata = entityMetadataManager.TryGet<SysUserMod>();
// using (var scope = app.ApplicationServices.CreateScope())
// {
// var defaultShardingDbContext = scope.ServiceProvider.GetService<DefaultShardingDbContext>();
// // if (defaultShardingDbContext.Database.GetPendingMigrations().Any())
// {
// try
// {
//
// defaultShardingDbContext.Database.Migrate();
// }
// catch (Exception e)
// {
// }
// }
// }
// using (var scope = app.ApplicationServices.CreateScope())
// {
// var defaultShardingDbContext = scope.ServiceProvider.GetService<OtherDbContext>();
// // if (defaultShardingDbContext.Database.GetPendingMigrations().Any())
// {
// try
// {
//
// defaultShardingDbContext.Database.Migrate();
// }
// catch (Exception e)
// {
// }
// }
// }
//
// app.ApplicationServices.UseAutoTryCompensateTable(12);
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseEndpoints(endpoints => { endpoints.MapControllers(); });
// for (int i = 1; i < 500; i++)
// {
// using (var conn = new MySqlConnection(
@ -187,4 +256,4 @@ namespace Sample.MySql
app.DbSeed();
}
}
}
}

View File

@ -0,0 +1,8 @@
using System.ComponentModel.DataAnnotations.Schema;
namespace Sample.MySql.multi;
[Table("MyUser")]
public class MyUser
{
public string Id { get; set; }
}

View File

@ -0,0 +1,16 @@
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.VirtualRoutes.Mods;
namespace Sample.MySql.multi;
public class MyUserRoute:AbstractSimpleShardingModKeyStringVirtualTableRoute<MyUser>
{
public MyUserRoute() : base(1, 3)
{
}
public override void Configure(EntityMetadataTableBuilder<MyUser> builder)
{
builder.ShardingProperty(o => o.Id);
}
}

View File

@ -0,0 +1,16 @@
using Microsoft.EntityFrameworkCore;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Sharding;
using ShardingCore.Sharding.Abstractions;
namespace Sample.MySql.multi;
public class OtherDbContext:AbstractShardingDbContext,IShardingTableDbContext
{
public DbSet<MyUser> MyUsers { get; set; }
public OtherDbContext(DbContextOptions<OtherDbContext> options) : base(options)
{
}
public IRouteTail RouteTail { get; set; }
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
namespace ShardingCore.Core.RuntimeContexts
{
public interface IShardingRuntimeContextManager
{
/// <summary>
/// 尝试获取注册的dbcontext type对应的 没有返回null
/// </summary>
/// <param name="dbContextType"></param>
/// <returns></returns>
IShardingRuntimeContext TryGet(Type dbContextType);
IReadOnlyDictionary<Type, IShardingRuntimeContext> GetAll();
}
}

View File

@ -0,0 +1,32 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
namespace ShardingCore.Core.RuntimeContexts
{
public class ShardingRuntimeContextManager:IShardingRuntimeContextManager
{
private readonly ImmutableDictionary<Type, IShardingRuntimeContext> _caches;
public ShardingRuntimeContextManager(IEnumerable<IShardingRuntimeContext> shardingRuntimeContexts)
{
_caches = shardingRuntimeContexts.ToImmutableDictionary(o => o.DbContextType, o => o);
}
public IShardingRuntimeContext TryGet(Type dbContextType)
{
if (_caches.TryGetValue(dbContextType, out var shardingRuntimeContext))
{
return shardingRuntimeContext;
}
return null;
}
public IReadOnlyDictionary<Type, IShardingRuntimeContext> GetAll()
{
return _caches;
}
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
@ -19,15 +20,15 @@ namespace ShardingCore.EFCores.OptionsExtensions
#if EFCORE6
public class ShardingOptionsExtension : IDbContextOptionsExtension
{
private readonly IShardingRuntimeContext _shardingRuntimeContext;
public IShardingRuntimeContext ShardingRuntimeContext { get; }
public ShardingOptionsExtension(IShardingRuntimeContext shardingRuntimeContext)
{
_shardingRuntimeContext = shardingRuntimeContext;
ShardingRuntimeContext = shardingRuntimeContext;
}
public void ApplyServices(IServiceCollection services)
{
services.AddSingleton<IShardingRuntimeContext>(sp => _shardingRuntimeContext);
services.AddSingleton<IShardingRuntimeContext>(sp =>ShardingRuntimeContext);
}
public void Validate(IDbContextOptions options)
@ -35,15 +36,17 @@ namespace ShardingCore.EFCores.OptionsExtensions
}
public DbContextOptionsExtensionInfo Info => new ShardingWrapDbContextOptionsExtensionInfo(this);
public DbContextOptionsExtensionInfo Info => new ShardingOptionsExtensionInfo(this);
private class ShardingWrapDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo
private class ShardingOptionsExtensionInfo : DbContextOptionsExtensionInfo
{
public ShardingWrapDbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension)
private readonly ShardingOptionsExtension _shardingOptionsExtension;
public ShardingOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension)
{
_shardingOptionsExtension = (ShardingOptionsExtension)extension;
}
public override int GetServiceProviderHashCode() => 0;
public override int GetServiceProviderHashCode() => _shardingOptionsExtension.ShardingRuntimeContext.GetHashCode();
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other) => true;
@ -60,15 +63,15 @@ namespace ShardingCore.EFCores.OptionsExtensions
public class ShardingOptionsExtension: IDbContextOptionsExtension
{
private readonly IShardingRuntimeContext _shardingRuntimeContext;
public IShardingRuntimeContext ShardingRuntimeContext { get; }
public ShardingOptionsExtension(IShardingRuntimeContext shardingRuntimeContext)
{
_shardingRuntimeContext = shardingRuntimeContext;
ShardingRuntimeContext = shardingRuntimeContext;
}
public void ApplyServices(IServiceCollection services)
{
services.AddSingleton<IShardingRuntimeContext>(sp => _shardingRuntimeContext);
services.AddSingleton<IShardingRuntimeContext>(sp => ShardingRuntimeContext);
}
public void Validate(IDbContextOptions options)
@ -76,13 +79,18 @@ namespace ShardingCore.EFCores.OptionsExtensions
}
public DbContextOptionsExtensionInfo Info => new ShardingWrapDbContextOptionsExtensionInfo(this);
public DbContextOptionsExtensionInfo Info => new ShardingOptionsExtensionInfo(this);
private class ShardingWrapDbContextOptionsExtensionInfo : DbContextOptionsExtensionInfo
private class ShardingOptionsExtensionInfo : DbContextOptionsExtensionInfo
{
public ShardingWrapDbContextOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension) { }
private readonly ShardingOptionsExtension _shardingOptionsExtension;
public ShardingOptionsExtensionInfo(IDbContextOptionsExtension extension) : base(extension)
{
_shardingOptionsExtension = (ShardingOptionsExtension)extension;
}
public override long GetServiceProviderHashCode() => 0;
public override long GetServiceProviderHashCode() => _shardingOptionsExtension.ShardingRuntimeContext.GetHashCode();
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo) { }
@ -96,18 +104,18 @@ namespace ShardingCore.EFCores.OptionsExtensions
public class ShardingOptionsExtension: IDbContextOptionsExtension
{
private readonly IShardingRuntimeContext _shardingRuntimeContext;
public IShardingRuntimeContext ShardingRuntimeContext { get; }
public ShardingOptionsExtension(IShardingRuntimeContext shardingRuntimeContext)
{
_shardingRuntimeContext = shardingRuntimeContext;
ShardingRuntimeContext = shardingRuntimeContext;
}
public bool ApplyServices(IServiceCollection services)
{
services.AddSingleton<IShardingRuntimeContext>(sp => _shardingRuntimeContext);
services.AddSingleton<IShardingRuntimeContext>(sp => ShardingRuntimeContext);
return true;
}
public long GetServiceProviderHashCode() => 0;
public long GetServiceProviderHashCode() => ShardingRuntimeContext.GetHashCode();
public void Validate(IDbContextOptions options)
{

View File

@ -37,14 +37,14 @@ namespace ShardingCore.EFCores
public ShardingInternalDbSet(DbContext context, string entityTypeName) : base(context, entityTypeName)
{
_context = (IShardingDbContext)context;
_shardingRuntimeContext = context.GetService<IShardingRuntimeContext>();
_shardingRuntimeContext = context.GetShardingRuntimeContext();
}
#endif
#if EFCORE2 || EFCORE3
public ShardingInternalDbSet(DbContext context) : base(context)
{
_context = (IShardingDbContext)context;
_shardingRuntimeContext = context.GetService<IShardingRuntimeContext>();
_shardingRuntimeContext = context.GetShardingRuntimeContext();
}
#endif

View File

@ -16,7 +16,10 @@ namespace ShardingCore.EFCores
public class ShardingModelCacheKeyFactory : IModelCacheKeyFactory
{
public ShardingModelCacheKeyFactory()
{
Console.WriteLine("ShardingModelCacheKeyFactory");
}
public object Create(DbContext context)
{
return Create(context, false);

View File

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -11,6 +13,7 @@ using ShardingCore.Core;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.RuntimeContexts;
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
using ShardingCore.Extensions;
using ShardingCore.Extensions.InternalExtensions;
using ShardingCore.Sharding.Abstractions;
@ -38,8 +41,7 @@ namespace ShardingCore.EFCores
if (context is IShardingTableDbContext shardingTableDbContext&& shardingTableDbContext.RouteTail !=null&& shardingTableDbContext.RouteTail.IsShardingTableQuery())
{
var shardingRuntimeContext = context.GetService<IShardingRuntimeContext>();
var shardingRuntimeContext = context.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
var isMultiEntityQuery = shardingTableDbContext.RouteTail.IsMultiEntityQuery();
if (!isMultiEntityQuery)

View File

@ -29,6 +29,7 @@ namespace ShardingCore.EFCores
{
_shardingDbContext = currentContext.Context as IShardingDbContext ??
throw new ShardingCoreException("db context operator is not IShardingDbContext");
Console.WriteLine("ShardingQueryCompiler"+shardingRuntimeContext.DbContextType);
_shardingCompilerExecutor = shardingRuntimeContext.GetShardingCompilerExecutor();
}

View File

@ -17,6 +17,7 @@ using ShardingCore.Core;
using ShardingCore.Core.EntityMetadatas;
using ShardingCore.Core.RuntimeContexts;
using ShardingCore.EFCores;
using ShardingCore.EFCores.OptionsExtensions;
using ShardingCore.Exceptions;
using ShardingCore.Utils;
@ -42,7 +43,7 @@ namespace ShardingCore.Extensions
var contextModel = dbContext.Model as Model;
#endif
var shardingRuntimeContext = dbContext.GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = dbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
#if EFCORE6
@ -119,7 +120,7 @@ namespace ShardingCore.Extensions
var contextModel = dbContext.Model as Model;
#endif
var shardingRuntimeContext = dbContext.GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = dbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
#if EFCORE6
@ -327,15 +328,16 @@ namespace ShardingCore.Extensions
//return entry?.Entity;
}
public static TService GetRequireService<TService>(this DbContext dbContext) where TService:class
public static IShardingRuntimeContext GetShardingRuntimeContext(this DbContext dbContext)
{
var service = dbContext.GetService<TService>();
if (service == null)
var shardingRuntimeContext = dbContext.GetService<IShardingRuntimeContext>();
if (shardingRuntimeContext == null)
{
throw new ShardingCoreInvalidOperationException($"cant resolve:[{typeof(TService)}]");
throw new ShardingCoreInvalidOperationException($"cant resolve:[{typeof(IShardingRuntimeContext)}],dbcontext:[{dbContext}]");
}
return service;
return shardingRuntimeContext;
}
}

View File

@ -30,12 +30,6 @@ namespace ShardingCore.Extensions
return dbContext.GetService<IDbContextServices>().ContextOptions.FindExtension<UnionAllMergeOptionsExtension>() is not null;
}
public static IShardingRuntimeContext GetShardingRuntimeContext(this IShardingDbContext shardingDbContext)
{
return ((DbContext)shardingDbContext).GetRequireService<IShardingRuntimeContext>();
}
/// <summary>
/// 创建共享链接DbConnection
/// </summary>

View File

@ -89,7 +89,7 @@ namespace ShardingCore.Extensions
{
if (entities.IsEmpty())
return new Dictionary<string, Dictionary<DbContext, IEnumerable<TEntity>>>();
var shardingRuntimeContext = shardingDbContext.GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var entityType = typeof(TEntity);
var routeTailFactory = shardingRuntimeContext.GetRouteTailFactory();
var virtualDataSource = shardingDbContext.GetVirtualDataSource();
@ -225,7 +225,7 @@ namespace ShardingCore.Extensions
IEnumerable<TEntity> entities) where TShardingDbContext : DbContext, IShardingDbContext
where TEntity : class
{
var shardingRuntimeContext = shardingDbContext.GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();
if (entityMetadataManager.IsShardingDataSource(typeof(TEntity)))
throw new ShardingCoreInvalidOperationException(typeof(TEntity).FullName);
@ -246,7 +246,7 @@ namespace ShardingCore.Extensions
public static IDictionary<string, IEnumerable<DbContext>> BulkShardingExpression<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext, Expression<Func<TEntity, bool>> where) where TEntity : class
where TShardingDbContext : DbContext, IShardingDbContext
{
var shardingRuntimeContext = shardingDbContext.GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var routeTailFactory = shardingRuntimeContext.GetRouteTailFactory();
var dataSourceRouteManager = shardingRuntimeContext.GetDataSourceRouteManager();
var tableRouteManager = shardingRuntimeContext.GetTableRouteManager();// (IVirtualTableManager)ShardingContainer.GetService(typeof(IVirtualTableManager<>).GetGenericType0(shardingDbContext.GetType()));
@ -289,7 +289,7 @@ namespace ShardingCore.Extensions
public static IEnumerable<DbContext> BulkShardingTableExpression<TShardingDbContext, TEntity>(this TShardingDbContext shardingDbContext, Expression<Func<TEntity, bool>> where) where TEntity : class
where TShardingDbContext : DbContext, IShardingDbContext
{
var shardingRuntimeContext = shardingDbContext.GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var entityMetadataManager = shardingRuntimeContext.GetEntityMetadataManager();// (IEntityMetadataManager)ShardingContainer.GetService(typeof(IEntityMetadataManager<>).GetGenericType0(shardingDbContext.GetType()));
if (entityMetadataManager.IsShardingDataSource(typeof(TEntity)))
throw new ShardingCoreInvalidOperationException(typeof(TEntity).FullName);

View File

@ -44,7 +44,7 @@ namespace ShardingCore.Extensions.ShardingPageExtensions
public static async Task<ShardingPagedResult<T>> ToShardingPageAsync<T>(this IQueryable<T> source, int pageIndex, int pageSize)
{
var shardingDbContext = GetShardingDbContext(source);
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
//设置每次获取多少页
var take = pageSize <= 0 ? 1 : pageSize;
@ -79,7 +79,7 @@ namespace ShardingCore.Extensions.ShardingPageExtensions
public static ShardingPagedResult<T> ToShardingPage<T>(this IQueryable<T> source, int pageIndex, int pageSize)
{
var shardingDbContext = GetShardingDbContext(source);
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
//设置每次获取多少页
var take = pageSize <= 0 ? 1 : pageSize;
//设置当前页码最小1

View File

@ -58,7 +58,7 @@ namespace ShardingCore.Extensions
/// <param name="readOnly">是否是读数据源</param>
private static void SetReadWriteSeparation(this ISupportShardingReadWrite supportShardingReadWrite, bool readOnly)
{
var shardingRuntimeContext = ((DbContext)supportShardingReadWrite).GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = ((DbContext)supportShardingReadWrite).GetShardingRuntimeContext();
var shardingReadWriteManager =shardingRuntimeContext.GetService<IShardingReadWriteManager>();
var shardingReadWriteContext = shardingReadWriteManager.GetCurrent();
if (shardingReadWriteContext != null)
@ -86,7 +86,7 @@ namespace ShardingCore.Extensions
{
if (shardingDbContext.IsUseReadWriteSeparation())
{
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
var shardingReadWriteManager =shardingRuntimeContext.GetService<IShardingReadWriteManager>();
var shardingReadWriteContext = shardingReadWriteManager.GetCurrent();
if (shardingReadWriteContext != null)

View File

@ -27,7 +27,7 @@ namespace ShardingCore.Sharding.Enumerators.TrackerEnumerators
public AsyncTrackerEnumerator(IShardingDbContext shardingDbContext, IAsyncEnumerator<T> asyncEnumerator)
{
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
_shardingDbContext = shardingDbContext;
_asyncEnumerator = asyncEnumerator;
_queryTrack = shardingRuntimeContext.GetQueryTracker();
@ -70,7 +70,7 @@ namespace ShardingCore.Sharding.Enumerators.TrackerEnumerators
public AsyncTrackerEnumerator(IShardingDbContext shardingDbContext, IAsyncEnumerator<T> asyncEnumerator)
{
var shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
_shardingDbContext = shardingDbContext;
_asyncEnumerator = asyncEnumerator;
_queryTrack = shardingRuntimeContext.GetQueryTracker();

View File

@ -24,7 +24,7 @@ namespace ShardingCore.Sharding.Enumerators.TrackerEnumerators
public TrackerEnumerator(IShardingDbContext shardingDbContext,IEnumerator<T> enumerator)
{
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
_shardingDbContext = shardingDbContext;
_enumerator = enumerator;
_queryTrack = shardingRuntimeContext.GetQueryTracker();

View File

@ -5,6 +5,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ShardingCore.Extensions;
using ShardingCore.Sharding.Abstractions;
using ShardingCore.Sharding.Enumerators;
using ShardingCore.Sharding.Enumerators.StreamMergeAsync;
using ShardingCore.Sharding.MergeEngines.Abstractions;

View File

@ -42,7 +42,7 @@ namespace ShardingCore.Sharding.Parsers.Visitors
public ShardingQueryPrepareVisitor(IShardingDbContext shardingDbContext)
{
_shardingDbContext = shardingDbContext;
_trackerManager =shardingDbContext.GetShardingRuntimeContext()
_trackerManager =((DbContext)shardingDbContext).GetShardingRuntimeContext()
.GetTrackerManager();
}
public ShardingPrepareResult GetShardingPrepareResult()

View File

@ -124,7 +124,7 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors
DataSourceName = dataSourceName;
IsDefault = isDefault;
_shardingShellDbContext = shardingShellDbContext;
_shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
_shardingRuntimeContext = shardingShellDbContext.GetShardingRuntimeContext();
DbContextType = shardingShellDbContext.GetType();
_virtualDataSource =shardingDbContext
.GetVirtualDataSource();

View File

@ -64,7 +64,7 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors
{
_shardingDbContext = shardingDbContext;
//初始化
_shardingRuntimeContext = shardingDbContext.GetRequireService<IShardingRuntimeContext>();
_shardingRuntimeContext = shardingDbContext.GetShardingRuntimeContext();
_shardingRuntimeContext.GetOrCreateShardingRuntimeModel(shardingDbContext);
_virtualDataSource = _shardingRuntimeContext.GetVirtualDataSource();
_dataSourceRouteManager = _shardingRuntimeContext.GetDataSourceRouteManager();

View File

@ -55,13 +55,11 @@ namespace ShardingCore.Sharding.ShardingQueryExecutors
if (mergeQueryCompilerContext.IsEnumerableQuery())
{
return EnumerableExecute<TResult>(mergeQueryCompilerContext);
}
if (typeof(TResult).HasImplementedRawGeneric(typeof(Task<>)))
{
return DoExecute<TResult>(mergeQueryCompilerContext, true, cancellationToken);
}

View File

@ -101,7 +101,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
public static MergeQueryCompilerContext Create(IQueryCompilerContext queryCompilerContext, QueryCombineResult queryCombineResult, ShardingRouteResult shardingRouteResult)
{
var shardingDbContext = queryCompilerContext.GetShardingDbContext();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetRequireService<IShardingRuntimeContext>();
var shardingRuntimeContext = ((DbContext)shardingDbContext).GetShardingRuntimeContext();
return new MergeQueryCompilerContext(shardingRuntimeContext,queryCompilerContext, queryCombineResult,shardingRouteResult);
}
public Dictionary<Type,IQueryable> GetQueryEntities()

View File

@ -39,7 +39,7 @@ namespace ShardingCore.Sharding.ShardingExecutors
private QueryCompilerContext(IPrepareParseResult prepareParseResult)
{
_shardingRuntimeContext = ((DbContext)prepareParseResult.GetShardingDbContext()).GetRequireService<IShardingRuntimeContext>();
_shardingRuntimeContext = ((DbContext)prepareParseResult.GetShardingDbContext()).GetShardingRuntimeContext();
_shardingDbContext = prepareParseResult.GetShardingDbContext();
_queryExpression = prepareParseResult.GetNativeQueryExpression();
_shardingDbContextType = _shardingDbContext.GetType();

View File

@ -93,7 +93,7 @@ namespace ShardingCore.Sharding
RewriteQueryable = rewriteResult.GetRewriteQueryable();
OptimizeResult = optimizeResult;
_rewriteResult = rewriteResult;
ShardingRuntimeContext = mergeQueryCompilerContext.GetShardingDbContext().GetShardingRuntimeContext();
ShardingRuntimeContext = ((DbContext)mergeQueryCompilerContext.GetShardingDbContext()).GetShardingRuntimeContext();
_routeTailFactory = ShardingRuntimeContext.GetRouteTailFactory();
_trackerManager = ShardingRuntimeContext.GetTrackerManager();
_shardingConfigOptions = ShardingRuntimeContext.GetShardingConfigOptions();
@ -289,7 +289,7 @@ namespace ShardingCore.Sharding
public IShardingComparer GetShardingComparer()
{
return GetShardingDbContext().GetShardingRuntimeContext().GetRequiredService<IShardingComparer>();
return ((DbContext)GetShardingDbContext()).GetShardingRuntimeContext().GetShardingComparer();
}
/// <summary>

View File

@ -15,9 +15,8 @@ namespace ShardingCore.Core.Internal.Visitors
* @Date: Wednesday, 13 January 2021 11:31:01
* @Email: 326308290@qq.com
*/
public abstract class ShardingExpressionVisitor:ExpressionVisitor
public abstract class ShardingExpressionVisitor : ExpressionVisitor
{
//public object GetFieldValue(Expression expression)
//{
// if (expression is ConstantExpression)
@ -50,56 +49,67 @@ namespace ShardingCore.Core.Internal.Visitors
return field.GetValue(
GetExpressionValue(
e.Expression
) ?? throw new InvalidOperationException($"cant get expression value,{e.Expression.ShardingPrint()} may be null reference")
) ?? throw new InvalidOperationException(
$"cant get expression value,{e.Expression.ShardingPrint()} may be null reference")
);
case MemberExpression e when e.Member is PropertyInfo property:
{
if (e.Expression == null&&property.DeclaringType==typeof(DateTime)&&property.Name==nameof(DateTime.Now))
if (e.Expression == null)
{
return DateTime.Now;
}
else
{
return property.GetValue(
GetExpressionValue(
e.Expression
)??throw new InvalidOperationException($"cant get expression value,{e.Expression.ShardingPrint()} may be null reference")
);
if (property.DeclaringType == typeof(DateTime) && property.Name == nameof(DateTime.Now))
{
return DateTime.Now;
}
if (property.DeclaringType == typeof(DateTimeOffset) &&
property.Name == nameof(DateTimeOffset.Now))
{
return DateTimeOffset.Now;
}
}
return property.GetValue(
GetExpressionValue(
e.Expression
) ?? throw new InvalidOperationException(
$"cant get expression value,{e.Expression.ShardingPrint()} may be null reference")
);
}
case ListInitExpression e when e.NewExpression.Arguments.Count() == 0:
{
var collection = e.NewExpression.Constructor.Invoke(new object[0]);
foreach (var i in e.Initializers)
{
var collection = e.NewExpression.Constructor.Invoke(new object[0]);
foreach (var i in e.Initializers)
{
i.AddMethod.Invoke(
collection,
i.Arguments
.Select(
a => GetExpressionValue(a)
)
.ToArray()
);
}
return collection;
i.AddMethod.Invoke(
collection,
i.Arguments
.Select(
a => GetExpressionValue(a)
)
.ToArray()
);
}
return collection;
}
case NewArrayExpression e when e.NodeType == ExpressionType.NewArrayInit && e.Expressions.Count > 0:
{
var collection = new List<object>(e.Expressions.Count);
foreach (var arrayItemExpression in e.Expressions)
{
var collection = new List<object>(e.Expressions.Count);
foreach (var arrayItemExpression in e.Expressions)
{
collection.Add(GetExpressionValue(arrayItemExpression));
}
return collection;
collection.Add(GetExpressionValue(arrayItemExpression));
}
return collection;
}
case MethodCallExpression e:
{
var expressionValue = GetExpressionValue(e.Object);
return e.Method.Invoke(
expressionValue,
e.Arguments
@ -116,7 +126,8 @@ namespace ShardingCore.Core.Internal.Visitors
default:
{
if (expression is BinaryExpression binaryExpression&&expression.NodeType == ExpressionType.ArrayIndex)
if (expression is BinaryExpression binaryExpression &&
expression.NodeType == ExpressionType.ArrayIndex)
{
var index = GetExpressionValue(binaryExpression.Right);
if (index is int i)
@ -128,6 +139,7 @@ namespace ShardingCore.Core.Internal.Visitors
}
}
}
//TODO: better messaging
throw new ShardingCoreException("cant get value " + expression);
}

View File

@ -32,8 +32,8 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
</ItemGroup>
<ItemGroup>

View File

@ -91,6 +91,22 @@ namespace ShardingCore
return services.AddShardingConfigure<TShardingDbContext>();
}
public static ShardingCoreConfigBuilder<TShardingDbContext> AddMultiShardingDbContext<TShardingDbContext>(
this IServiceCollection services,
ServiceLifetime contextLifetime = ServiceLifetime.Scoped,
ServiceLifetime optionsLifetime = ServiceLifetime.Scoped)
where TShardingDbContext : DbContext, IShardingDbContext
{
if (contextLifetime == ServiceLifetime.Singleton)
throw new NotSupportedException($"{nameof(contextLifetime)}:{nameof(ServiceLifetime.Singleton)}");
if (optionsLifetime == ServiceLifetime.Singleton)
throw new NotSupportedException($"{nameof(optionsLifetime)}:{nameof(ServiceLifetime.Singleton)}");
services.AddDbContext<TShardingDbContext>(UseMutliDefaultSharding<TShardingDbContext>, contextLifetime,
optionsLifetime);
services.TryAddSingleton<IShardingRuntimeContextManager, ShardingRuntimeContextManager>();
return services.AddShardingConfigure<TShardingDbContext>();
}
public static ShardingCoreConfigBuilder<TShardingDbContext> AddShardingConfigure<TShardingDbContext>(
this IServiceCollection services)
where TShardingDbContext : DbContext, IShardingDbContext
@ -99,18 +115,36 @@ namespace ShardingCore
return new ShardingCoreConfigBuilder<TShardingDbContext>(services);
}
public static void UseDefaultSharding<TShardingDbContext>(this DbContextOptionsBuilder dbContextOptionsBuilder,IServiceProvider serviceProvider) where TShardingDbContext : DbContext, IShardingDbContext
public static void UseDefaultSharding<TShardingDbContext>(this DbContextOptionsBuilder dbContextOptionsBuilder,
IServiceProvider serviceProvider) where TShardingDbContext : DbContext, IShardingDbContext
{
var shardingRuntimeContext = serviceProvider.GetRequiredService<IShardingRuntimeContext>();
dbContextOptionsBuilder.UseDefaultSharding<TShardingDbContext>(shardingRuntimeContext);
}
public static void UseDefaultSharding<TShardingDbContext>(IServiceProvider serviceProvider,
DbContextOptionsBuilder dbContextOptionsBuilder) where TShardingDbContext : DbContext, IShardingDbContext
{
var shardingRuntimeContext = serviceProvider.GetRequiredService<IShardingRuntimeContext>();
dbContextOptionsBuilder.UseDefaultSharding<TShardingDbContext>(shardingRuntimeContext);
}
public static void UseDefaultSharding<TShardingDbContext>(this DbContextOptionsBuilder dbContextOptionsBuilder,IShardingRuntimeContext shardingRuntimeContext) where TShardingDbContext : DbContext, IShardingDbContext
public static void UseMutliDefaultSharding<TShardingDbContext>(IServiceProvider serviceProvider,
DbContextOptionsBuilder dbContextOptionsBuilder) where TShardingDbContext : DbContext, IShardingDbContext
{
var shardingRuntimeContextManager = serviceProvider.GetRequiredService<IShardingRuntimeContextManager>();
var shardingRuntimeContext = shardingRuntimeContextManager.TryGet(typeof(TShardingDbContext));
if (shardingRuntimeContext == null)
{
throw new InvalidOperationException(
$"cant get multi sharding runtime context:[{typeof(TShardingDbContext)}]");
}
dbContextOptionsBuilder.UseDefaultSharding<TShardingDbContext>(shardingRuntimeContext);
}
public static void UseDefaultSharding<TShardingDbContext>(this DbContextOptionsBuilder dbContextOptionsBuilder,
IShardingRuntimeContext shardingRuntimeContext) where TShardingDbContext : DbContext, IShardingDbContext
{
var shardingConfigOptions = shardingRuntimeContext.GetShardingConfigOptions();
shardingConfigOptions.ShardingMigrationConfigure?.Invoke(dbContextOptionsBuilder);
@ -211,6 +245,7 @@ namespace ShardingCore
.ReplaceService<IRelationalTransactionFactory,
ShardingRelationalTransactionFactory<TShardingDbContext>>();
}
public static DbContextOptionsBuilder UseShardingMigrator(
this DbContextOptionsBuilder optionsBuilder)
{
@ -221,6 +256,7 @@ namespace ShardingCore
public static DbContextOptionsBuilder UseShardingOptions(this DbContextOptionsBuilder optionsBuilder,
IShardingRuntimeContext shardingRuntimeContext)
{
var shardingOptionsExtension = optionsBuilder.CreateOrGetShardingOptionsExtension(shardingRuntimeContext);
((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(shardingOptionsExtension);
return optionsBuilder;
@ -240,9 +276,13 @@ namespace ShardingCore
new ShardingWrapOptionsExtension();
private static ShardingOptionsExtension CreateOrGetShardingOptionsExtension(
this DbContextOptionsBuilder optionsBuilder, IShardingRuntimeContext shardingRuntimeContext)
=> optionsBuilder.Options.FindExtension<ShardingOptionsExtension>() ??
new ShardingOptionsExtension(shardingRuntimeContext);
this DbContextOptionsBuilder optionsBuilder, IShardingRuntimeContext shardingRuntimeContext) =>
optionsBuilder.Options.FindExtension<ShardingOptionsExtension>() ??
new ShardingOptionsExtension(shardingRuntimeContext);
// private static CoreOptionsExtension CreateOrGetCoreOptionsExtension(
// this DbContextOptionsBuilder optionsBuilder) =>
// optionsBuilder.Options.FindExtension<CoreOptionsExtension>() ??
// new CoreOptionsExtension();
public static DbContextOptionsBuilder UseInnerDbContextSharding(this DbContextOptionsBuilder optionsBuilder)
{

View File

@ -41,8 +41,8 @@
<Compile Remove="..\..\src\ShardingCore\ShardingTableConfig.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.26" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.26" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.27" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="3.1.27" />
</ItemGroup>
</Project>