添加codefirst并且优化自动追踪
This commit is contained in:
parent
2a9d3fff98
commit
47ca273377
|
@ -45,6 +45,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src5x", "src5x", "{EB1C9149
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShardingCore.5x", "src5x\ShardingCore.5x\ShardingCore.5x.csproj", "{68A9F118-EF0A-4D03-8845-77D084561A28}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShardingCore.5x", "src5x\ShardingCore.5x\ShardingCore.5x.csproj", "{68A9F118-EF0A-4D03-8845-77D084561A28}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sample.Migrations", "samples\Sample.Migrations\Sample.Migrations.csproj", "{648DCBBE-BE8F-4EAC-8367-FE7BC558DA8C}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -111,6 +113,10 @@ Global
|
||||||
{68A9F118-EF0A-4D03-8845-77D084561A28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{68A9F118-EF0A-4D03-8845-77D084561A28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{68A9F118-EF0A-4D03-8845-77D084561A28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{68A9F118-EF0A-4D03-8845-77D084561A28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{68A9F118-EF0A-4D03-8845-77D084561A28}.Release|Any CPU.Build.0 = Release|Any CPU
|
{68A9F118-EF0A-4D03-8845-77D084561A28}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{648DCBBE-BE8F-4EAC-8367-FE7BC558DA8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{648DCBBE-BE8F-4EAC-8367-FE7BC558DA8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{648DCBBE-BE8F-4EAC-8367-FE7BC558DA8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{648DCBBE-BE8F-4EAC-8367-FE7BC558DA8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -131,6 +137,7 @@ Global
|
||||||
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686} = {CC2C88C0-65F2-445D-BE78-973B840FE281}
|
{E4DAA43A-B64D-45CF-81B8-7B8FD338D686} = {CC2C88C0-65F2-445D-BE78-973B840FE281}
|
||||||
{0193E3CF-F2FD-449A-B2D5-7F68E551FDBF} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
{0193E3CF-F2FD-449A-B2D5-7F68E551FDBF} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
||||||
{68A9F118-EF0A-4D03-8845-77D084561A28} = {EB1C9149-78C9-4D99-BE3F-B80FE2015E96}
|
{68A9F118-EF0A-4D03-8845-77D084561A28} = {EB1C9149-78C9-4D99-BE3F-B80FE2015E96}
|
||||||
|
{648DCBBE-BE8F-4EAC-8367-FE7BC558DA8C} = {EDF8869A-C1E1-491B-BC9F-4A33F4DE1C73}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {8C07A667-E8B4-43C7-8053-721584BAD291}
|
SolutionGuid = {8C07A667-E8B4-43C7-8053-721584BAD291}
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace Sample.BulkConsole
|
||||||
var queryable = myShardingDbContext.Set<Order>().Where(o => o.CreateTime >= b).OrderBy(o => o.CreateTime);
|
var queryable = myShardingDbContext.Set<Order>().Where(o => o.CreateTime >= b).OrderBy(o => o.CreateTime);
|
||||||
var startNew1 = Stopwatch.StartNew();
|
var startNew1 = Stopwatch.StartNew();
|
||||||
|
|
||||||
int skip = 0, take = 10;
|
int skip = 0, take = 1000;
|
||||||
for (int i = 20000; i < 30000; i++)
|
for (int i = 20000; i < 30000; i++)
|
||||||
{
|
{
|
||||||
skip = take * i;
|
skip = take * i;
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Sample.Migrations.EFCores;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class WeatherForecastController : ControllerBase
|
||||||
|
{
|
||||||
|
private static readonly string[] Summaries = new[]
|
||||||
|
{
|
||||||
|
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly ILogger<WeatherForecastController> _logger;
|
||||||
|
private readonly DefaultShardingTableDbContext _context;
|
||||||
|
|
||||||
|
public WeatherForecastController(ILogger<WeatherForecastController> logger,DefaultShardingTableDbContext context)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IEnumerable<WeatherForecast> Get()
|
||||||
|
{
|
||||||
|
_context.Database.Migrate();
|
||||||
|
var rng = new Random();
|
||||||
|
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
|
||||||
|
{
|
||||||
|
Date = DateTime.Now.AddDays(index),
|
||||||
|
TemperatureC = rng.Next(-20, 55),
|
||||||
|
Summary = Summaries[rng.Next(Summaries.Length)]
|
||||||
|
})
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Design;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Sample.Migrations.EFCores;
|
||||||
|
using ShardingCore;
|
||||||
|
|
||||||
|
namespace Sample.Migrations
|
||||||
|
{
|
||||||
|
public class DefaultDesignTimeDbContextFactory: IDesignTimeDbContextFactory<DefaultShardingTableDbContext>
|
||||||
|
{
|
||||||
|
static DefaultDesignTimeDbContextFactory()
|
||||||
|
{
|
||||||
|
var services = new ServiceCollection();
|
||||||
|
services.AddShardingDbContext<DefaultShardingTableDbContext, DefaultTableDbContext>(
|
||||||
|
o =>
|
||||||
|
o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBMigration;Integrated Security=True;")
|
||||||
|
.ReplaceService<IMigrationsSqlGenerator, ShardingSqlServerMigrationsSqlGenerator<DefaultShardingTableDbContext>>()
|
||||||
|
).Begin(o =>
|
||||||
|
{
|
||||||
|
o.CreateShardingTableOnStart = true;
|
||||||
|
o.EnsureCreatedWithOutShardingTable = true;
|
||||||
|
o.AutoTrackEntity = true;
|
||||||
|
})
|
||||||
|
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr)
|
||||||
|
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
|
||||||
|
.AddShardingTransaction((connection, builder) =>
|
||||||
|
builder.UseSqlServer(connection))
|
||||||
|
.AddDefaultDataSource("ds0",
|
||||||
|
"Data Source=localhost;Initial Catalog=ShardingCoreDBMigration;Integrated Security=True;")
|
||||||
|
.AddShardingTableRoute(o =>
|
||||||
|
{
|
||||||
|
o.AddShardingTableRoute<ShardingWithModVirtualTableRoute>();
|
||||||
|
o.AddShardingTableRoute<ShardingWithDateTimeVirtualTableRoute>();
|
||||||
|
}).End();
|
||||||
|
services.AddLogging();
|
||||||
|
var buildServiceProvider = services.BuildServiceProvider();
|
||||||
|
ShardingContainer.SetServices(buildServiceProvider);
|
||||||
|
new ShardingBootstrapper(buildServiceProvider).Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultShardingTableDbContext CreateDbContext(string[] args)
|
||||||
|
{
|
||||||
|
var dbContextOptions = new DbContextOptionsBuilder<DefaultShardingTableDbContext>().UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBMigration;Integrated Security=True;").Options;
|
||||||
|
return new DefaultShardingTableDbContext(dbContextOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using ShardingCore.Sharding;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.EFCores
|
||||||
|
{
|
||||||
|
public class DefaultShardingTableDbContext:AbstractShardingDbContext<DefaultTableDbContext>
|
||||||
|
{
|
||||||
|
public DefaultShardingTableDbContext(DbContextOptions options) : base(options)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
modelBuilder.ApplyConfiguration(new NoShardingTableMap());
|
||||||
|
modelBuilder.ApplyConfiguration(new ShardingWithModMap());
|
||||||
|
modelBuilder.ApplyConfiguration(new ShardingWithDateTimeMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using ShardingCore.Core.VirtualRoutes.TableRoutes.RouteTails.Abstractions;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.EFCores
|
||||||
|
{
|
||||||
|
public class DefaultTableDbContext:DbContext,IShardingTableDbContext
|
||||||
|
{
|
||||||
|
public DefaultTableDbContext(DbContextOptions<DefaultTableDbContext> options):base(options)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(modelBuilder);
|
||||||
|
modelBuilder.ApplyConfiguration(new NoShardingTableMap());
|
||||||
|
modelBuilder.ApplyConfiguration(new ShardingWithModMap());
|
||||||
|
modelBuilder.ApplyConfiguration(new ShardingWithDateTimeMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
public IRouteTail RouteTail { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.EFCores
|
||||||
|
{
|
||||||
|
public class NoShardingTable
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Age { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NoShardingTableMap : IEntityTypeConfiguration<NoShardingTable>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<NoShardingTable> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(o => o.Id);
|
||||||
|
builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(128);
|
||||||
|
builder.Property(o => o.Name).HasMaxLength(128);
|
||||||
|
builder.ToTable(nameof(NoShardingTable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using ShardingCore.Helpers;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.EFCores
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// https://github.com/Coldairarrow/EFCore.Sharding/blob/master/src/EFCore.Sharding.SqlServer/ShardingSqlServerMigrationsSqlGenerator.cs
|
||||||
|
/// </summary>
|
||||||
|
public class ShardingSqlServerMigrationsSqlGenerator<TShardingDbContext> : SqlServerMigrationsSqlGenerator where TShardingDbContext:DbContext,IShardingDbContext
|
||||||
|
{
|
||||||
|
public ShardingSqlServerMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IRelationalAnnotationProvider migrationsAnnotations) : base(dependencies, migrationsAnnotations)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
protected override void Generate(
|
||||||
|
MigrationOperation operation,
|
||||||
|
IModel model,
|
||||||
|
MigrationCommandListBuilder builder)
|
||||||
|
{
|
||||||
|
var oldCmds = builder.GetCommandList().ToList();
|
||||||
|
base.Generate(operation, model, builder);
|
||||||
|
var newCmds = builder.GetCommandList().ToList();
|
||||||
|
var addCmds = newCmds.Where(x => !oldCmds.Contains(x)).ToList();
|
||||||
|
|
||||||
|
MigrationHelper.Generate<TShardingDbContext>(operation, builder, Dependencies.SqlGenerationHelper, addCmds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using ShardingCore.Core;
|
||||||
|
using ShardingCore.VirtualRoutes.Months;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.EFCores
|
||||||
|
{
|
||||||
|
public class ShardingWithDateTime:IShardingTable
|
||||||
|
{
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Age { get; set; }
|
||||||
|
[ShardingTableKey]
|
||||||
|
public DateTime CreateTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShardingWithDateTimeMap : IEntityTypeConfiguration<ShardingWithDateTime>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ShardingWithDateTime> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(o => o.Id);
|
||||||
|
builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(128);
|
||||||
|
builder.Property(o => o.Name).HasMaxLength(128);
|
||||||
|
builder.ToTable(nameof(ShardingWithDateTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class ShardingWithDateTimeVirtualTableRoute : AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute<ShardingWithDateTime>
|
||||||
|
{
|
||||||
|
public override DateTime GetBeginTime()
|
||||||
|
{
|
||||||
|
return new DateTime(2021, 9, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||||
|
using ShardingCore.Core;
|
||||||
|
using ShardingCore.VirtualRoutes.Mods;
|
||||||
|
using ShardingCore.VirtualRoutes.Months;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.EFCores
|
||||||
|
{
|
||||||
|
public class ShardingWithMod:IShardingTable
|
||||||
|
{
|
||||||
|
[ShardingTableKey]
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Age { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShardingWithModMap : IEntityTypeConfiguration<ShardingWithMod>
|
||||||
|
{
|
||||||
|
public void Configure(EntityTypeBuilder<ShardingWithMod> builder)
|
||||||
|
{
|
||||||
|
builder.HasKey(o => o.Id);
|
||||||
|
builder.Property(o => o.Id).IsRequired().IsUnicode(false).HasMaxLength(128);
|
||||||
|
builder.Property(o => o.Name).HasMaxLength(128);
|
||||||
|
builder.ToTable(nameof(ShardingWithMod));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class ShardingWithModVirtualTableRoute : AbstractSimpleShardingModKeyStringVirtualTableRoute<ShardingWithMod>
|
||||||
|
{
|
||||||
|
public ShardingWithModVirtualTableRoute() : base(2, 3)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
samples/Sample.Migrations/Migrations/ShardingMigrations/20211006202136_EFCoreSharding.Designer.cs
generated
Normal file
86
samples/Sample.Migrations/Migrations/ShardingMigrations/20211006202136_EFCoreSharding.Designer.cs
generated
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Sample.Migrations.EFCores;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.Migrations.ShardingMigrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DefaultShardingTableDbContext))]
|
||||||
|
[Migration("20211006202136_EFCoreSharding")]
|
||||||
|
partial class EFCoreSharding
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||||
|
.HasAnnotation("ProductVersion", "5.0.10")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sample.Migrations.EFCores.NoShardingTable", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.IsUnicode(false)
|
||||||
|
.HasColumnType("varchar(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Age")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("NoShardingTable");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sample.Migrations.EFCores.ShardingWithDateTime", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.IsUnicode(false)
|
||||||
|
.HasColumnType("varchar(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Age")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ShardingWithDateTime");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sample.Migrations.EFCores.ShardingWithMod", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.IsUnicode(false)
|
||||||
|
.HasColumnType("varchar(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Age")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ShardingWithMod");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.Migrations.ShardingMigrations
|
||||||
|
{
|
||||||
|
public partial class EFCoreSharding : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "NoShardingTable",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<string>(type: "varchar(128)", unicode: false, maxLength: 128, nullable: false),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||||
|
Age = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_NoShardingTable", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShardingWithDateTime",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<string>(type: "varchar(128)", unicode: false, maxLength: 128, nullable: false),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||||
|
Age = table.Column<int>(type: "int", nullable: false),
|
||||||
|
CreateTime = table.Column<DateTime>(type: "datetime2", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShardingWithDateTime", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ShardingWithMod",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<string>(type: "varchar(128)", unicode: false, maxLength: 128, nullable: false),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: true),
|
||||||
|
Age = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ShardingWithMod", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "NoShardingTable");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ShardingWithDateTime");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ShardingWithMod");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Sample.Migrations.EFCores;
|
||||||
|
|
||||||
|
namespace Sample.Migrations.Migrations.ShardingMigrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(DefaultShardingTableDbContext))]
|
||||||
|
partial class DefaultShardingTableDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128)
|
||||||
|
.HasAnnotation("ProductVersion", "5.0.10")
|
||||||
|
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sample.Migrations.EFCores.NoShardingTable", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.IsUnicode(false)
|
||||||
|
.HasColumnType("varchar(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Age")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("NoShardingTable");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sample.Migrations.EFCores.ShardingWithDateTime", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.IsUnicode(false)
|
||||||
|
.HasColumnType("varchar(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Age")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ShardingWithDateTime");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Sample.Migrations.EFCores.ShardingWithMod", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.IsUnicode(false)
|
||||||
|
.HasColumnType("varchar(128)");
|
||||||
|
|
||||||
|
b.Property<int>("Age")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(128)
|
||||||
|
.HasColumnType("nvarchar(128)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ShardingWithMod");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Sample.Migrations
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
CreateHostBuilder(args).Build().Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||||
|
Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:7924",
|
||||||
|
"sslPort": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "weatherforecast",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Sample.Migrations": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": "true",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "weatherforecast",
|
||||||
|
"applicationUrl": "http://localhost:5000",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.10">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\ShardingCore\ShardingCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
|
@ -0,0 +1,78 @@
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Sample.Migrations.EFCores;
|
||||||
|
using ShardingCore;
|
||||||
|
|
||||||
|
namespace Sample.Migrations
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Startup(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
|
||||||
|
services.AddControllers();
|
||||||
|
|
||||||
|
services.AddShardingDbContext<DefaultShardingTableDbContext, DefaultTableDbContext>(
|
||||||
|
o =>
|
||||||
|
o.UseSqlServer("Data Source=localhost;Initial Catalog=ShardingCoreDBMigration;Integrated Security=True;")
|
||||||
|
.ReplaceService<IMigrationsSqlGenerator,ShardingSqlServerMigrationsSqlGenerator<DefaultShardingTableDbContext>>()
|
||||||
|
).Begin(o =>
|
||||||
|
{
|
||||||
|
o.CreateShardingTableOnStart = false;
|
||||||
|
o.EnsureCreatedWithOutShardingTable = false;
|
||||||
|
o.AutoTrackEntity = true;
|
||||||
|
})
|
||||||
|
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr)
|
||||||
|
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
|
||||||
|
.AddShardingTransaction((connection, builder) =>
|
||||||
|
builder.UseSqlServer(connection))
|
||||||
|
.AddDefaultDataSource("ds0",
|
||||||
|
"Data Source=localhost;Initial Catalog=ShardingCoreDBMigration;Integrated Security=True;")
|
||||||
|
.AddShardingTableRoute(o =>
|
||||||
|
{
|
||||||
|
o.AddShardingTableRoute<ShardingWithModVirtualTableRoute>();
|
||||||
|
o.AddShardingTableRoute<ShardingWithDateTimeVirtualTableRoute>();
|
||||||
|
}).End();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
if (env.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
var shardingBootstrapper = app.ApplicationServices.GetRequiredService<IShardingBootstrapper>();
|
||||||
|
shardingBootstrapper.Start();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Sample.Migrations
|
||||||
|
{
|
||||||
|
public class WeatherForecast
|
||||||
|
{
|
||||||
|
public DateTime Date { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureC { get; set; }
|
||||||
|
|
||||||
|
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||||
|
|
||||||
|
public string Summary { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
|
@ -34,7 +34,7 @@
|
||||||
// [HttpGet]
|
// [HttpGet]
|
||||||
// public async Task<IActionResult> Get()
|
// public async Task<IActionResult> Get()
|
||||||
// {
|
// {
|
||||||
// var taleAllTails = _virtualTableManager.GetVirtualTable(typeof(SysUserLogByMonth)).GetTaleAllTails();
|
// var taleAllTails = _virtualTableManager.GetVirtualTable(typeof(SysUserLogByMonth)).GetTableAllTails();
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync();
|
// var result = await _defaultTableDbContext.Set<SysTest>().AnyAsync();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
@ -38,6 +39,8 @@ namespace Sample.SqlServer
|
||||||
o.CreateShardingTableOnStart = true;
|
o.CreateShardingTableOnStart = true;
|
||||||
o.EnsureCreatedWithOutShardingTable = true;
|
o.EnsureCreatedWithOutShardingTable = true;
|
||||||
o.AutoTrackEntity = true;
|
o.AutoTrackEntity = true;
|
||||||
|
o.ParallelQueryMaxThreadCount = 100;
|
||||||
|
o.ParallelQueryTimeOut=TimeSpan.FromSeconds(10);
|
||||||
})
|
})
|
||||||
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)
|
.AddShardingQuery((conStr, builder) => builder.UseSqlServer(conStr).UseLoggerFactory(efLogger)
|
||||||
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
|
.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking))
|
||||||
|
|
|
@ -34,7 +34,6 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
||||||
|
|
||||||
public List<string> RouteTo(Type entityType,ShardingDataSourceRouteConfig routeRouteConfig)
|
public List<string> RouteTo(Type entityType,ShardingDataSourceRouteConfig routeRouteConfig)
|
||||||
{
|
{
|
||||||
var shardingEntityConfig = ShardingUtil.Parse(entityType);
|
|
||||||
var virtualDataSourceRoute = GetRoute( entityType);
|
var virtualDataSourceRoute = GetRoute( entityType);
|
||||||
|
|
||||||
if (routeRouteConfig.UseQueryable())
|
if (routeRouteConfig.UseQueryable())
|
||||||
|
@ -46,7 +45,10 @@ namespace ShardingCore.Core.VirtualDatabase.VirtualDataSources
|
||||||
shardingKeyValue = routeRouteConfig.GetShardingKeyValue();
|
shardingKeyValue = routeRouteConfig.GetShardingKeyValue();
|
||||||
|
|
||||||
if (routeRouteConfig.UseEntity())
|
if (routeRouteConfig.UseEntity())
|
||||||
|
{
|
||||||
|
var shardingEntityConfig = ShardingUtil.Parse(entityType);
|
||||||
shardingKeyValue = routeRouteConfig.GetShardingDataSource().GetPropertyValue(shardingEntityConfig.ShardingDataSourceField);
|
shardingKeyValue = routeRouteConfig.GetShardingDataSource().GetPropertyValue(shardingEntityConfig.ShardingDataSourceField);
|
||||||
|
}
|
||||||
|
|
||||||
if (shardingKeyValue != null)
|
if (shardingKeyValue != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace ShardingCore.Core.VirtualTables
|
||||||
return GetVirtualRoute();
|
return GetVirtualRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<string> GetTaleAllTails()
|
public List<string> GetTableAllTails()
|
||||||
{
|
{
|
||||||
return _physicTables.Keys.Select(o => o.Tail).ToList();
|
return _physicTables.Keys.Select(o => o.Tail).ToList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace ShardingCore.Core.VirtualTables
|
||||||
/// <see cref="ShardingBootstrapper"/> CreateDateTables
|
/// <see cref="ShardingBootstrapper"/> CreateDateTables
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
List<string> GetTaleAllTails();
|
List<string> GetTableAllTails();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IVirtualTable<T> : IVirtualTable where T : class,IShardingTable
|
public interface IVirtualTable<T> : IVirtualTable where T : class,IShardingTable
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace ShardingCore.EFCores
|
||||||
var singleQueryRouteTail = (ISingleQueryRouteTail) shardingTableDbContext.RouteTail;
|
var singleQueryRouteTail = (ISingleQueryRouteTail) shardingTableDbContext.RouteTail;
|
||||||
var tail = singleQueryRouteTail.GetTail();
|
var tail = singleQueryRouteTail.GetTail();
|
||||||
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
|
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDbContext>>();
|
||||||
var typeMap = virtualTableManager.GetAllVirtualTables().Where(o => o.GetTaleAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet();
|
var typeMap = virtualTableManager.GetAllVirtualTables().Where(o => o.GetTableAllTails().Contains(tail)).Select(o => o.EntityType).ToHashSet();
|
||||||
|
|
||||||
//设置分表
|
//设置分表
|
||||||
var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable() && typeMap.Contains(o.ClrType));
|
var mutableEntityTypes = modelBuilder.Model.GetEntityTypes().Where(o => o.ClrType.IsShardingTable() && typeMap.Contains(o.ClrType));
|
||||||
|
|
|
@ -162,16 +162,9 @@ namespace ShardingCore.Extensions
|
||||||
var primaryKeyValue = ShardingKeyUtil.GetPrimaryKeyValues(entity);
|
var primaryKeyValue = ShardingKeyUtil.GetPrimaryKeyValues(entity);
|
||||||
if (primaryKeyValue.IsEmpty())
|
if (primaryKeyValue.IsEmpty())
|
||||||
return null;
|
return null;
|
||||||
var entry = context.ChangeTracker.Entries<TEntity>().FirstOrDefault(e => primaryKeyValue.SequenceEqual(ShardingKeyUtil.GetPrimaryKeyValues(e.Entity)));
|
var entry = context.ChangeTracker.Entries<TEntity>().FirstOrDefault(e =>e.State != EntityState.Detached&&primaryKeyValue.SequenceEqual(ShardingKeyUtil.GetPrimaryKeyValues(e.Entity)));
|
||||||
if (entry != null)
|
|
||||||
{
|
|
||||||
if (entry.State != EntityState.Detached)
|
|
||||||
{
|
|
||||||
return entry.Entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
return entry?.Entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations.Operations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using ShardingCore.Core.VirtualDatabase.VirtualTables;
|
||||||
|
using ShardingCore.Extensions;
|
||||||
|
using ShardingCore.Sharding.Abstractions;
|
||||||
|
|
||||||
|
namespace ShardingCore.Helpers
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* @Author: xjm
|
||||||
|
* @Description:
|
||||||
|
* @Date: 2021/10/6 8:11:59
|
||||||
|
* @Ver: 1.0
|
||||||
|
* @Email: 326308290@qq.com
|
||||||
|
*/
|
||||||
|
/// <summary>
|
||||||
|
/// https://github.com/Coldairarrow/EFCore.Sharding/blob/master/src/EFCore.Sharding/Migrations/MigrationHelper.cs
|
||||||
|
/// </summary>
|
||||||
|
public class MigrationHelper
|
||||||
|
{
|
||||||
|
private MigrationHelper() { }
|
||||||
|
public static void Generate<TShardingDContext>(
|
||||||
|
MigrationOperation operation,
|
||||||
|
MigrationCommandListBuilder builder,
|
||||||
|
ISqlGenerationHelper sqlGenerationHelper,
|
||||||
|
List<MigrationCommand> addCmds
|
||||||
|
) where TShardingDContext:DbContext,IShardingDbContext
|
||||||
|
{
|
||||||
|
|
||||||
|
addCmds.ForEach(aAddCmd =>
|
||||||
|
{
|
||||||
|
var shardingCmds = BuildShardingCmds<TShardingDContext>(operation, aAddCmd.CommandText, sqlGenerationHelper);
|
||||||
|
//针对builder的原始表进行移除
|
||||||
|
shardingCmds.ForEach(aShardingCmd =>
|
||||||
|
{
|
||||||
|
builder.Append(aShardingCmd)
|
||||||
|
.EndCommand();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> BuildShardingCmds<TShardingDContext>(MigrationOperation operation, string sourceCmd, ISqlGenerationHelper sqlGenerationHelper)
|
||||||
|
where TShardingDContext : DbContext, IShardingDbContext
|
||||||
|
{
|
||||||
|
//所有MigrationOperation定义
|
||||||
|
//https://github.com/dotnet/efcore/tree/b970bf29a46521f40862a01db9e276e6448d3cb0/src/EFCore.Relational/Migrations/Operations
|
||||||
|
//ColumnOperation仅替换Table
|
||||||
|
//其余其余都是将Name和Table使用分表名替换
|
||||||
|
var virtualTableManager = ShardingContainer.GetService<IVirtualTableManager<TShardingDContext>>();
|
||||||
|
var allVirtualTables = virtualTableManager.GetAllVirtualTables();
|
||||||
|
var existsShardingTables = allVirtualTables.ToDictionary(o => o.ShardingConfig.VirtualTableName, o => o.GetAllPhysicTables().Select(p=>p.FullName).ToList());
|
||||||
|
//Dictionary<string, List<string>> _existsShardingTables
|
||||||
|
// = Cache.ServiceProvider.GetService<ShardingContainer>().ExistsShardingTables;
|
||||||
|
List<string> resList = new List<string>();
|
||||||
|
string absTableName = string.Empty;
|
||||||
|
|
||||||
|
string name = operation.GetPropertyValue("Name") as string;
|
||||||
|
string tableName = operation.GetPropertyValue("Table") as string;
|
||||||
|
string pattern = string.Format("^({0})$|^({0}_.*?)$|^(.*?_{0}_.*?)$|^(.*?_{0})$", absTableName);
|
||||||
|
Func<KeyValuePair<string, List<string>>, bool> where = x =>
|
||||||
|
existsShardingTables.Any(y =>x.Key==y.Key&& Regex.IsMatch(name, BuildPattern(y.Key)));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tableName))
|
||||||
|
{
|
||||||
|
absTableName = tableName;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrWhiteSpace(name) && existsShardingTables.Any(x => where(x)))
|
||||||
|
{
|
||||||
|
absTableName = existsShardingTables.Where(x => where(x)).FirstOrDefault().Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
//分表
|
||||||
|
if (!string.IsNullOrWhiteSpace(absTableName) && existsShardingTables.ContainsKey(absTableName))
|
||||||
|
{
|
||||||
|
var shardings = existsShardingTables[absTableName];
|
||||||
|
shardings.ForEach(aShardingTable =>
|
||||||
|
{
|
||||||
|
string newCmd = sourceCmd;
|
||||||
|
GetReplaceGroups(operation, absTableName, aShardingTable).ForEach(aReplace =>
|
||||||
|
{
|
||||||
|
newCmd = newCmd.Replace(
|
||||||
|
sqlGenerationHelper.DelimitIdentifier(aReplace.sourceName),
|
||||||
|
sqlGenerationHelper.DelimitIdentifier(aReplace.targetName));
|
||||||
|
});
|
||||||
|
resList.Add(newCmd);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return resList;
|
||||||
|
|
||||||
|
string BuildPattern(string absTableName)
|
||||||
|
{
|
||||||
|
return string.Format("^({0})$|^({0}_.*?)$|^(.*?_{0}_.*?)$|^(.*?_{0})$", absTableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static List<(string sourceName, string targetName)> GetReplaceGroups(
|
||||||
|
MigrationOperation operation, string sourceTableName, string targetTableName)
|
||||||
|
{
|
||||||
|
List<(string sourceName, string targetName)> resList =
|
||||||
|
new List<(string sourceName, string targetName)>
|
||||||
|
{
|
||||||
|
(sourceTableName, targetTableName)
|
||||||
|
};
|
||||||
|
|
||||||
|
string name = operation.GetPropertyValue("Name") as string;
|
||||||
|
if (!string.IsNullOrWhiteSpace(name) && !(operation is ColumnOperation))
|
||||||
|
{
|
||||||
|
string[] patterns = new string[] { $"^()({sourceTableName})()$", $"^()({sourceTableName})(_.*?)$", $"^(.*?_)({sourceTableName})(_.*?)$", $"^(.*?_)({sourceTableName})()$" };
|
||||||
|
foreach (var aPattern in patterns)
|
||||||
|
{
|
||||||
|
if (Regex.IsMatch(name, aPattern))
|
||||||
|
{
|
||||||
|
var newName = new Regex(aPattern).Replace(name, "${1}" + targetTableName + "$3");
|
||||||
|
resList.Add((name, newName));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Func<PropertyInfo, bool> listPropertyWhere = x =>
|
||||||
|
x.PropertyType.IsGenericType
|
||||||
|
&& x.PropertyType.GetGenericTypeDefinition() == typeof(List<>)
|
||||||
|
&& typeof(MigrationOperation).IsAssignableFrom(x.PropertyType.GetGenericArguments()[0]);
|
||||||
|
//其它
|
||||||
|
operation.GetType().GetProperties()
|
||||||
|
.Where(x => x.Name != "Name"
|
||||||
|
&& x.Name != "Table"
|
||||||
|
&& x.PropertyType != typeof(object)
|
||||||
|
&& (typeof(MigrationOperation).IsAssignableFrom(x.PropertyType) || listPropertyWhere(x))
|
||||||
|
)
|
||||||
|
.ToList()
|
||||||
|
.ForEach(aProperty =>
|
||||||
|
{
|
||||||
|
var propertyValue = aProperty.GetValue(operation);
|
||||||
|
if (propertyValue is MigrationOperation propertyOperation)
|
||||||
|
{
|
||||||
|
resList.AddRange(GetReplaceGroups(propertyOperation, sourceTableName, targetTableName));
|
||||||
|
}
|
||||||
|
else if (listPropertyWhere(aProperty))
|
||||||
|
{
|
||||||
|
foreach (var aValue in (IEnumerable)propertyValue)
|
||||||
|
{
|
||||||
|
resList.AddRange(GetReplaceGroups((MigrationOperation)aValue, sourceTableName, targetTableName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return resList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ namespace ShardingCore.Sharding.ShardingDbContextExecutors
|
||||||
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, DbContext>> _dbContextCaches = new ConcurrentDictionary<string, ConcurrentDictionary<string, DbContext>>();
|
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, DbContext>> _dbContextCaches = new ConcurrentDictionary<string, ConcurrentDictionary<string, DbContext>>();
|
||||||
public IShardingTransaction CurrentShardingTransaction { get; private set; }
|
public IShardingTransaction CurrentShardingTransaction { get; private set; }
|
||||||
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
|
private readonly IVirtualDataSource<TShardingDbContext> _virtualDataSource;
|
||||||
private readonly IVirtualTableManager _virtualTableManager;
|
private readonly IVirtualTableManager<TShardingDbContext> _virtualTableManager;
|
||||||
private readonly IShardingDbContextFactory<TShardingDbContext> _shardingDbContextFactory;
|
private readonly IShardingDbContextFactory<TShardingDbContext> _shardingDbContextFactory;
|
||||||
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
|
private readonly IShardingDbContextOptionsBuilderConfig _shardingDbContextOptionsBuilderConfig;
|
||||||
private readonly IRouteTailFactory _routeTailFactory;
|
private readonly IRouteTailFactory _routeTailFactory;
|
||||||
|
|
|
@ -14,10 +14,10 @@ namespace ShardingCore
|
||||||
{
|
{
|
||||||
private readonly IEnumerable<IShardingConfigOption> _shardingConfigOptions;
|
private readonly IEnumerable<IShardingConfigOption> _shardingConfigOptions;
|
||||||
|
|
||||||
public ShardingBootstrapper(IServiceProvider serviceProvider, IEnumerable<IShardingConfigOption> shardingConfigOptions)
|
public ShardingBootstrapper(IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
ShardingContainer.SetServices(serviceProvider);
|
ShardingContainer.SetServices(serviceProvider);
|
||||||
_shardingConfigOptions = shardingConfigOptions;
|
_shardingConfigOptions = ShardingContainer.GetServices<IShardingConfigOption>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
|
|
|
@ -26,11 +26,11 @@ namespace ShardingCore.VirtualRoutes.Days
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public override List<string> GetAllTails()
|
public override List<string> GetAllTails()
|
||||||
{
|
{
|
||||||
var beginTime = GetBeginTime();
|
var beginTime = GetBeginTime().Date;
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp = DateTime.Now.AddDays(1).Date;
|
var nowTimeStamp = DateTime.Now.Date;
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -20,11 +20,11 @@ namespace ShardingCore.VirtualRoutes.Days
|
||||||
public abstract DateTime GetBeginTime();
|
public abstract DateTime GetBeginTime();
|
||||||
public override List<string> GetAllTails()
|
public override List<string> GetAllTails()
|
||||||
{
|
{
|
||||||
var beginTime = GetBeginTime();
|
var beginTime = GetBeginTime().Date;
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp = DateTime.Now.AddDays(1).Date;
|
var nowTimeStamp = DateTime.Now.Date;
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace ShardingCore.VirtualRoutes.Months
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp =ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now);
|
var nowTimeStamp =ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now);
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace ShardingCore.VirtualRoutes.Months
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp =ShardingCoreHelper.GetNextMonthFirstDay(DateTime.Now);
|
var nowTimeStamp =ShardingCoreHelper.GetCurrentMonthFirstDay(DateTime.Now);
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -19,11 +19,11 @@ namespace ShardingCore.VirtualRoutes.Weeks
|
||||||
public abstract DateTime GetBeginTime();
|
public abstract DateTime GetBeginTime();
|
||||||
public override List<string> GetAllTails()
|
public override List<string> GetAllTails()
|
||||||
{
|
{
|
||||||
var beginTime = GetBeginTime();
|
var beginTime = GetBeginTime().Date;
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp = DateTime.Now.AddDays(7).Date;
|
var nowTimeStamp = DateTime.Now.Date;
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -19,11 +19,11 @@ namespace ShardingCore.VirtualRoutes.Weeks
|
||||||
public abstract DateTime GetBeginTime();
|
public abstract DateTime GetBeginTime();
|
||||||
public override List<string> GetAllTails()
|
public override List<string> GetAllTails()
|
||||||
{
|
{
|
||||||
var beginTime = GetBeginTime();
|
var beginTime = GetBeginTime().Date;
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp = DateTime.Now.AddDays(7).Date;
|
var nowTimeStamp = DateTime.Now.Date;
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -18,11 +18,11 @@ namespace ShardingCore.VirtualRoutes.Years
|
||||||
public abstract DateTime GetBeginTime();
|
public abstract DateTime GetBeginTime();
|
||||||
public override List<string> GetAllTails()
|
public override List<string> GetAllTails()
|
||||||
{
|
{
|
||||||
var beginTime = GetBeginTime();
|
var beginTime = GetBeginTime().Date;
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp = DateTime.Now.AddYears(1).Date;
|
var nowTimeStamp = DateTime.Now.Date;
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
|
@ -19,11 +19,11 @@ namespace ShardingCore.VirtualRoutes.Years
|
||||||
public abstract DateTime GetBeginTime();
|
public abstract DateTime GetBeginTime();
|
||||||
public override List<string> GetAllTails()
|
public override List<string> GetAllTails()
|
||||||
{
|
{
|
||||||
var beginTime = GetBeginTime();
|
var beginTime = GetBeginTime().Date;
|
||||||
|
|
||||||
var tails=new List<string>();
|
var tails=new List<string>();
|
||||||
//提前创建表
|
//提前创建表
|
||||||
var nowTimeStamp = DateTime.Now.AddYears(1).Date;
|
var nowTimeStamp = DateTime.Now.Date;
|
||||||
if (beginTime > nowTimeStamp)
|
if (beginTime > nowTimeStamp)
|
||||||
throw new ArgumentException("begin time error");
|
throw new ArgumentException("begin time error");
|
||||||
var currentTimeStamp = beginTime;
|
var currentTimeStamp = beginTime;
|
||||||
|
|
Loading…
Reference in New Issue