分离mysql和sqlserver的单元测试

This commit is contained in:
xuejmnet 2021-01-26 17:42:01 +08:00
parent 9740f897ec
commit 3b2dacb2c5
13 changed files with 491 additions and 29 deletions

View File

@ -1,6 +1,6 @@
{ {
"MySql": { "MySql": {
"ConnectionString": "server=localhost;port=3306;user=root;password=123456;database=ShardingCoreDB;sslMode=None;" "ConnectionString": "server=127.0.0.1;port=3306;user=root;password=root;database=ShardingCoreDB;sslMode=None;"
} }
} }

View File

@ -0,0 +1,28 @@
using ShardingCore.Core;
namespace ShardingCore.Test50.MySql.Domain.Entities
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 14 January 2021 15:36:43
* @Email: 326308290@qq.com
*/
public class SysUserMod:IShardingEntity
{
/// <summary>
/// 用户Id用于分表
/// </summary>
[ShardingKey(TailPrefix = "_",AutoCreateTableOnStart = true)]
public string Id { get; set; }
/// <summary>
/// 用户名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 用户姓名
/// </summary>
public int Age { get; set; }
}
}

View File

@ -0,0 +1,27 @@
using ShardingCore.Core;
namespace ShardingCore.Test50.MySql.Domain.Entities
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 20 January 2021 10:43:19
* @Email: 326308290@qq.com
*/
public class SysUserRange:IShardingEntity
{
/// <summary>
/// 分表分库range切分
/// </summary>
[ShardingKey(TailPrefix = "_",AutoCreateTableOnStart = true)]
public string Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 年龄
/// </summary>
public int Age { get; set; }
}
}

View File

@ -0,0 +1,13 @@
namespace ShardingCore.Test50.MySql.Domain.Entities
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 22 January 2021 14:17:29
* @Email: 326308290@qq.com
*/
public class UserGroup
{
}
}

View File

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ShardingCore.Test50.MySql.Domain.Entities;
namespace ShardingCore.Test50.MySql.Domain.Maps
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 14 January 2021 15:37:33
* @Email: 326308290@qq.com
*/
public class SysUserModMap:IEntityTypeConfiguration<SysUserMod>
{
public void Configure(EntityTypeBuilder<SysUserMod> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
builder.Property(o => o.Name).HasMaxLength(128);
builder.ToTable(nameof(SysUserMod));
}
}
}

View File

@ -0,0 +1,23 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using ShardingCore.Test50.MySql.Domain.Entities;
namespace ShardingCore.Test50.MySql.Domain.Maps
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 20 January 2021 10:45:47
* @Email: 326308290@qq.com
*/
public class SysUserRangeMap:IEntityTypeConfiguration<SysUserRange>
{
public void Configure(EntityTypeBuilder<SysUserRange> builder)
{
builder.HasKey(o => o.Id);
builder.Property(o => o.Id).IsRequired().HasMaxLength(128);
builder.Property(o => o.Name).HasMaxLength(128);
builder.ToTable(nameof(SysUserRange));
}
}
}

View File

@ -2,11 +2,8 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<DefineConstants>TRACE;DEBUG;EFCORE5MYSQL;</DefineConstants> <PackageId>ShardingCore.Test50.MySql</PackageId>
<AssemblyName>ShardingCore.Test50</AssemblyName> <Product>ShardingCore.Test50.MySql</Product>
<RootNamespace>ShardingCore.Test50</RootNamespace>
<PackageId>ShardingCore.Test50</PackageId>
<Product>ShardingCore.Test50</Product>
<LangVersion>9.0</LangVersion> <LangVersion>9.0</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -24,12 +21,6 @@
<ProjectReference Include="..\..\src\ShardingCore.MySql\ShardingCore.MySql.csproj" /> <ProjectReference Include="..\..\src\ShardingCore.MySql\ShardingCore.MySql.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Compile Include="..\..\test\ShardingCore.Test50\**\*.cs" />
<Compile Remove="..\..\test\ShardingCore.Test50\obj\**" />
<Compile Remove="..\..\test\ShardingCore.Test50\bin\**" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Configs\DbConfig.json"> <Content Include="Configs\DbConfig.json">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile> <ExcludeFromSingleFile>true</ExcludeFromSingleFile>

View File

@ -0,0 +1,146 @@
using System.Linq;
using System.Threading.Tasks;
using ShardingCore.DbContexts.VirtualDbContexts;
using ShardingCore.Extensions;
using ShardingCore.Test50.MySql.Domain.Entities;
using Xunit;
namespace ShardingCore.Test50.MySql
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 15 January 2021 17:22:10
* @Email: 326308290@qq.com
*/
public class ShardingTest
{
private readonly IVirtualDbContext _virtualDbContext;
public ShardingTest(IVirtualDbContext virtualDbContext)
{
_virtualDbContext = virtualDbContext;
}
[Fact]
public async Task ToList_All_Test()
{
var mods=await _virtualDbContext.Set<SysUserMod>().ToShardingListAsync();
Assert.Equal(100,mods.Count);
var ranges=await _virtualDbContext.Set<SysUserRange>().ToShardingListAsync();
Assert.Equal(1000,ranges.Count);
}
[Fact]
public async Task ToList_OrderBy_Asc_Desc_Test()
{
var modascs=await _virtualDbContext.Set<SysUserMod>().OrderBy(o=>o.Age).ToShardingListAsync();
Assert.Equal(100,modascs.Count);
Assert.Equal(100,modascs.Last().Age);
var moddescs=await _virtualDbContext.Set<SysUserMod>().OrderByDescending(o=>o.Age).ToShardingListAsync();
Assert.Equal(100,moddescs.Count);
Assert.Equal(1,moddescs.Last().Age);
}
[Fact]
public async Task ToList_Id_In_Test()
{
var ids = new[] {"1", "2", "3", "4"};
var sysUserMods=await _virtualDbContext.Set<SysUserMod>().Where(o=>ids.Contains(o.Id)).ToShardingListAsync();
var sysUserRanges=await _virtualDbContext.Set<SysUserRange>().Where(o=>ids.Contains(o.Id)).ToShardingListAsync();
foreach (var id in ids)
{
Assert.Contains(sysUserMods, o =>o.Id==id);
Assert.Contains(sysUserRanges, o =>o.Id==id);
}
}
[Fact]
public async Task ToList_Id_Eq_Test()
{
var mods=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="3").ToShardingListAsync();
Assert.Single(mods);
Assert.Equal("3",mods[0].Id);
var ranges=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Id=="3").ToShardingListAsync();
Assert.Single(ranges);
Assert.Equal("3",ranges[0].Id);
}
[Fact]
public async Task ToList_Id_Not_Eq_Test()
{
var mods=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id!="3").ToShardingListAsync();
Assert.Equal(99,mods.Count);
Assert.DoesNotContain(mods,o=>o.Id=="3");
var ranges=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Id!="3").ToShardingListAsync();
Assert.Equal(999,ranges.Count);
Assert.DoesNotContain(ranges,o=>o.Id=="3");
}
[Fact]
public async Task ToList_Name_Eq_Test()
{
var mods=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Name=="name_3").ToShardingListAsync();
Assert.Single(mods);
Assert.Equal("3",mods[0].Id);
var ranges=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Name=="name_range_3").ToShardingListAsync();
Assert.Single(ranges);
Assert.Equal("3",ranges[0].Id);
}
[Fact]
public async Task ToList_Id_Eq_Not_In_Db_Test()
{
var mods=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="1001").ToShardingListAsync();
Assert.Empty(mods);
var ranges=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Id=="1001").ToShardingListAsync();
Assert.Empty(ranges);
}
[Fact]
public async Task ToList_Name_Eq_Not_In_Db_Test()
{
var mods=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Name=="name_1001").ToShardingListAsync();
Assert.Empty(mods);
var ranges=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Name=="name_range_1001").ToShardingListAsync();
Assert.Empty(ranges);
}
[Fact]
public async Task FirstOrDefault_Order_By_Id_Test()
{
var sysUserMod=await _virtualDbContext.Set<SysUserMod>().OrderBy(o=>o.Id).ShardingFirstOrDefaultAsync();
Assert.True(sysUserMod!=null&&sysUserMod.Id=="1");
var sysUserRange=await _virtualDbContext.Set<SysUserRange>().OrderBy(o=>o.Id).ShardingFirstOrDefaultAsync();
Assert.True(sysUserRange!=null&&sysUserRange.Id=="1");
}
[Fact]
public async Task FirstOrDefault2()
{
var sysUserMod=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id=="1").ShardingFirstOrDefaultAsync();
Assert.True(sysUserMod!=null&&sysUserMod.Id=="1");
var sysUserRange=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Id=="1").ShardingFirstOrDefaultAsync();
Assert.True(sysUserRange!=null&&sysUserRange.Id=="1");
}
[Fact]
public async Task FirstOrDefault3()
{
var sysUserMod=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Name=="name_2").ShardingFirstOrDefaultAsync();
Assert.NotNull(sysUserMod);
Assert.Equal("2",sysUserMod.Id);
var sysUserRange=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Name=="name_range_2").ShardingFirstOrDefaultAsync();
Assert.NotNull(sysUserRange);
Assert.Equal("2",sysUserRange.Id);
}
[Fact]
public async Task FirstOrDefault4()
{
var sysUserMod=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Id!="1").ShardingFirstOrDefaultAsync();
Assert.NotNull(sysUserMod);
Assert.True(sysUserMod.Id!="1");
var sysUserRange=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Id!="1").ShardingFirstOrDefaultAsync();
Assert.NotNull(sysUserRange);
Assert.True(sysUserRange.Id!="1");
}
[Fact]
public async Task FirstOrDefault5()
{
var sysUserMod=await _virtualDbContext.Set<SysUserMod>().Where(o=>o.Name=="name_1001").ShardingFirstOrDefaultAsync();
Assert.Null(sysUserMod);
var sysUserRange=await _virtualDbContext.Set<SysUserRange>().Where(o=>o.Name=="name_range_1001").ShardingFirstOrDefaultAsync();
Assert.Null(sysUserRange);
}
}
}

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Test50.MySql.Domain.Entities;
using ShardingCore.VirtualRoutes;
namespace ShardingCore.Test50.MySql.Shardings
{
/*
* @Author: xjm
* @Description:
* @Date: Thursday, 14 January 2021 15:39:27
* @Email: 326308290@qq.com
*/
public class SysUserModVirtualRoute : AbstractSimpleShardingModVirtualRoute<SysUserMod, string>
{
public SysUserModVirtualRoute() : base(3)
{
}
protected override string ConvertToShardingKey(object shardingKey)
{
return shardingKey.ToString();
}
public override List<string> GetAllTails()
{
return new() { "0","1","2"};
}
protected override Expression<Func<string, bool>> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator)
{
var t = ShardingKeyToTail(shardingKey);
switch (shardingOperator)
{
case ShardingOperatorEnum.Equal: return tail => tail == t;
default:
{
Console.WriteLine($"shardingOperator is not equal scan all table tail");
return tail => true;
}
}
}
}
}

View File

@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using ShardingCore.Core.VirtualRoutes;
using ShardingCore.Core.VirtualRoutes.Abstractions;
using ShardingCore.Helpers;
using ShardingCore.Test50.MySql.Domain.Entities;
namespace ShardingCore.Test50.MySql.Shardings
{
/*
* @Author: xjm
* @Description:
* @Date: Wednesday, 20 January 2021 10:46:37
* @Email: 326308290@qq.com
*/
public class SysUserRangeVirtualRoute: AbstractShardingOperatorVirtualRoute<SysUserRange, string>
{
private int _mod = 1000;
protected override string ConvertToShardingKey(object shardingKey)
{
return shardingKey.ToString();
}
public override string ShardingKeyToTail(object shardingKey)
{
var shardingKeyStr = ConvertToShardingKey(shardingKey);
var m = Math.Abs(ShardingCoreHelper.GetStringHashCode(shardingKeyStr) % _mod);
if (m > 800)//801-999
{
return "3";
} else if (m > 600)//601-800
{
return "2";
} else if (m > 300)//301-600
{
return "1";
} else //0-300
{
return "0";
}
}
public override List<string> GetAllTails()
{
return new(){"0", "1","2","3"};
}
protected override Expression<Func<string, bool>> GetRouteToFilter(string shardingKey, ShardingOperatorEnum shardingOperator)
{
var t = ShardingKeyToTail(shardingKey);
switch (shardingOperator)
{
case ShardingOperatorEnum.Equal: return tail => tail == t;
default:
{
Console.WriteLine($"shardingOperator is not equal scan all table tail");
return tail => true;
}
}
}
// public override List<IPhysicTable> AfterPhysicTableFilter(List<IPhysicTable> allPhysicTables, List<IPhysicTable> filterPhysicTables)
// {
// if (filterPhysicTables.Count > 1)
// throw new Exception($"query {nameof(SysUserRange)} not support cross table");
// return base.AfterPhysicTableFilter(allPhysicTables, filterPhysicTables);
// }
}
}

View File

@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ShardingCore.DbContexts.VirtualDbContexts;
using ShardingCore.Extensions;
using ShardingCore.Test50.MySql.Domain.Entities;
using ShardingCore.MySql;
using ShardingCore.Test50.MySql.Shardings;
namespace ShardingCore.Test50.MySql
{
/*
* @Author: xjm
* @Description:
* @Date: Friday, 15 January 2021 15:37:46
* @Email: 326308290@qq.com
*/
public class Startup
{
// // 自定义 host 构建
public void ConfigureHost(IHostBuilder hostBuilder)
{
hostBuilder
.ConfigureAppConfiguration(builder =>
{
builder.AddJsonFile("Configs/DbConfig.json");
});
}
// 支持的形式:
// ConfigureServices(IServiceCollection services)
// ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
{
services.AddShardingMySql(o =>
{
o.ConnectionString = hostBuilderContext.Configuration.GetSection("MySql")["ConnectionString"];
o.ServerVersion = new MySqlServerVersion(new Version());
o.AddSharding<SysUserModVirtualRoute>();
o.AddSharding<SysUserRangeVirtualRoute>();
o.CreateIfNotExists((provider, config) =>
{
config.EnsureCreated = true;
});
});
}
// 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法
public void Configure(IServiceProvider serviceProvider)
{
var shardingBootstrapper = serviceProvider.GetService<IShardingBootstrapper>();
shardingBootstrapper.Start();
// 有一些测试数据要初始化可以放在这里
InitData(serviceProvider).GetAwaiter().GetResult();
}
/// <summary>
/// 添加种子数据
/// </summary>
/// <param name="serviceProvider"></param>
/// <returns></returns>
private async Task InitData(IServiceProvider serviceProvider)
{
using (var scope = serviceProvider.CreateScope())
{
var virtualDbContext = scope.ServiceProvider.GetService<IVirtualDbContext>();
if (!await virtualDbContext.Set<SysUserMod>().ShardingAnyAsync(o => true))
{
var ids = Enumerable.Range(1, 100);
var userMods = new List<SysUserMod>();
foreach (var id in ids)
{
userMods.Add(new SysUserMod()
{
Id = id.ToString(),
Age = id,
Name = $"name_{id}"
});
}
await virtualDbContext.InsertRangeAsync(userMods);
var idRanges = Enumerable.Range(1, 1000);
var userRanges = new List<SysUserRange>();
foreach (var id in idRanges)
{
userRanges.Add(new SysUserRange()
{
Id = id.ToString(),
Age = id,
Name = $"name_range_{id}"
});
}
await virtualDbContext.InsertRangeAsync(userRanges);
await virtualDbContext.SaveChangesAsync();
}
}
}
}
}

View File

@ -3,7 +3,6 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net5.0</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<LangVersion>9.0</LangVersion> <LangVersion>9.0</LangVersion>
<DefineConstants>TRACE;DEBUG;EFCORE5SQLSERVER;</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -8,6 +8,7 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using ShardingCore.DbContexts.VirtualDbContexts; using ShardingCore.DbContexts.VirtualDbContexts;
using ShardingCore.Extensions; using ShardingCore.Extensions;
using ShardingCore.SqlServer;
using ShardingCore.Test50.Domain.Entities; using ShardingCore.Test50.Domain.Entities;
using ShardingCore.Test50.Shardings; using ShardingCore.Test50.Shardings;
@ -43,8 +44,7 @@ namespace ShardingCore.Test50
// ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) // ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
// ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services) // ConfigureServices(HostBuilderContext hostBuilderContext, IServiceCollection services)
public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext) public void ConfigureServices(IServiceCollection services, HostBuilderContext hostBuilderContext)
{ {
#if EFCORE5SQLSERVER
services.AddShardingSqlServer(o => services.AddShardingSqlServer(o =>
{ {
o.ConnectionString = hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"]; o.ConnectionString = hostBuilderContext.Configuration.GetSection("SqlServer")["ConnectionString"];
@ -55,20 +55,6 @@ namespace ShardingCore.Test50
config.EnsureCreated = true; config.EnsureCreated = true;
}); });
}); });
#endif
#if EFCORE5MYSQL
services.AddShardingMySql(o =>
{
o.ConnectionString = hostBuilderContext.Configuration.GetSection("MySql")["ConnectionString"];
o.ServerVersion = new MySqlServerVersion(new Version());
o.AddSharding<SysUserModVirtualRoute>();
o.AddSharding<SysUserRangeVirtualRoute>();
o.CreateIfNotExists((provider, config) =>
{
config.EnsureCreated = true;
});
});
#endif
} }
// 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法 // 可以添加要用到的方法参数,会自动从注册的服务中获取服务实例,类似于 asp.net core 里 Configure 方法