diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json index ed270fe2f8c5936e9ce28e0749545a0004657b0f..d736dd5728e3d8034b34bb39807479ac374aef76 100644 --- a/.vs/VSWorkspaceState.json +++ b/.vs/VSWorkspaceState.json @@ -1,7 +1,8 @@ { "ExpandedNodes": [ - "" + "", + "\\LingYanAspCoreFramework" ], - "SelectedNode": "\\LingYanAspCoreFramework.sln", + "SelectedNode": "\\.gitattributes", "PreviewInSolutionExplorer": false } \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite index 042597b3e3c26e68ee449aa2e35f3fc335e18d7a..8a2a6ce8336e65eee11c06c4ba3a958697b6073e 100644 Binary files a/.vs/slnx.sqlite and b/.vs/slnx.sqlite differ diff --git a/LingTest/Controllers/DynamicShardingController .cs b/LingTest/Controllers/DynamicShardingController .cs new file mode 100644 index 0000000000000000000000000000000000000000..7a8422c7ad23ecad2979d275e5ded0a3ac6ffe27 --- /dev/null +++ b/LingTest/Controllers/DynamicShardingController .cs @@ -0,0 +1,41 @@ +using LingTest.DbContexts; +using LingTest.Entitys; +using LingYanAspCoreFramework.DynamicShard.Models.Enum; +using LingYanAspCoreFramework.Helpers; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json; +using TencentCloud.Ess.V20201111.Models; + +namespace LingTest.Controllers +{ + [ApiController] + [Route("api/[controller]/[action]")] + [AllowAnonymous] + public class DynamicShardingController : ControllerBase + { + private readonly StoreDbContext storeDbContext; + public DynamicShardingController(StoreDbContext storeDbContext) + { + this.storeDbContext = storeDbContext; + } + + [HttpPost] + public async Task> Create(Product product) + { + //数据库操作还是采用原生的EFCORE不会影响 + var rct = await this.storeDbContext.Products.AddAsync(product); + await this.storeDbContext.SaveChangesAsync(); + return rct?.Entity; + + } + + [HttpGet] + public async Task Search() + { + var ssss = await this.storeDbContext.Products.ToListAsync(); + return Ok(ssss); + } + } +} \ No newline at end of file diff --git a/LingTest/Controllers/TokenController.cs b/LingTest/Controllers/TokenController.cs deleted file mode 100644 index 269b4b7438815857868dd48fbcc2c6706d2d7e52..0000000000000000000000000000000000000000 --- a/LingTest/Controllers/TokenController.cs +++ /dev/null @@ -1,52 +0,0 @@ -using LingYanAspCoreFramework.Extensions; -using LingYanAspCoreFramework.SampleRoots; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Mvc; -using Yitter.IdGenerator; - -namespace LingTest.Controllers -{ - /// - /// 天气控制器 - /// - [ApiController] - [Route("api/[controller]/[action]")] - [Authorize(AuthenticationSchemes = SampleHelper.BearerScheme, Policy = SampleHelper.EmpowerPolicy)] - public class TokenController : ControllerBase - { - private readonly ILogger logger; - - public TokenController(ILogger logger) - { - this.logger = logger; - } - /// - /// 获取Token - /// - /// 测试是否引入 - /// 返回默认值 - - [HttpGet] - [AllowAnonymous] - public IActionResult Get(string sss) - { - if (string.IsNullOrEmpty(sss)) - { - throw new Exception("中途测试抛异常"); - } - Dictionary keyValuePairs = new Dictionary(); - keyValuePairs.Add(SampleHelper.ClaimUserId, "77777"); - var token = keyValuePairs.CreateJwtToken(SampleHelper.RSAPublicKey); - return Ok(token); - } - /// - /// 水水水水水 - /// - /// - [HttpGet] - public IActionResult Test() - { - return Ok("完成"); - } - } -} \ No newline at end of file diff --git a/LingTest/DbContexts/LingDbContext.cs b/LingTest/DbContexts/LingDbContext.cs deleted file mode 100644 index 6faff9b1236dc42dde0115c78c32d4d658e4bad0..0000000000000000000000000000000000000000 --- a/LingTest/DbContexts/LingDbContext.cs +++ /dev/null @@ -1,41 +0,0 @@ -锘縰sing LingTest.Entitys; -using LingYanAspCoreFramework.Attributes; -using LingYanAspCoreFramework.SampleRoots; -using Microsoft.EntityFrameworkCore; - -namespace LingTest.DbContexts -{ - [LYDbContext("Default")] - public class LingDbContext : DbContext - { - public LingDbContext() - { - } - - public LingDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions) - { - } - - public DbSet Users { get; set; } - public DbSet Roles { get; set; } - public DbSet Routes { get; set; } - public DbSet UserRoleGroups { get; set; } - public DbSet RoleRouteGroups { get; set; } - - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - base.OnConfiguring(optionsBuilder); - if (!optionsBuilder.IsConfigured) - { - optionsBuilder.UseMySql(SampleHelper.MysqlConnectionDic["Default"], ServerVersion.AutoDetect(SampleHelper.MysqlConnectionDic["Default"])) - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - .EnableSensitiveDataLogging(); - } - } - - protected override void OnModelCreating(ModelBuilder modelBuilder) - { - base.OnModelCreating(modelBuilder); - } - } -} \ No newline at end of file diff --git a/LingTest/DbContexts/StoreDbContext.cs b/LingTest/DbContexts/StoreDbContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..1cf1e65ea74c52548019e4d646d9bfa24087743c --- /dev/null +++ b/LingTest/DbContexts/StoreDbContext.cs @@ -0,0 +1,26 @@ +using LingTest.Entitys; +using LingYanAspCoreFramework.DynamicShard.EFCore.Impl; +using LingYanAspCoreFramework.DynamicShard.Models; +using Microsoft.EntityFrameworkCore; + +namespace LingTest.DbContexts +{ + public class StoreDbContext : DynamicShardDbContext + { + public DbSet Products { get; set; } + public DbSet Orders { get; set; } + public StoreDbContext(DbContextOptions options, DynamicShardOption dynamicShardOption, IServiceProvider serviceProvider) + : base(options, dynamicShardOption, serviceProvider) + { + } + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + base.OnConfiguring(optionsBuilder); + } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + } + + } +} diff --git a/LingTest/DynamicRoute/TestDynamicRoute.cs b/LingTest/DynamicRoute/TestDynamicRoute.cs new file mode 100644 index 0000000000000000000000000000000000000000..f0f54402c937e7e91723fb2af4ff5b5ae28dc2ea --- /dev/null +++ b/LingTest/DynamicRoute/TestDynamicRoute.cs @@ -0,0 +1,23 @@ +锘縰sing LingYanAspCoreFramework.Attributes; +using LingYanAspCoreFramework.BaseRoots; +using Microsoft.AspNetCore.Mvc; + +namespace LingTest.DynamicRoute +{ + //鍔ㄦ佽矾鐢卞師鍒欎笂鍙渶瑕佸湪绫讳笂娣诲姞[LYDynamicRoute]鐗规у嵆鍙 + //BaseDynamicRoute鍙槸缁ф壙ControllerBase锛屽彲浠ユ洿鏂逛究鐨勪娇鐢∣K(),NotFound()绛夌搴忓垪鍖栨柟娉 + //鍔ㄦ佽矾鐢辩殑HTTP绫诲瀷鍙互鍦ㄩ厤缃枃浠朵腑鐨凥ttpMethod.json閰嶇疆,涔熷彲浠ョ洿鎺ユ墦璧忚矾鐢辩被鍨嬬壒鎬 + [LYDynamicRoute] + public class TestDynamicRoute : BaseDynamicRoute + { + public IActionResult TestPost() + { + return Ok("杩斿洖鍊"); + } + [HttpGet] + public IActionResult TestGet() + { + return Ok("杩斿洖鍊"); + } + } +} diff --git a/LingTest/Entitys/Order.cs b/LingTest/Entitys/Order.cs new file mode 100644 index 0000000000000000000000000000000000000000..92d3e7a7cc6c6b6b27fa5f6171db37552e59de88 --- /dev/null +++ b/LingTest/Entitys/Order.cs @@ -0,0 +1,19 @@ +锘縰sing LingYanAspCoreFramework.BaseRoots; +using Microsoft.EntityFrameworkCore; + +namespace LingTest.Entitys +{ + [Index(nameof(TestIndex))] + [Index(nameof(TestIndex1),IsUnique =true)] + [Index(nameof(TestIndex2),nameof(TestIndex3))] + [Index(nameof(TestIndex1), nameof(TestIndex2),IsUnique =true)] + public class Order:BaseEntity + { + public string TestIndex { get; set; } + + public string TestIndex1 { get; set; } + public string TestIndex2 { get; set; } + public string TestIndex3 { get; set; } + public string TeaColm { get; set; } + } +} diff --git a/LingTest/Entitys/Product.cs b/LingTest/Entitys/Product.cs new file mode 100644 index 0000000000000000000000000000000000000000..18c5e0ba653d009b41ebdc2136e2b7019d324fe7 --- /dev/null +++ b/LingTest/Entitys/Product.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; + +namespace LingTest.Entitys +{ + public class Product + { + [Key] + public int Id { get; set; } + + [StringLength(50), Required] + public string Name { get; set; } + + public string Category { get; set; } + public int Price { get; set; } + } +} diff --git a/LingTest/Entitys/RoleEntity.cs b/LingTest/Entitys/RoleEntity.cs deleted file mode 100644 index ebd66c66f0f4387167f79a3e82d0700c91851084..0000000000000000000000000000000000000000 --- a/LingTest/Entitys/RoleEntity.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縰sing LingYanAspCoreFramework.BaseRoots; - -namespace LingTest.Entitys -{ - public class RoleEntity : BaseRole - { - } -} \ No newline at end of file diff --git a/LingTest/Entitys/RoleRouteGroupEntity.cs b/LingTest/Entitys/RoleRouteGroupEntity.cs deleted file mode 100644 index 87f0fd175a574664342081207285944a5804d29d..0000000000000000000000000000000000000000 --- a/LingTest/Entitys/RoleRouteGroupEntity.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縰sing LingYanAspCoreFramework.BaseRoots; - -namespace LingTest.Entitys -{ - public class RoleRouteGroupEntity : BaseRoleRouteGroup - { - } -} \ No newline at end of file diff --git a/LingTest/Entitys/RouteEntity.cs b/LingTest/Entitys/RouteEntity.cs deleted file mode 100644 index 29c3e51918413def3659184bafe49c8c0e9595c3..0000000000000000000000000000000000000000 --- a/LingTest/Entitys/RouteEntity.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縰sing LingYanAspCoreFramework.BaseRoots; - -namespace LingTest.Entitys -{ - public class RouteEntity : BaseRoute - { - } -} \ No newline at end of file diff --git a/LingTest/Entitys/UserEntity.cs b/LingTest/Entitys/UserEntity.cs deleted file mode 100644 index 6b8b52f6aaed72c0a9b7727087f740da1d5126f7..0000000000000000000000000000000000000000 --- a/LingTest/Entitys/UserEntity.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縰sing LingYanAspCoreFramework.BaseRoots; - -namespace LingTest.Entitys -{ - public class UserEntity : BaseUser - { - } -} \ No newline at end of file diff --git a/LingTest/Entitys/UserRoleGroupEntity.cs b/LingTest/Entitys/UserRoleGroupEntity.cs deleted file mode 100644 index 9d4a9a98811cf310c44b3ff030c706b1cd0861aa..0000000000000000000000000000000000000000 --- a/LingTest/Entitys/UserRoleGroupEntity.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縰sing LingYanAspCoreFramework.BaseRoots; - -namespace LingTest.Entitys -{ - public class UserRoleGroupEntity : BaseUserRoleGroup - { - } -} \ No newline at end of file diff --git a/LingTest/Filters/AuthorFilter.cs b/LingTest/Filters/AuthorFilter.cs deleted file mode 100644 index 0e1d204ca6d00083e339c8ed103b4b70294829d0..0000000000000000000000000000000000000000 --- a/LingTest/Filters/AuthorFilter.cs +++ /dev/null @@ -1,11 +0,0 @@ -锘縰sing LingTest.Entitys; -using LingYanAspCoreFramework.Attributes; -using LingYanAspCoreFramework.SampleRoots; - -namespace LingTest.Filters -{ - [LYGlobalFilter] - public class AuthorFilter:SampleGlobalAuthorizationFilterAttribute - { - } -} diff --git a/LingTest/Filters/PermissionHandle.cs b/LingTest/Filters/PermissionHandle.cs deleted file mode 100644 index 3fadd7150785661edb78e038e6ff563dcdc6513b..0000000000000000000000000000000000000000 --- a/LingTest/Filters/PermissionHandle.cs +++ /dev/null @@ -1,13 +0,0 @@ -锘縰sing LingYanAspCoreFramework.Attributes; -using LingYanAspCoreFramework.SampleRoots; - -namespace LingTest.Filters -{ - [LYAuthorizeHandler] - public class PermissionHandle : SampleGlobalPermissionHandle - { - public PermissionHandle(IHttpContextAccessor httpContextAccessor) : base(httpContextAccessor) - { - } - } -} diff --git a/LingTest/Helper/TestHelper.cs b/LingTest/Helper/TestHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..a014846486453985b692ce394d0b36882803e219 --- /dev/null +++ b/LingTest/Helper/TestHelper.cs @@ -0,0 +1,14 @@ +锘縰sing LingYanAspCoreFramework.Attributes; + +namespace LingTest.Helper +{ + //瀹炰緥鐗规э紝鏃犻渶浠讳綍浼犲弬锛屾敞鍐屾渚 + [LYInstance] + public class TestHelper + { + public void TestInstance() + { + + } + } +} diff --git a/LingTest/LingTest.csproj b/LingTest/LingTest.csproj index f55199d13d3c6d58f8b02e7ab9c6f3e883794d63..4f022e41d328e698e1526e4b800ad2c0563a1b3f 100644 --- a/LingTest/LingTest.csproj +++ b/LingTest/LingTest.csproj @@ -8,10 +8,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/LingTest/Migrations/20241223072307_v1.Designer.cs b/LingTest/Migrations/20241223072307_v1.Designer.cs deleted file mode 100644 index 69931f6a7f9a8c7ef6e7a74d975dc02c617dde68..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241223072307_v1.Designer.cs +++ /dev/null @@ -1,196 +0,0 @@ -锘// -using LingTest.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace LingTest.Migrations -{ - [DbContext(typeof(LingDbContext))] - [Migration("20241223072307_v1")] - partial class v1 - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("LingTest.Entitys.RoleEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Roles"); - }); - - modelBuilder.Entity("LingTest.Entitys.RoleRouteGroup", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("RouteId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("RoleRouteGroups"); - }); - - modelBuilder.Entity("LingTest.Entitys.RouteEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ContrillereFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Controller") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerSummary") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Display") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplaySummary") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("HttpMethod") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("ProjectName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RoutePrefix") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RouteTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Routes"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("NickName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Phone") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserRoleGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("UserRoleGroups"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/LingTest/Migrations/20241223072307_v1.cs b/LingTest/Migrations/20241223072307_v1.cs deleted file mode 100644 index 0f6f5bfa7c5f84bbc3ad9902a8a73ed7b7608048..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241223072307_v1.cs +++ /dev/null @@ -1,146 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace LingTest.Migrations -{ - /// - public partial class v1 : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterDatabase() - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "RoleRouteGroups", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IsDeleted = table.Column(type: "tinyint(1)", nullable: false), - CreateTimeStamp = table.Column(type: "bigint", nullable: false), - RoleId = table.Column(type: "bigint", nullable: false), - RouteId = table.Column(type: "bigint", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_RoleRouteGroups", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Roles", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IsDeleted = table.Column(type: "tinyint(1)", nullable: false), - CreateTimeStamp = table.Column(type: "bigint", nullable: false), - Name = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Description = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Roles", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Routes", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IsDeleted = table.Column(type: "tinyint(1)", nullable: false), - CreateTimeStamp = table.Column(type: "bigint", nullable: false), - Display = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplaySummary = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - DisplayFullName = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Controller = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ControllerSummary = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ContrillereFullName = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - RouteTemplate = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - HttpMethod = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - RoutePrefix = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ProjectName = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Routes", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "UserRoleGroups", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IsDeleted = table.Column(type: "tinyint(1)", nullable: false), - CreateTimeStamp = table.Column(type: "bigint", nullable: false), - UserId = table.Column(type: "bigint", nullable: false), - RoleId = table.Column(type: "bigint", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_UserRoleGroups", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Users", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - IsDeleted = table.Column(type: "tinyint(1)", nullable: false), - CreateTimeStamp = table.Column(type: "bigint", nullable: false), - NickName = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Phone = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Password = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "RoleRouteGroups"); - - migrationBuilder.DropTable( - name: "Roles"); - - migrationBuilder.DropTable( - name: "Routes"); - - migrationBuilder.DropTable( - name: "UserRoleGroups"); - - migrationBuilder.DropTable( - name: "Users"); - } - } -} \ No newline at end of file diff --git a/LingTest/Migrations/20241223133026_v2.Designer.cs b/LingTest/Migrations/20241223133026_v2.Designer.cs deleted file mode 100644 index 6b3ba8d1eb01217caf29b184f0f859703b64b48b..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241223133026_v2.Designer.cs +++ /dev/null @@ -1,194 +0,0 @@ -锘// -using LingTest.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace LingTest.Migrations -{ - [DbContext(typeof(LingDbContext))] - [Migration("20241223133026_v2")] - partial class v2 - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("LingTest.Entitys.RoleEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Roles"); - }); - - modelBuilder.Entity("LingTest.Entitys.RoleRouteGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("RouteId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("RoleRouteGroups"); - }); - - modelBuilder.Entity("LingTest.Entitys.RouteEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("ContrillereFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Controller") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerSummary") - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Display") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplaySummary") - .HasColumnType("longtext"); - - b.Property("HttpMethod") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("ProjectName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RoutePrefix") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RouteTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Routes"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("NickName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Phone") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserRoleGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("UserRoleGroups"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/LingTest/Migrations/20241223133026_v2.cs b/LingTest/Migrations/20241223133026_v2.cs deleted file mode 100644 index e1795c8ab0f59a47c53d36b68ff4e52ee72bf409..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241223133026_v2.cs +++ /dev/null @@ -1,74 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace LingTest.Migrations -{ - /// - public partial class v2 : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "DisplaySummary", - table: "Routes", - type: "longtext", - nullable: true, - oldClrType: typeof(string), - oldType: "longtext") - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AlterColumn( - name: "ControllerSummary", - table: "Routes", - type: "longtext", - nullable: true, - oldClrType: typeof(string), - oldType: "longtext") - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.UpdateData( - table: "Routes", - keyColumn: "DisplaySummary", - keyValue: null, - column: "DisplaySummary", - value: ""); - - migrationBuilder.AlterColumn( - name: "DisplaySummary", - table: "Routes", - type: "longtext", - nullable: false, - oldClrType: typeof(string), - oldType: "longtext", - oldNullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.UpdateData( - table: "Routes", - keyColumn: "ControllerSummary", - keyValue: null, - column: "ControllerSummary", - value: ""); - - migrationBuilder.AlterColumn( - name: "ControllerSummary", - table: "Routes", - type: "longtext", - nullable: false, - oldClrType: typeof(string), - oldType: "longtext", - oldNullable: true) - .Annotation("MySql:CharSet", "utf8mb4") - .OldAnnotation("MySql:CharSet", "utf8mb4"); - } - } -} \ No newline at end of file diff --git a/LingTest/Migrations/20241225083119_v3.Designer.cs b/LingTest/Migrations/20241225083119_v3.Designer.cs deleted file mode 100644 index 73b8e929833eec69f79e8cf934b31f4fe2f47ab4..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241225083119_v3.Designer.cs +++ /dev/null @@ -1,194 +0,0 @@ -锘// -using LingTest.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace LingTest.Migrations -{ - [DbContext(typeof(LingDbContext))] - [Migration("20241225083119_v3")] - partial class v3 - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("LingTest.Entitys.RoleEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Roles"); - }); - - modelBuilder.Entity("LingTest.Entitys.RoleRouteGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("RouteId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("RoleRouteGroups"); - }); - - modelBuilder.Entity("LingTest.Entitys.RouteEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Controller") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerSummary") - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Display") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplaySummary") - .HasColumnType("longtext"); - - b.Property("HttpMethod") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("ProjectName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RoutePrefix") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RouteTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Routes"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("NickName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Phone") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserRoleGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("UserRoleGroups"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/LingTest/Migrations/20241225083119_v3.cs b/LingTest/Migrations/20241225083119_v3.cs deleted file mode 100644 index 1a60aacae98aa81859d5cda7bb0e22ef083482be..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241225083119_v3.cs +++ /dev/null @@ -1,28 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace LingTest.Migrations -{ - /// - public partial class v3 : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "ContrillereFullName", - table: "Routes", - newName: "ControllerFullName"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "ControllerFullName", - table: "Routes", - newName: "ContrillereFullName"); - } - } -} diff --git a/LingTest/Migrations/20241227064847_v4.Designer.cs b/LingTest/Migrations/20241227064847_v4.Designer.cs deleted file mode 100644 index d2d5ab47e117ce7404acbb0b385e9b51a512afbd..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241227064847_v4.Designer.cs +++ /dev/null @@ -1,202 +0,0 @@ -锘// -using LingTest.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace LingTest.Migrations -{ - [DbContext(typeof(LingDbContext))] - [Migration("20241227064847_v4")] - partial class v4 - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("LingTest.Entitys.RoleEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Roles"); - }); - - modelBuilder.Entity("LingTest.Entitys.RoleRouteGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("RouteId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("RoleRouteGroups"); - }); - - modelBuilder.Entity("LingTest.Entitys.RouteEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Controller") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerSummary") - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Display") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplaySummary") - .HasColumnType("longtext"); - - b.Property("HttpMethod") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("ProjectName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RoutePrefix") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RouteTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Routes"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Avatar") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Email") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("NickName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Phone") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserRoleGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("UserRoleGroups"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/LingTest/Migrations/20241227064847_v4.cs b/LingTest/Migrations/20241227064847_v4.cs deleted file mode 100644 index adb5514bccede0525eadf8b61e314b7539cf3e68..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/20241227064847_v4.cs +++ /dev/null @@ -1,40 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace LingTest.Migrations -{ - /// - public partial class v4 : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Avatar", - table: "Users", - type: "longtext", - nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.AddColumn( - name: "Email", - table: "Users", - type: "longtext", - nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Avatar", - table: "Users"); - - migrationBuilder.DropColumn( - name: "Email", - table: "Users"); - } - } -} diff --git a/LingTest/Migrations/LingDbContextModelSnapshot.cs b/LingTest/Migrations/LingDbContextModelSnapshot.cs deleted file mode 100644 index 777fcb00ad7cf06e5a75718834c09a4859737fce..0000000000000000000000000000000000000000 --- a/LingTest/Migrations/LingDbContextModelSnapshot.cs +++ /dev/null @@ -1,199 +0,0 @@ -锘// -using LingTest.DbContexts; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace LingTest.Migrations -{ - [DbContext(typeof(LingDbContext))] - partial class LingDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "8.0.11") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); - - modelBuilder.Entity("LingTest.Entitys.RoleEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Roles"); - }); - - modelBuilder.Entity("LingTest.Entitys.RoleRouteGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("RouteId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("RoleRouteGroups"); - }); - - modelBuilder.Entity("LingTest.Entitys.RouteEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Controller") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ControllerSummary") - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Display") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplayFullName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("DisplaySummary") - .HasColumnType("longtext"); - - b.Property("HttpMethod") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("ProjectName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RoutePrefix") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("RouteTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Routes"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("Avatar") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("Email") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("NickName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Phone") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("LingTest.Entitys.UserRoleGroupEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); - - b.Property("CreateTimeStamp") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("tinyint(1)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("UserRoleGroups"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/LingTest/Migrations/MySql/20250402060703_initCreate.Designer.cs b/LingTest/Migrations/MySql/20250402060703_initCreate.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..589c65972940b273d163eb5e267bc134202462dc --- /dev/null +++ b/LingTest/Migrations/MySql/20250402060703_initCreate.Designer.cs @@ -0,0 +1,103 @@ +锘// +using LingTest.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace LingTest.Migrations.MySql +{ + [DbContext(typeof(StoreDbContext))] + [Migration("20250402060703_initCreate")] + partial class initCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("LingTest.Entitys.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreateTimeStamp") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)"); + + b.Property("TeaColm") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TestIndex") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TestIndex1") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TestIndex2") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TestIndex3") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("TestIndex"); + + b.HasIndex("TestIndex1") + .IsUnique(); + + b.HasIndex("TestIndex1", "TestIndex2") + .IsUnique(); + + b.HasIndex("TestIndex2", "TestIndex3"); + + b.ToTable("Orders", (string)null); + }); + + modelBuilder.Entity("LingTest.Entitys.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Price") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Products", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LingTest/Migrations/MySql/20250402060703_initCreate.cs b/LingTest/Migrations/MySql/20250402060703_initCreate.cs new file mode 100644 index 0000000000000000000000000000000000000000..802f6aaffcb048346f68c601f0073646bfc7b434 --- /dev/null +++ b/LingTest/Migrations/MySql/20250402060703_initCreate.cs @@ -0,0 +1,102 @@ +锘縰sing Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LingTest.Migrations.MySql +{ + /// + public partial class initCreate : Migration + { + //DynamicShard妗嗘灦娉ㄥ叆鍔ㄦ佸垎鐗囧弬鏁 + private readonly string shardingTablePrefix; + private readonly string shardingSchemaPostfix; + public initCreate(string _shardingTablePrefix,string _shardingSchemaPostfix) + { + this.shardingTablePrefix = _shardingTablePrefix; + this.shardingSchemaPostfix = _shardingSchemaPostfix; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: $"{this.shardingTablePrefix}Orders", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + TestIndex = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TestIndex1 = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TestIndex2 = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TestIndex3 = table.Column(type: "varchar(255)", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + TeaColm = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + IsDeleted = table.Column(type: "tinyint(1)", nullable: false), + CreateTimeStamp = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey($"{this.shardingTablePrefix}PK_Orders", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: $"{this.shardingTablePrefix}Products", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "varchar(50)", maxLength: 50, nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Category = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Price = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey($"{this.shardingTablePrefix}PK_Products", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex", + table: $"{this.shardingTablePrefix}Orders", + column: "TestIndex"); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex1", + table: $"{this.shardingTablePrefix}Orders", + column: "TestIndex1", + unique: true); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex1_TestIndex2", + table: $"{this.shardingTablePrefix}Orders", + columns: new[] { "TestIndex1", "TestIndex2" }, + unique: true); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex2_TestIndex3", + table: $"{this.shardingTablePrefix}Orders", + columns: new[] { "TestIndex2", "TestIndex3" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: $"{this.shardingTablePrefix}Orders"); + + migrationBuilder.DropTable( + name: $"{this.shardingTablePrefix}Products"); + } + } +} diff --git a/LingTest/Migrations/Mysql/StoreDbContextModelSnapshot.cs b/LingTest/Migrations/Mysql/StoreDbContextModelSnapshot.cs new file mode 100644 index 0000000000000000000000000000000000000000..8b2d1a67483e1a1462aed0b2876e22a87809e6a2 --- /dev/null +++ b/LingTest/Migrations/Mysql/StoreDbContextModelSnapshot.cs @@ -0,0 +1,100 @@ +锘// +using LingTest.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace LingTest.Migrations.MySql +{ + [DbContext(typeof(StoreDbContext))] + partial class StoreDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder); + + modelBuilder.Entity("LingTest.Entitys.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("CreateTimeStamp") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .HasColumnType("tinyint(1)"); + + b.Property("TeaColm") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TestIndex") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TestIndex1") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TestIndex2") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.Property("TestIndex3") + .IsRequired() + .HasColumnType("varchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("TestIndex"); + + b.HasIndex("TestIndex1") + .IsUnique(); + + b.HasIndex("TestIndex1", "TestIndex2") + .IsUnique(); + + b.HasIndex("TestIndex2", "TestIndex3"); + + b.ToTable("Orders", (string)null); + }); + + modelBuilder.Entity("LingTest.Entitys.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Price") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Products", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LingTest/Migrations/PostgreSql/20250402121617_initCreate.Designer.cs b/LingTest/Migrations/PostgreSql/20250402121617_initCreate.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..cda13f0209403731ea33ecb4ea9c5e79d484bd46 --- /dev/null +++ b/LingTest/Migrations/PostgreSql/20250402121617_initCreate.Designer.cs @@ -0,0 +1,103 @@ +锘// +using LingTest.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LingTest.Migrations.PostgreSql +{ + [DbContext(typeof(StoreDbContext))] + [Migration("20250402121617_initCreate")] + partial class initCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LingTest.Entitys.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreateTimeStamp") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("TeaColm") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex1") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex2") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex3") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TestIndex"); + + b.HasIndex("TestIndex1") + .IsUnique(); + + b.HasIndex("TestIndex1", "TestIndex2") + .IsUnique(); + + b.HasIndex("TestIndex2", "TestIndex3"); + + b.ToTable("Orders", "dbo"); + }); + + modelBuilder.Entity("LingTest.Entitys.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Price") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Products", "dbo"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LingTest/Migrations/PostgreSql/20250402121617_initCreate.cs b/LingTest/Migrations/PostgreSql/20250402121617_initCreate.cs new file mode 100644 index 0000000000000000000000000000000000000000..0174ddeba0421377af96ef4eea72d90a10ed9414 --- /dev/null +++ b/LingTest/Migrations/PostgreSql/20250402121617_initCreate.cs @@ -0,0 +1,101 @@ +锘縰sing Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LingTest.Migrations.PostgreSql +{ + /// + public partial class initCreate : Migration + { + //DynamicShard妗嗘灦娉ㄥ叆鍔ㄦ佸垎鐗囧弬鏁 + private readonly string shardingTablePrefix; + private readonly string shardingSchemaPostfix; + public initCreate(string _shardingTablePrefix,string _shardingSchemaPostfix) + { + this.shardingTablePrefix = _shardingTablePrefix; + this.shardingSchemaPostfix = _shardingSchemaPostfix; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "dbo"); + + migrationBuilder.CreateTable( + name: $"{this.shardingTablePrefix}Orders", + schema: "dbo"+this.shardingSchemaPostfix, + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TestIndex = table.Column(type: "text", nullable: false), + TestIndex1 = table.Column(type: "text", nullable: false), + TestIndex2 = table.Column(type: "text", nullable: false), + TestIndex3 = table.Column(type: "text", nullable: false), + TeaColm = table.Column(type: "text", nullable: false), + IsDeleted = table.Column(type: "boolean", nullable: false), + CreateTimeStamp = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey($"{this.shardingTablePrefix}PK_Orders", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: $"{this.shardingTablePrefix}Products", + schema: "dbo"+this.shardingSchemaPostfix, + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "character varying(50)", maxLength: 50, nullable: false), + Category = table.Column(type: "text", nullable: false), + Price = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey($"{this.shardingTablePrefix}PK_Products", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + column: "TestIndex"); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex1", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + column: "TestIndex1", + unique: true); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex1_TestIndex2", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + columns: new[] { "TestIndex1", "TestIndex2" }, + unique: true); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex2_TestIndex3", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + columns: new[] { "TestIndex2", "TestIndex3" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: $"{this.shardingTablePrefix}Orders", + schema: "dbo"+this.shardingSchemaPostfix); + + migrationBuilder.DropTable( + name: $"{this.shardingTablePrefix}Products", + schema: "dbo"+this.shardingSchemaPostfix); + } + } +} diff --git a/LingTest/Migrations/PostgreSql/StoreDbContextModelSnapshot.cs b/LingTest/Migrations/PostgreSql/StoreDbContextModelSnapshot.cs new file mode 100644 index 0000000000000000000000000000000000000000..1e980f4436999b069b85d1b4bd4913fef0165737 --- /dev/null +++ b/LingTest/Migrations/PostgreSql/StoreDbContextModelSnapshot.cs @@ -0,0 +1,100 @@ +锘// +using LingTest.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace LingTest.Migrations.PostgreSql +{ + [DbContext(typeof(StoreDbContext))] + partial class StoreDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("LingTest.Entitys.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreateTimeStamp") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .HasColumnType("boolean"); + + b.Property("TeaColm") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex1") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex2") + .IsRequired() + .HasColumnType("text"); + + b.Property("TestIndex3") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("TestIndex"); + + b.HasIndex("TestIndex1") + .IsUnique(); + + b.HasIndex("TestIndex1", "TestIndex2") + .IsUnique(); + + b.HasIndex("TestIndex2", "TestIndex3"); + + b.ToTable("Orders", "dbo"); + }); + + modelBuilder.Entity("LingTest.Entitys.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Price") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Products", "dbo"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LingTest/Migrations/SqlServer/20250402060722_initCreate.Designer.cs b/LingTest/Migrations/SqlServer/20250402060722_initCreate.Designer.cs new file mode 100644 index 0000000000000000000000000000000000000000..bf7b03c0488d6336110ffe391a236221f0ee9e49 --- /dev/null +++ b/LingTest/Migrations/SqlServer/20250402060722_initCreate.Designer.cs @@ -0,0 +1,103 @@ +锘// +using LingTest.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace LingTest.Migrations.SqlServer +{ + [DbContext(typeof(StoreDbContext))] + [Migration("20250402060722_initCreate")] + partial class initCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("LingTest.Entitys.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateTimeStamp") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("TeaColm") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TestIndex") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TestIndex1") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TestIndex2") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TestIndex3") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("TestIndex"); + + b.HasIndex("TestIndex1") + .IsUnique(); + + b.HasIndex("TestIndex1", "TestIndex2") + .IsUnique(); + + b.HasIndex("TestIndex2", "TestIndex3"); + + b.ToTable("Orders", "dbo"); + }); + + modelBuilder.Entity("LingTest.Entitys.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Price") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Products", "dbo"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LingTest/Migrations/SqlServer/20250402060722_initCreate.cs b/LingTest/Migrations/SqlServer/20250402060722_initCreate.cs new file mode 100644 index 0000000000000000000000000000000000000000..f71e7740cf4bf0810479a49d0d3809ee2daf0c97 --- /dev/null +++ b/LingTest/Migrations/SqlServer/20250402060722_initCreate.cs @@ -0,0 +1,100 @@ +锘縰sing Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace LingTest.Migrations.SqlServer +{ + /// + public partial class initCreate : Migration + { + //DynamicShard妗嗘灦娉ㄥ叆鍔ㄦ佸垎鐗囧弬鏁 + private readonly string shardingTablePrefix; + private readonly string shardingSchemaPostfix; + public initCreate(string _shardingTablePrefix,string _shardingSchemaPostfix) + { + this.shardingTablePrefix = _shardingTablePrefix; + this.shardingSchemaPostfix = _shardingSchemaPostfix; + } + + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "dbo"); + + migrationBuilder.CreateTable( + name: $"{this.shardingTablePrefix}Orders", + schema: "dbo"+this.shardingSchemaPostfix, + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + TestIndex = table.Column(type: "nvarchar(450)", nullable: false), + TestIndex1 = table.Column(type: "nvarchar(450)", nullable: false), + TestIndex2 = table.Column(type: "nvarchar(450)", nullable: false), + TestIndex3 = table.Column(type: "nvarchar(450)", nullable: false), + TeaColm = table.Column(type: "nvarchar(max)", nullable: false), + IsDeleted = table.Column(type: "bit", nullable: false), + CreateTimeStamp = table.Column(type: "bigint", nullable: false) + }, + constraints: table => + { + table.PrimaryKey($"{this.shardingTablePrefix}PK_Orders", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: $"{this.shardingTablePrefix}Products", + schema: "dbo"+this.shardingSchemaPostfix, + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(50)", maxLength: 50, nullable: false), + Category = table.Column(type: "nvarchar(max)", nullable: false), + Price = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey($"{this.shardingTablePrefix}PK_Products", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + column: "TestIndex"); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex1", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + column: "TestIndex1", + unique: true); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex1_TestIndex2", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + columns: new[] { "TestIndex1", "TestIndex2" }, + unique: true); + + migrationBuilder.CreateIndex( + name: $"{this.shardingTablePrefix}IX_Orders_TestIndex2_TestIndex3", + schema: "dbo"+this.shardingSchemaPostfix, + table: $"{this.shardingTablePrefix}Orders", + columns: new[] { "TestIndex2", "TestIndex3" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: $"{this.shardingTablePrefix}Orders", + schema: "dbo"+this.shardingSchemaPostfix); + + migrationBuilder.DropTable( + name: $"{this.shardingTablePrefix}Products", + schema: "dbo"+this.shardingSchemaPostfix); + } + } +} diff --git a/LingTest/Migrations/SqlServer/StoreDbContextModelSnapshot.cs b/LingTest/Migrations/SqlServer/StoreDbContextModelSnapshot.cs new file mode 100644 index 0000000000000000000000000000000000000000..36dd1a295ead4014461f8149fa2b9274145d31b4 --- /dev/null +++ b/LingTest/Migrations/SqlServer/StoreDbContextModelSnapshot.cs @@ -0,0 +1,100 @@ +锘// +using LingTest.DbContexts; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace LingTest.Migrations.SqlServer +{ + [DbContext(typeof(StoreDbContext))] + partial class StoreDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("LingTest.Entitys.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CreateTimeStamp") + .HasColumnType("bigint"); + + b.Property("IsDeleted") + .HasColumnType("bit"); + + b.Property("TeaColm") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("TestIndex") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TestIndex1") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TestIndex2") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("TestIndex3") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("TestIndex"); + + b.HasIndex("TestIndex1") + .IsUnique(); + + b.HasIndex("TestIndex1", "TestIndex2") + .IsUnique(); + + b.HasIndex("TestIndex2", "TestIndex3"); + + b.ToTable("Orders", "dbo"); + }); + + modelBuilder.Entity("LingTest.Entitys.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Category") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Price") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Products", "dbo"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/LingTest/MyDesignTimeServices.cs b/LingTest/MyDesignTimeServices.cs new file mode 100644 index 0000000000000000000000000000000000000000..5969c8607cae55730bb0e52a9e5e175dc783a261 --- /dev/null +++ b/LingTest/MyDesignTimeServices.cs @@ -0,0 +1,15 @@ +锘縰sing LingYanAspCoreFramework.DynamicShard.EFCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Migrations.Design; + +namespace LingTest +{ + public class MyDesignTimeServices : IDesignTimeServices + { + public void ConfigureDesignTimeServices(IServiceCollection serviceCollection) + { + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + } + } +} diff --git a/LingTest/RestApiModule.cs b/LingTest/RestApiModule.cs index c65aed1205915e35105d181bc1ac493a10ad15c8..85f3b50f933be3207e1495b862b48c0f43ac24d4 100644 --- a/LingTest/RestApiModule.cs +++ b/LingTest/RestApiModule.cs @@ -1,4 +1,9 @@ -锘縰sing LingYanAspCoreFramework.BaseRoots; +锘縰sing LingTest.DbContexts; +using LingYanAspCoreFramework.BaseRoots; +using LingYanAspCoreFramework.DynamicShard.Core; +using LingYanAspCoreFramework.DynamicShard.Core.Extension; +using LingYanAspCoreFramework.DynamicShard.Models.Enum; +using LingYanAspCoreFramework.Helpers; namespace LingTest { @@ -6,14 +11,51 @@ namespace LingTest { public override void ARegisterModule(WebApplicationBuilder services) { + //娉ㄥ唽鍔ㄦ佸垎搴撳垎妯″紡鍒嗚〃璁捐 + services.Services.AddDynamicSharding(dynamicSettingsFunc => + { + //鍒嗗簱濮旀墭-杩斿洖杩炴帴瀛楃涓诧紙string锛 + dynamicSettingsFunc.ConnectionNameFunc = (serviceProvider, dynamicShardInfo) => + { + Dictionary> connectionDic = new Dictionary>(); + connectionDic["mysql"] = new Tuple( + ConnectionType.Mysql, + $"server=192.168.188.128;port=3306;database={dynamicShardInfo?.RequestOtherHeader["ShardingDbName"]};user=laoda;password=12345678;charset=utf8mb4;AllowLoadLocalInfile=true;SslMode=none;" + ); + connectionDic["pgsql"] = new Tuple( + ConnectionType.PostgreSql, + $"Host=192.168.188.128;Database={dynamicShardInfo?.RequestOtherHeader["ShardingDbName"]};Username=postgres;Password=12345678;" + ); + connectionDic["sqlserver"] = new Tuple( + ConnectionType.SqlServer, + $"Server=192.168.188.129;Database={dynamicShardInfo?.RequestOtherHeader["ShardingDbName"]};User Id=sa;Password=12345678;Encrypt=False;" + ); + LoggerHelper.DefaultLog($"鏁版嵁搴撶被鍨:{dynamicShardInfo.ShardingDataBase},杩炴帴瀛楃涓瞷connectionDic[dynamicShardInfo.ShardingDataBase]}"); + return connectionDic[dynamicShardInfo.ShardingDataBase]; + }; + //鍒嗘ā寮忓鎵-杩斿洖妯″紡鍚嶏紙string锛 + dynamicSettingsFunc.SchemaNameFunc = (serviceProvider,dynamicShardInfo) => + { + return dynamicShardInfo?.ShardingSchema; + }; + //鍒嗚〃濮旀墭-杩斿洖鍒嗚〃鍓嶇紑锛坰tring锛 + dynamicSettingsFunc.TablePrefixFunc = (serviceProvider,dynamicShardInfo) => + { + return dynamicShardInfo?.ShardingTable; + }; + }); } public override void BInitializationModule(WebApplication provider) { - //Task.Run(async () => - //{ - // await provider.Services.InitSeedData(); - //}).Wait(); + + //浣跨敤鍔ㄦ佸垎搴撳垎妯″紡鍒嗚〃璁捐涓棿浠讹紝姝や腑闂翠欢璋冪敤DynamicShardInfoGenerator鍒嗙墖淇℃伅鐢熸垚鍣紝濉厖鍒嗙墖淇℃伅 + provider.UseMiddleware(); + + //鍒嗙墖淇℃伅鐢熸垚鍣ㄦ帴鍙DynamicShardInfoGenerator锛屽湪鍒嗙墖淇℃伅鐢熸垚鍣ㄤ腑璇诲彇HTTPS璇锋眰澶磋繘琛屽~鍏咃紝鍒嗗簱鍊笺佸垎妯″紡鍊笺佸垎琛ㄥ硷紝鍙墿灞 + //dynamicShardInfo.ShardingDataBase = httpContext?.Request?.Headers["ShardingDataBase"]; + //dynamicShardInfo.ShardingSchema = httpContext?.Request?.Headers["ShardingSchema"]; + //dynamicShardInfo.ShardingTable = httpContext?.Request?.Headers["ShardingTable"]; } } } \ No newline at end of file diff --git a/LingTest/TestProvider/ITestService.cs b/LingTest/TestProvider/ITestService.cs new file mode 100644 index 0000000000000000000000000000000000000000..92f51b268eb6789e0e9d76d6eb5aaeecfd64d5d3 --- /dev/null +++ b/LingTest/TestProvider/ITestService.cs @@ -0,0 +1,9 @@ +锘縰sing LingYanAspCoreFramework.Models; + +namespace LingTest.TestProvider +{ + public interface ITestService + { + ResponceBody TestBack(); + } +} \ No newline at end of file diff --git a/LingTest/TestProvider/TestService.cs b/LingTest/TestProvider/TestService.cs new file mode 100644 index 0000000000000000000000000000000000000000..613e21703fcda438fe57b2d1f9eceb0e249bf5d1 --- /dev/null +++ b/LingTest/TestProvider/TestService.cs @@ -0,0 +1,15 @@ +锘縰sing LingYanAspCoreFramework.Attributes; +using LingYanAspCoreFramework.Models; + +namespace LingTest.TestProvider +{ + //璇ョ壒鎬у彧闇瑕佹墦鍦ㄦ湇鍔$被涓婏紝浼犲叆鎺ュ彛绫诲瀷鍗冲彲锛屾鏋朵細鍦ㄥ惎鍔ㄦ椂鑷姩娉ㄥ叆 + [LYTService(typeof(ITestService))] + public class TestService : ITestService + { + public ResponceBody TestBack() + { + return new ResponceBody(20000, "娴嬭瘯杩斿洖"); + } + } +} diff --git a/LingTest/appsettings.json b/LingTest/appsettings.json index ec04bc120fb7f339ce3c5ef898d3db32f7366a0c..7153dabdc03eda417abb3cc2ececf28965a7568e 100644 --- a/LingTest/appsettings.json +++ b/LingTest/appsettings.json @@ -4,6 +4,6 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" } - }, + }, "AllowedHosts": "*" } \ No newline at end of file diff --git a/LingYanAspCoreFramework/Attributes/LYDbContextAttribute.cs b/LingYanAspCoreFramework/Attributes/LYDbContextAttribute.cs index 132929479774adbd1b993f24f8c9dd40e3639033..9b26e7eceefe114ec3d86f5607b0270d6af4df39 100644 --- a/LingYanAspCoreFramework/Attributes/LYDbContextAttribute.cs +++ b/LingYanAspCoreFramework/Attributes/LYDbContextAttribute.cs @@ -3,35 +3,11 @@ [AttributeUsage(AttributeTargets.Class, Inherited = true)] public class LYDbContextAttribute : Attribute { - public DbContextType DbContextType { get; set; } public string ConnectionString { get; set; } - public Type[] ShardingTable { get; set; } - public LYDbContextAttribute(string connectionString, DbContextType dbContextType = DbContextType.DbContext, params Type[] shardingTable) + public LYDbContextAttribute(string connectionString) { this.ConnectionString = connectionString; - DbContextType = dbContextType; - ShardingTable = shardingTable; } } - - public enum DataBaseType - { - MYSQL = 1, - MSSQL = 2 - } - - public enum DbContextType - { - DbContext = 1, - TenantConfigDbContext = 2, - TenantTemplateDbContext = 3, - ShardingDbContext = 4 - } - - public enum ShardingKeyType - { - Mod = 1, - Time = 2 - } } \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseEntity.cs b/LingYanAspCoreFramework/BaseRoots/BaseEntity.cs index 2a442a4ca3f03368707220b44ff9fa1529814b18..b61ea3e554dfff428e1129c88362d2857e83cd1b 100644 --- a/LingYanAspCoreFramework/BaseRoots/BaseEntity.cs +++ b/LingYanAspCoreFramework/BaseRoots/BaseEntity.cs @@ -6,7 +6,7 @@ namespace LingYanAspCoreFramework.BaseRoots { public long Id { get; set; } - //10鏂板缓銆20鍒犻櫎 + //鐪熷垹闄わ紝鍋囦笉鍒犻櫎 public bool IsDeleted { get; set; } public long CreateTimeStamp { get; set; } diff --git a/LingYanAspCoreFramework/BaseRoots/BaseModule.cs b/LingYanAspCoreFramework/BaseRoots/BaseModule.cs index 2137c1a1a614dea7f73a85682cbbee5ce578fbda..1732efe4bc817c067d4daed7e8d6dc3478c67214 100644 --- a/LingYanAspCoreFramework/BaseRoots/BaseModule.cs +++ b/LingYanAspCoreFramework/BaseRoots/BaseModule.cs @@ -6,9 +6,9 @@ { public virtual int PageIndex { get; set; } - public abstract void ARegisterModule(TCollection services); + public abstract void ARegisterModule(TCollection AppBuilder); - public abstract void BInitializationModule(TProvider provider); + public abstract void BInitializationModule(TProvider App); } public abstract class BaseModule @@ -18,8 +18,8 @@ { public virtual int PageIndex { get; set; } - public abstract void ARegisterModule(TCollection services, TConfiguration configuration); + public abstract void ARegisterModule(TCollection AppBuilder, TConfiguration configuration); - public abstract void BInitializationModule(TProvider provider); + public abstract void BInitializationModule(TProvider App); } } \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseRole.cs b/LingYanAspCoreFramework/BaseRoots/BaseRole.cs index 7c74c3301858afca8387c0177ad1c2a8666228a3..10e2370612f79862e8f53ab61ad3241e939000cd 100644 --- a/LingYanAspCoreFramework/BaseRoots/BaseRole.cs +++ b/LingYanAspCoreFramework/BaseRoots/BaseRole.cs @@ -1,8 +1,6 @@ 锘縩amespace LingYanAspCoreFramework.BaseRoots { - public class BaseRole : BaseEntity + public class BaseRole: BaseEntity { - public string RoleName { get; set; } - public string Description { get; set; } } -} \ No newline at end of file +} diff --git a/LingYanAspCoreFramework/BaseRoots/BaseRoleRouteGroup.cs b/LingYanAspCoreFramework/BaseRoots/BaseRoleRouteGroup.cs deleted file mode 100644 index 1509ec0a0f5148d7bbc0ee36922b859bfde04cab..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/BaseRoots/BaseRoleRouteGroup.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.BaseRoots -{ - public class BaseRoleRouteGroup : BaseEntity - { - public long RoleId { get; set; } - public long RouteId { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseRoute.cs b/LingYanAspCoreFramework/BaseRoots/BaseRoute.cs index 88b9b2be33063b6c4479509b752ab8c168c0f6aa..af0638c2270a851e6a45b380869159917211f95c 100644 --- a/LingYanAspCoreFramework/BaseRoots/BaseRoute.cs +++ b/LingYanAspCoreFramework/BaseRoots/BaseRoute.cs @@ -1,5 +1,4 @@ 锘縰sing LingYanAspCoreFramework.Helpers; -using System.ComponentModel.DataAnnotations.Schema; using System.Reflection; namespace LingYanAspCoreFramework.BaseRoots @@ -11,26 +10,15 @@ namespace LingYanAspCoreFramework.BaseRoots public virtual string DisplayFullName { get; set; } public virtual string Controller { get; set; } public virtual string? ControllerSummary { get; set; } - public virtual string ControllerFullName { get; set; } + public virtual string ControllerFullName { get; set; } public virtual string RouteTemplate { get; set; } public virtual string HttpMethod { get; set; } public virtual string RoutePrefix { get; set; } public virtual string ProjectName { get; set; } - - [NotMapped] internal MethodInfo RefMethodInfo { get; set; } - - public BaseRoute() : base() + public BaseRoute() { this.ProjectName = ProjectHelper.GetProjectName(); } - - public void UpdateEvent(BaseRoute baseRoute) - { - if (baseRoute != null) - { - this.Id = baseRoute.Id; - } - } } } \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseSysOwner.cs b/LingYanAspCoreFramework/BaseRoots/BaseSysOwner.cs deleted file mode 100644 index e281f827ad6fa26e2cc6571ea84f5f45bdbd3f38..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/BaseRoots/BaseSysOwner.cs +++ /dev/null @@ -1,11 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.BaseRoots -{ - public class BaseSysOwner - { - public virtual Tid Id { get; set; } - public virtual string Name { get; set; } - public virtual string Password { get; set; } - public virtual DateTime CreationTime { get; set; } - public virtual bool IsDeleted { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseSysOwnerTenantConfig.cs b/LingYanAspCoreFramework/BaseRoots/BaseSysOwnerTenantConfig.cs deleted file mode 100644 index 5205fbb6197804d04df197110b6f6dd5fde29483..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/BaseRoots/BaseSysOwnerTenantConfig.cs +++ /dev/null @@ -1,16 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.BaseRoots -{ - public class BaseSysOwnerTenantConfig - { - public virtual Tid Id { get; set; } - - //浼佷笟鍏宠仈瀛楁 - public virtual long CompanyId { get; set; } - - //鏁版嵁搴撹繛鎺ュ瓧绗︿覆 - public virtual string ConfigJson { get; set; } - - public virtual DateTime CreationTime { get; set; } - public virtual bool IsDeleted { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseUser.cs b/LingYanAspCoreFramework/BaseRoots/BaseUser.cs deleted file mode 100644 index ec372f1d71cd105262271580ed37c9ba1f46f70b..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/BaseRoots/BaseUser.cs +++ /dev/null @@ -1,11 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.BaseRoots -{ - public class BaseUser : BaseEntity - { - public string NickName { get; set; } - public string Phone { get; set; } - public string Password { get; set; } - public string Email { get; set; } - public string Avatar { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/BaseRoots/BaseUserRoleGroup.cs b/LingYanAspCoreFramework/BaseRoots/BaseUserRoleGroup.cs deleted file mode 100644 index 1f05b624c109b7573628ef20ac907da1ef6ac5bc..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/BaseRoots/BaseUserRoleGroup.cs +++ /dev/null @@ -1,8 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.BaseRoots -{ - public class BaseUserRoleGroup : BaseEntity - { - public long UserId { get; set; } - public long RoleId { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/DynamicApis/DynamicControllerConvention.cs b/LingYanAspCoreFramework/DynamicApis/DynamicApplicationModelConvention.cs similarity index 90% rename from LingYanAspCoreFramework/DynamicApis/DynamicControllerConvention.cs rename to LingYanAspCoreFramework/DynamicApis/DynamicApplicationModelConvention.cs index 4bf7c56f01ee949d6a75cf7a3a9bf07738e04b09..a02507d6c33f32cd53cac8d4c21ebc84159539fd 100644 --- a/LingYanAspCoreFramework/DynamicApis/DynamicControllerConvention.cs +++ b/LingYanAspCoreFramework/DynamicApis/DynamicApplicationModelConvention.cs @@ -1,20 +1,16 @@ 锘縰sing LingYanAspCoreFramework.Attributes; using LingYanAspCoreFramework.BaseRoots; using LingYanAspCoreFramework.Models; +using LingYanAspCoreFramework.SampleRoots; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ActionConstraints; using Microsoft.AspNetCore.Mvc.ApplicationModels; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.Extensions.Configuration; -namespace LingYanAspCoreFramework.DynamicApis +namespace LingYanAspCoreFramework.DynamicApis { - internal class DynamicControllerConvention : IApplicationModelConvention + internal class DynamicApplicationModelConvention : IApplicationModelConvention { - private IConfiguration _configuration; - public DynamicControllerConvention(IConfiguration configuration) - { - _configuration = configuration; - } public void Apply(ApplicationModel application) { //寰幆姣忎竴涓帶鍒跺櫒淇℃伅 @@ -121,13 +117,13 @@ namespace LingYanAspCoreFramework.DynamicApis private AttributeRouteModel CreateActionRoutePath(string controllerName, string actionName) { string routePrefix=""; - if (!string.IsNullOrEmpty(_configuration.GetSection("DynamicHttpRoutePrefix").Get())) + if (!string.IsNullOrEmpty(LingYanRuntimeManager.CommonConfigModel.DynamicHttpRoutePrefix)) { - routePrefix = _configuration.GetSection("DynamicHttpRoutePrefix").Get(); + routePrefix = LingYanRuntimeManager.CommonConfigModel.DynamicHttpRoutePrefix; } else { - throw new CommonException(new ResponceBody(60010)); + throw new CommonException(new ResponceBody(60000, "閰嶇疆鏂囦欢涓嶅寘鍚獶ynamicHttpRoutePrefix閿")); } //鍒涘缓璺敱璺緞 var routePath = string.Concat(routePrefix + "/", controllerName + "/", actionName).Replace("//", "/"); diff --git a/LingYanAspCoreFramework/DynamicApis/MvcOptionsExtensions.cs b/LingYanAspCoreFramework/DynamicApis/MvcOptionsExtensions.cs index 5009082bd5499ca86768b4168d0962c2142393b1..5e001184cae740050b0e3d2577242176b88a62bd 100644 --- a/LingYanAspCoreFramework/DynamicApis/MvcOptionsExtensions.cs +++ b/LingYanAspCoreFramework/DynamicApis/MvcOptionsExtensions.cs @@ -1,7 +1,4 @@ -锘縰sing LingYanAspCoreFramework.DynamicApis; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Routing; -using Microsoft.Extensions.Configuration; +锘縰sing Microsoft.AspNetCore.Mvc; namespace LingYanAspCoreFramework.DynamicApis { @@ -12,9 +9,9 @@ namespace LingYanAspCoreFramework.DynamicApis /// /// /// - public static void UseCentralRouteJsonConfig(this MvcOptions opts, IConfiguration configuration) + public static void UseCentralRouteJsonConfig(this MvcOptions opts) { - opts.Conventions.Insert(0, new DynamicControllerConvention(configuration)); + opts.Conventions.Insert(0, new DynamicApplicationModelConvention()); } } } diff --git a/LingYanAspCoreFramework/DynamicShard/Core/DynamicShardInfoMiddleware.cs b/LingYanAspCoreFramework/DynamicShard/Core/DynamicShardInfoMiddleware.cs new file mode 100644 index 0000000000000000000000000000000000000000..184876e1030dde67fa4a0b4360de1678d192c855 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Core/DynamicShardInfoMiddleware.cs @@ -0,0 +1,21 @@ +using LingYanAspCoreFramework.DynamicShard.Core.Interface; +using Microsoft.AspNetCore.Http; + +namespace LingYanAspCoreFramework.DynamicShard.Core +{ + public class DynamicShardInfoMiddleware + { + private readonly RequestDelegate _next; + + public DynamicShardInfoMiddleware(RequestDelegate next) + { + _next = next; + } + + public async Task InvokeAsync(HttpContext context, IDynamicShardInfoGenerator dynamicShardInfoGenerator) + { + dynamicShardInfoGenerator.GenerateDynamicShardInfo(this, context); + await _next(context); + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Core/Extension/DynamicShardCoreExtension.cs b/LingYanAspCoreFramework/DynamicShard/Core/Extension/DynamicShardCoreExtension.cs new file mode 100644 index 0000000000000000000000000000000000000000..19befcb68dda8558fcf812ed2aa2015ac1390dd7 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Core/Extension/DynamicShardCoreExtension.cs @@ -0,0 +1,104 @@ +using LingYanAspCoreFramework.DynamicShard.Core.Impl; +using LingYanAspCoreFramework.DynamicShard.Core.Interface; +using LingYanAspCoreFramework.DynamicShard.EFCore; +using LingYanAspCoreFramework.DynamicShard.EFCore.Impl; +using LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using LingYanAspCoreFramework.DynamicShard.Models; +using LingYanAspCoreFramework.DynamicShard.Models.Enum; +using LingYanAspCoreFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace LingYanAspCoreFramework.DynamicShard.Core.Extension +{ + public static class DynamicShardCoreExtension + { + public static IServiceCollection AddDynamicSharding(this IServiceCollection services, Action> dynamicSettingsFunc) + where TDbContext : DbContext, IDynamicShardtDbContext + { + services.AddScoped(); + services.AddScoped(); + services.TryAddScoped(); + services.TryAddScoped, DynamicShardConnectionResolver>(); + services.TryAddScoped, DynamicShardEntityBuilder>(); + services.TryAddScoped, DynamicShardEntityScaner>(); + services.AddSingleton(dynamicSettingsFunc.ConfigShardingConnectionType()); + services.AddDbContext((serviceProvider, options) => + { + var dynamicShardSettings = serviceProvider.GetRequiredService>(); + var connectionResolver = serviceProvider.GetRequiredService>(); + var dynamicShardOption = connectionResolver.GetConnection(); + dynamicShardSettings?.DbContextOptionDelegate?.Invoke(dynamicShardOption, options); + }); + return services; + } + internal static Func> ConfigShardingConnectionType(this Action> dynamicShardSettingsAction) + where TDbContext : DbContext, IDynamicShardtDbContext + { + Func> dynamicShardOptionConfigFunc = (serviceProvider) => + { + var dynamicShardSettings = new DynamicShardSettings(); + dynamicShardSettings.DbContextOptionDelegate = (dynamicShardOption, optionsBuilder) => + { + if (string.IsNullOrEmpty(dynamicShardOption.ConnectionName)) + { + throw new CommonException(new ResponceBody(63000, "连接字符串不能为空")); + } + optionsBuilder.DbContextOptionsBuilderSetting(dynamicShardOption); + optionsBuilder.ReplaceService>(); + optionsBuilder.ReplaceService(); + + }; + dynamicShardSettingsAction?.Invoke(dynamicShardSettings); + return dynamicShardSettings; + }; + return dynamicShardOptionConfigFunc; + } + internal static void DbContextOptionsBuilderSetting(this DbContextOptionsBuilder dbContextOptionsBuilder, DynamicShardOption dynamicShardOption) + { + switch (dynamicShardOption.ConnectionType) + { + case ConnectionType.Mysql: + dbContextOptionsBuilder.UseMySql(dynamicShardOption.ConnectionName, ServerVersion.AutoDetect(dynamicShardOption.ConnectionName), builder => + { + builder.DbContextOptionsBuilderMigrationHistory(dynamicShardOption); + }); + break; + case ConnectionType.PostgreSql: + dbContextOptionsBuilder.UseNpgsql(dynamicShardOption.ConnectionName, builder => + { + builder.DbContextOptionsBuilderMigrationHistory(dynamicShardOption); + }); + break; + case ConnectionType.SqlServer: + dbContextOptionsBuilder.UseSqlServer(dynamicShardOption.ConnectionName, builder => + { + builder.DbContextOptionsBuilderMigrationHistory(dynamicShardOption); + }); + break; + } + } + internal static void DbContextOptionsBuilderMigrationHistory(this RelationalDbContextOptionsBuilder relationalDbContextOptionsBuilder, DynamicShardOption dynamicShardOption) + where TBuilder : RelationalDbContextOptionsBuilder + where TExtension : RelationalOptionsExtension, new() + { + switch (dynamicShardOption.ConnectionType) + { + case ConnectionType.Mysql: + relationalDbContextOptionsBuilder.MigrationsHistoryTable($"{dynamicShardOption.TablePrefix}EFMigrationHistory"); + break; + case ConnectionType.SqlServer: + relationalDbContextOptionsBuilder.MigrationsHistoryTable($"{dynamicShardOption.TablePrefix}EFMigrationHistory", $"dbo{dynamicShardOption.SchemaPostfix}"); + break; + case ConnectionType.PostgreSql: + relationalDbContextOptionsBuilder.MigrationsHistoryTable($"{dynamicShardOption.TablePrefix}EFMigrationHistory", $"dbo{dynamicShardOption.SchemaPostfix}"); + break; + } + } + + } + +} diff --git a/LingYanAspCoreFramework/DynamicShard/Core/Impl/DynamicShardConnectionResolver.cs b/LingYanAspCoreFramework/DynamicShard/Core/Impl/DynamicShardConnectionResolver.cs new file mode 100644 index 0000000000000000000000000000000000000000..c22ca731db9892f0a555cad641dadc41cebab335 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Core/Impl/DynamicShardConnectionResolver.cs @@ -0,0 +1,37 @@ +using LingYanAspCoreFramework.DynamicShard.Core.Interface; +using LingYanAspCoreFramework.DynamicShard.Models; +using Microsoft.EntityFrameworkCore; + +namespace LingYanAspCoreFramework.DynamicShard.Core.Impl +{ + public class DynamicShardConnectionResolver : IDynamicShardConnectionResolver + where TDbContext : DbContext + { + private readonly DynamicShardSettings dynamicShardSettings; + private readonly DynamicShardInfo dynamicShardInfo; + private readonly IServiceProvider serviceProvider; + private readonly DynamicShardOption dynamicShardOption; + + public DynamicShardConnectionResolver(DynamicShardSettings dynamicShardSettings, + DynamicShardInfo dynamicShardInfo, + DynamicShardOption dynamicShardOption, + IServiceProvider serviceProvider) + { + this.dynamicShardOption = dynamicShardOption; + this.dynamicShardSettings = dynamicShardSettings; + this.dynamicShardInfo = dynamicShardInfo; + this.serviceProvider = serviceProvider; + } + + public DynamicShardOption GetConnection() + { + var connectionTupple = this.dynamicShardSettings.ConnectionNameFunc?.Invoke(this.serviceProvider, this.dynamicShardInfo); + dynamicShardOption.ConnectionType = connectionTupple!.Item1; + dynamicShardOption.ConnectionName = connectionTupple.Item2; + dynamicShardOption.SchemaPostfix = this.dynamicShardSettings.SchemaNameFunc?.Invoke(this.serviceProvider, this.dynamicShardInfo)!; + dynamicShardOption.TablePrefix = this.dynamicShardSettings.TablePrefixFunc?.Invoke(this.serviceProvider, this.dynamicShardInfo)!; + dynamicShardOption.PostSetting(); + return this.dynamicShardOption; + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Core/Impl/DynamicShardInfoGenerator.cs b/LingYanAspCoreFramework/DynamicShard/Core/Impl/DynamicShardInfoGenerator.cs new file mode 100644 index 0000000000000000000000000000000000000000..b1dd45dbc7e071f9943d7a65ac0357139c3c5c11 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Core/Impl/DynamicShardInfoGenerator.cs @@ -0,0 +1,31 @@ +using LingYanAspCoreFramework.DynamicShard.Core.Interface; +using LingYanAspCoreFramework.DynamicShard.Models; +using Microsoft.AspNetCore.Http; + +namespace LingYanAspCoreFramework.DynamicShard.Core.Impl +{ + public class DynamicShardInfoGenerator : IDynamicShardInfoGenerator + { + private readonly DynamicShardInfo dynamicShardInfo; + public DynamicShardInfoGenerator(DynamicShardInfo dynamicShardInfo) + { + this.dynamicShardInfo = dynamicShardInfo; + } + + public DynamicShardInfo GenerateDynamicShardInfo(object sender, HttpContext httpContext) + { + if (this.dynamicShardInfo.RequestOtherHeader==null) + { + this.dynamicShardInfo.RequestOtherHeader = new Dictionary(); + } + foreach (var item in httpContext.Request.Headers) + { + this.dynamicShardInfo.RequestOtherHeader.TryAdd(item.Key, item.Value); + } + this.dynamicShardInfo.ShardingDataBase = httpContext?.Request?.Headers["ShardingDataBase"]; + this.dynamicShardInfo.ShardingSchema = httpContext?.Request?.Headers["ShardingSchema"]; + this.dynamicShardInfo.ShardingTable = httpContext?.Request?.Headers["ShardingTable"]; + return this.dynamicShardInfo; + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Core/Interface/IDynamicShardConnectionResolver.cs b/LingYanAspCoreFramework/DynamicShard/Core/Interface/IDynamicShardConnectionResolver.cs new file mode 100644 index 0000000000000000000000000000000000000000..c459c8778ec4a73106cc0da307cde9075c8ea0d1 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Core/Interface/IDynamicShardConnectionResolver.cs @@ -0,0 +1,9 @@ +using LingYanAspCoreFramework.DynamicShard.Models; + +namespace LingYanAspCoreFramework.DynamicShard.Core.Interface +{ + public interface IDynamicShardConnectionResolver + { + DynamicShardOption GetConnection(); + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Core/Interface/IDynamicShardInfoGenerator.cs b/LingYanAspCoreFramework/DynamicShard/Core/Interface/IDynamicShardInfoGenerator.cs new file mode 100644 index 0000000000000000000000000000000000000000..dafd089abb0878f343da1bf66cb3f42bf02ba6a8 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Core/Interface/IDynamicShardInfoGenerator.cs @@ -0,0 +1,11 @@ +using LingYanAspCoreFramework.DynamicShard.Models; +using Microsoft.AspNetCore.Http; + +namespace LingYanAspCoreFramework.DynamicShard.Core.Interface +{ + public interface IDynamicShardInfoGenerator + { + DynamicShardInfo GenerateDynamicShardInfo(object sender, HttpContext httpContext); + } + +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationAssembly.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationAssembly.cs new file mode 100644 index 0000000000000000000000000000000000000000..1ddd12eebe5f621ced1e122253bddb4622d19249 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationAssembly.cs @@ -0,0 +1,92 @@ +锘縰sing LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using LingYanAspCoreFramework.Extensions; +using LingYanAspCoreFramework.Helpers; +using LingYanAspCoreFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Migrations.Internal; +using System.Reflection; +namespace LingYanAspCoreFramework.DynamicShard.EFCore +{ + public class DynamicShardMigrationAssembly : MigrationsAssembly + { + private readonly DbContext context; + public DynamicShardMigrationAssembly(ICurrentDbContext currentContext, + IDbContextOptions options, IMigrationsIdGenerator idGenerator, + IDiagnosticsLogger logger) + : base(currentContext, options, idGenerator, logger) + { + context = currentContext.Context; + } + + public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider) + { + if (activeProvider == null) + throw new CommonException(new ResponceBody(63000, $"杩佺Щ鏃,{nameof(activeProvider)}鍙傛暟涓虹┖")); + if (context is IDynamicShardtDbContext dynamicShardtDbContext) + { + var dynamicShardMigration = (Migration)Activator.CreateInstance(migrationClass.AsType(), + dynamicShardtDbContext?.DynamicShardOptionImpl?.TablePrefix, dynamicShardtDbContext!.DynamicShardOptionImpl.SchemaPostfix)!; + dynamicShardMigration.ActiveProvider = activeProvider; + return dynamicShardMigration; + } + return base.CreateMigration(migrationClass, activeProvider); + } + public override IReadOnlyDictionary Migrations + { + get + { + if (context is IDynamicShardtDbContext dynamicShardtDbContext) + { + var dyanamicShardMigrations = new SortedList(); + var items = Assembly.GetConstructibleTypes() + .Where(t => t.IsSubclassOf(typeof(Migration)) + && t.Namespace!.Equals(ProductMigrationNameSpaceStr(dynamicShardtDbContext)) + && t.GetCustomAttribute()?.ContextType == this.context.GetType()) + .Select(t => new + { + Id = t.GetCustomAttribute()?.Id, + Type = t + }) + .Where(x => x.Id != null) + .OrderBy(x => x.Id); + + foreach (var item in items) + { + LoggerHelper.DefaultLog($"杩佺Щ璁板綍:{item.Id},杩佺Щ绫诲瀷:{item.Type}"); + dyanamicShardMigrations!.TryAdd(item.Id, item.Type); + } + return dyanamicShardMigrations; + } + return base.Migrations; + + } + } + + public override ModelSnapshot? ModelSnapshot + { + get + { + if (context is IDynamicShardtDbContext dynamicShardtDbContext) + { + var snapshotType = this.Assembly.GetConstructibleTypes() + .FirstOrDefault(t => t.IsSubclassOf(typeof(ModelSnapshot)) + && t.Namespace!.Equals(ProductMigrationNameSpaceStr(dynamicShardtDbContext)) + && t.GetCustomAttribute()?.ContextType == this.context.GetType()); + if (snapshotType == null) + return null; + var dyanamicShardModelSnapshot = (ModelSnapshot)Activator.CreateInstance(snapshotType.AsType())!; + return dyanamicShardModelSnapshot; + } + return base.ModelSnapshot; + } + } + + private string ProductMigrationNameSpaceStr(IDynamicShardtDbContext dynamicShardtDbContext) + { + return dynamicShardtDbContext.DynamicShardOptionImpl.MigrationNameSpace.Replace("$DynamicShard", this.Assembly.GetName().Name); + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationGenerator.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationGenerator.cs new file mode 100644 index 0000000000000000000000000000000000000000..76df0823cc67e0ec2b8f5aa1313273d2bc4c1ac9 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationGenerator.cs @@ -0,0 +1,147 @@ +锘縰sing LingYanAspCoreFramework.Extensions; +using LingYanAspCoreFramework.Helpers; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations.Design; +using Microsoft.EntityFrameworkCore.Migrations.Operations; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore +{ + public class DynamicShardMigrationGenerator : CSharpMigrationsGenerator + { + + public DynamicShardMigrationGenerator(MigrationsCodeGeneratorDependencies dependencies, + CSharpMigrationsGeneratorDependencies csharpDependencies) : base(dependencies, csharpDependencies) + { + } + public override string GenerateMigration(string migrationNamespace, string migrationName, IReadOnlyList upOperations, + IReadOnlyList downOperations) + { + // 鏋勯犲櫒鍙傛暟 + string ctorTableStr = "shardingTablePrefix"; + string ctorSchemaStr = "shardingSchemaPostfix"; + //杩佺Щ鐢熸垚鍣ㄨ繍琛屽墠缃坊鍔犺〃鍚嶅崰浣嶇 + GernateBeforeUpDownTableName(ctorTableStr, ctorSchemaStr, upOperations, downOperations); + //杩佺Щ鐢熸垚鍣ㄨ繍琛 + var generatedCode = base.GenerateMigration(migrationNamespace, migrationName, upOperations, downOperations); + //鏋勯犲櫒浠g爜鎻掑叆杩佺Щ浠g爜 + generatedCode = GernateAfterCtor(ctorTableStr, ctorSchemaStr, migrationName, generatedCode); + //鏇挎崲琛ㄥ悕涓殑鍗犱綅绗 + generatedCode = generatedCode.Replace($"\"${ctorTableStr}", $"$\"{{this.{ctorTableStr}}}"); + //鏇挎崲妯″紡涓殑鍗犱綅绗 + generatedCode = generatedCode.Replace($"${ctorSchemaStr}\"", $"\"+this.{ctorSchemaStr}"); + return generatedCode; + } + private void GernateBeforeUpDownTableName(string ctorTableStr, string ctorSchemaStr, + IReadOnlyList upOperations, + IReadOnlyList downOperations) + { + // 淇敼涓厤缃姩鎬佽〃鍚 + foreach (var operation in upOperations) + { + TableOperationModify(operation); + } + + // 鍥炴粴涓厤缃姩鎬佽〃鍚 + foreach (var operation in downOperations) + { + TableOperationModify(operation); + } + //琛ㄣ佺储寮曘侀敭銆佺害鏉熴佸垪瀵硅薄淇敼 + void TableOperationModify(MigrationOperation migrationOperation) + { + if (migrationOperation is CreateTableOperation createTableOperation) + { + createTableOperation.Name = GernateBeforeTableName(createTableOperation.Name); + createTableOperation.PrimaryKey.Name = GernateBeforeTableName(createTableOperation.PrimaryKey.Name); + foreach (var foreignKey in createTableOperation.ForeignKeys) + { + foreignKey.Name = GernateBeforeTableName(foreignKey.Name); + } + foreach (var uniqueConstraint in createTableOperation.UniqueConstraints) + { + uniqueConstraint.Name = GernateBeforeTableName(uniqueConstraint.Name); + } + } + else if (migrationOperation is RenameTableOperation renameTableOperation) + { + renameTableOperation.Name = GernateBeforeTableName(renameTableOperation.Name); + renameTableOperation.NewName = GernateBeforeTableName(renameTableOperation.NewName); + } + else if (migrationOperation is DropTableOperation dropTableOperation) + { + dropTableOperation.Name = GernateBeforeTableName(dropTableOperation.Name); + } + else if (migrationOperation is AlterTableOperation alterTableOperation) + { + alterTableOperation.Name = GernateBeforeTableName(alterTableOperation.Name); + } + else + { + //鍒楄〃鍚 + var tableName = migrationOperation.GetPropertyValue("Table"); + if (!string.IsNullOrEmpty(tableName)) + { + migrationOperation.SetPropertyValue("Table", GernateBeforeTableName(tableName)); + } + + if (migrationOperation is AddForeignKeyOperation addForeignKeyOperation) + { + addForeignKeyOperation.Name = GernateBeforeTableName(addForeignKeyOperation.Name); + } + else if (migrationOperation is AddPrimaryKeyOperation addPrimaryKeyOperation) + { + addPrimaryKeyOperation.Name = GernateBeforeTableName(addPrimaryKeyOperation.Name); + } + else if (migrationOperation is AddUniqueConstraintOperation addUniqueConstraintOperation) + { + addUniqueConstraintOperation.Name = GernateBeforeTableName(addUniqueConstraintOperation.Name); + } + else if (migrationOperation is CreateIndexOperation createIndexOperation) + { + createIndexOperation.Name = GernateBeforeTableName(createIndexOperation.Name); + + } + } + //妯″紡鍚 + var schemaName = migrationOperation.GetPropertyValue("Schema"); + if (!string.IsNullOrEmpty(schemaName)) + { + migrationOperation.SetPropertyValue("Schema", GernateAftoreSchemaName(schemaName)); + } + } + //鐢熸垚琛ㄥ悕鍗犱綅绗 + string GernateBeforeTableName(string tableName) + { + return $"${ctorTableStr}{tableName}"; + } + string GernateAftoreSchemaName(string schemaName) + { + return $"{schemaName}${ctorSchemaStr}"; + } + } + private string GernateAfterCtor(string ctorTableStr, string ctorSchemaStr, string migrationName, string generatedCode) + { + + IndentedStringBuilder dynamicShardingCodeBuilder = new IndentedStringBuilder(); + dynamicShardingCodeBuilder.IncrementIndent().IncrementIndent().AppendLine(); + dynamicShardingCodeBuilder.AppendLine("//DynamicShard妗嗘灦娉ㄥ叆鍔ㄦ佸垎鐗囧弬鏁"); + dynamicShardingCodeBuilder.AppendLine($"private readonly string {ctorTableStr};"); + dynamicShardingCodeBuilder.AppendLine($"private readonly string {ctorSchemaStr};"); + dynamicShardingCodeBuilder.AppendLine($"public {migrationName}(string _{ctorTableStr},string _{ctorSchemaStr})"); + dynamicShardingCodeBuilder.AppendLine("{"); + dynamicShardingCodeBuilder.IncrementIndent().AppendLine($"this.{ctorTableStr} = _{ctorTableStr};").DecrementIndent(); + dynamicShardingCodeBuilder.IncrementIndent().AppendLine($"this.{ctorSchemaStr} = _{ctorSchemaStr};").DecrementIndent(); + dynamicShardingCodeBuilder.AppendLine("}"); + var classIndex = generatedCode.IndexOf($"public partial class {migrationName}"); + if (classIndex > 0) + { + var braceIndex = generatedCode.IndexOf("{", classIndex); + if (braceIndex > 0) + { + generatedCode = generatedCode.Insert(braceIndex + 1, dynamicShardingCodeBuilder.ToString()); + } + } + return generatedCode; + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationsScaffolder.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationsScaffolder.cs new file mode 100644 index 0000000000000000000000000000000000000000..7d9e191ee07e0c3ffcc7dee94846d7fc8f94baac --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardMigrationsScaffolder.cs @@ -0,0 +1,42 @@ +锘縰sing LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using LingYanAspCoreFramework.Helpers; +using Microsoft.EntityFrameworkCore.Internal; +using Microsoft.EntityFrameworkCore.Migrations.Design; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore +{ + public class DynamicShardMigrationsScaffolder : MigrationsScaffolder + { + private readonly Type _contextType; + public DynamicShardMigrationsScaffolder(MigrationsScaffolderDependencies dependencies) : base(dependencies) + { + _contextType = dependencies.CurrentContext.Context.GetType(); + } + protected override string GetDirectory(string projectDir, string? siblingFileName, string subnamespace) + { + if (typeof(IDynamicShardtDbContext).IsAssignableFrom(_contextType)) + { + var defaultDirectory = Path.Combine(projectDir, Path.Combine(subnamespace.Split('.'))); + if (siblingFileName != null) + { + if (!siblingFileName.StartsWith(_contextType.Name + "ModelSnapshot.")) + { + var siblingPath = TryGetProjectFile(projectDir, siblingFileName); + if (siblingPath != null) + { + var lastDirectory = Path.GetDirectoryName(siblingPath)!; + if (!defaultDirectory.Equals(lastDirectory, StringComparison.OrdinalIgnoreCase)) + { + Dependencies.OperationReporter.WriteVerbose(DesignStrings.ReusingNamespace(siblingFileName)); + + return lastDirectory; + } + } + } + } + return defaultDirectory; + } + return base.GetDirectory(projectDir, siblingFileName, subnamespace); + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardModelCacheKey.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardModelCacheKey.cs new file mode 100644 index 0000000000000000000000000000000000000000..6baea10aaeb41e011cbbc52678cba915b82928e9 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardModelCacheKey.cs @@ -0,0 +1,57 @@ +using LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore +{ + /// + /// 表示租户模型缓存键的类 + /// + /// 数据库上下文类型 + internal sealed class DynamicShardModelCacheKey : ModelCacheKey + where TDbContext : DbContext, IDynamicShardtDbContext + { + private readonly TDbContext context; + private readonly string identifier; + + /// + /// 初始化 TenantModelCacheKey 类的新实例 + /// + /// 数据库上下文 + /// 租户标识符 + public DynamicShardModelCacheKey(TDbContext context, string identifier) : base(context) + { + this.context = context; + this.identifier = identifier; + } + + /// + /// 确定当前对象是否等于另一个对象 + /// + /// 要与当前对象进行比较的对象 + /// 如果相等,返回 true;否则返回 false + protected override bool Equals(ModelCacheKey other) + { + var isEqual = base.Equals(other) && (other as DynamicShardModelCacheKey)?.identifier == identifier; + return isEqual; + } + + /// + /// 返回当前对象的哈希代码 + /// + /// 当前对象的哈希代码 + public override int GetHashCode() + { + var hashCode = base.GetHashCode(); + if (identifier != null) + { + hashCode ^= identifier.GetHashCode(); + } + return hashCode; + } + } +} + + + + diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardModelCacheKeyFactory.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardModelCacheKeyFactory.cs new file mode 100644 index 0000000000000000000000000000000000000000..b34768c68ecac11d225dabca617f8a4f7719a1ba --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/DynamicShardModelCacheKeyFactory.cs @@ -0,0 +1,48 @@ +using LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore +{ + /// + /// 表示租户模型缓存键工厂的类 + /// + /// 数据库上下文类型 + public sealed class DynamicShardModelCacheKeyFactory : ModelCacheKeyFactory + where TDbContext : DbContext, IDynamicShardtDbContext + { + /// + /// 初始化 TenantModelCacheKeyFactory 类的新实例 + /// + /// 模型缓存键工厂的依赖项 + public DynamicShardModelCacheKeyFactory(ModelCacheKeyFactoryDependencies dependencies) : base(dependencies) + { + + } + public override object Create(DbContext context) + { + return Create(context, false); + } + /// + /// 创建模型缓存键 + /// + /// 数据库上下文 + /// 模型缓存键对象 + public override object Create(DbContext context, bool designTime) + { + // 如果是设计时环境,返回默认缓存键 + if (designTime) + { + return new ModelCacheKey(context, designTime); + } + else + { + var dbContext = context as TDbContext; + var dynamicShardModelCacheKey = new DynamicShardModelCacheKey(dbContext, + dbContext?.DynamicShardOptionImpl?.SchemaPostfix + dbContext?.DynamicShardOptionImpl?.TablePrefix ?? "no_dynamicshard_identifier"); + return dynamicShardModelCacheKey; + + } + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardDbContext.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardDbContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..c3a6535b6977901a823311c4ec08f8666861fcef --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardDbContext.cs @@ -0,0 +1,61 @@ +using LingYanAspCoreFramework.DynamicShard.Core.Extension; +using LingYanAspCoreFramework.DynamicShard.Core.Interface; +using LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using LingYanAspCoreFramework.DynamicShard.Models; +using LingYanAspCoreFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Impl +{ + /// + /// 表示租户基础数据库上下文的抽象类 + /// + public abstract class DynamicShardDbContext : DbContext, IDynamicShardtDbContext + { + /// + /// 获取或设置租户信息 + /// + public DynamicShardOption DynamicShardOptionImpl { get; protected internal set; } + + private readonly IServiceProvider serviceProvider; + public DynamicShardDbContext(DbContextOptions dbContextOptions, DynamicShardOption dynamicShardOption, IServiceProvider serviceProvider) : base(dbContextOptions) + { + this.serviceProvider = serviceProvider; + this.DynamicShardOptionImpl = dynamicShardOption; + try + { + if (this.Database.GetPendingMigrations().Any()) + { + this.Database.Migrate(); + this.Database.EnsureCreated(); + } + } + catch (Exception ex) + { + throw new CommonException(new ResponceBody(63000, ex.Message)); + } + } + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + var builderType = typeof(IDynamicShardEntityBuilder<>).MakeGenericType(GetType()); + IDynamicShardEntityBuilder entityBuilder = (IDynamicShardEntityBuilder)serviceProvider.GetRequiredService(builderType); + entityBuilder.UpdateEntities(modelBuilder); + } + //public async Task FindDbContext(Action> dynamicShardSetting, Func func) + // where TDbContext : DbContext, IDynamicShardtDbContext + //{ + // using (var scope = this.serviceProvider.CreateScope()) + // { + // var dynamicShardSettings = dynamicShardSetting.ConfigShardingConnectionType().Invoke(scope.ServiceProvider); + // var connectionResolver = this.serviceProvider.GetRequiredService>(); + // var dynamicShardOption = connectionResolver.GetConnection(); + // var dbContextOptionsBuilder = new DbContextOptionsBuilder(); + // dynamicShardSettings.DbContextOptionDelegate.Invoke(dynamicShardOption, dbContextOptionsBuilder); + // var dbContext = (TDbContext)Activator.CreateInstance(typeof(TDbContext), dbContextOptionsBuilder.Options, dynamicShardOption, scope.ServiceProvider); + // await func.Invoke(dbContext); + // } + //} + } +} \ No newline at end of file diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardEntityBuilder.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardEntityBuilder.cs new file mode 100644 index 0000000000000000000000000000000000000000..f58332306c1e22a6d3de55c36c6d00975306e177 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardEntityBuilder.cs @@ -0,0 +1,57 @@ +using LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using LingYanAspCoreFramework.DynamicShard.Models; +using LingYanAspCoreFramework.DynamicShard.Models.Enum; +using Microsoft.EntityFrameworkCore; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Impl +{ + /// + /// 表示租户实体构建器的类 + /// + /// 数据库上下文类型 + public class DynamicShardEntityBuilder : IDynamicShardEntityBuilder + where TDbContext : DbContext + { + private readonly IDynamicShardEntityScaner dynamicShardEntityScaner; + private readonly DynamicShardOption dynamicShardOption; + + /// + /// 初始化 + /// + /// + /// + /// + public DynamicShardEntityBuilder(IDynamicShardEntityScaner dynamicShardEntityScaner, + DynamicShardOption dynamicShardOption) + { + this.dynamicShardOption = dynamicShardOption; + this.dynamicShardEntityScaner = dynamicShardEntityScaner; + } + + /// + /// 更新实体模型 + /// + /// 模型构建器 + public void UpdateEntities(ModelBuilder modelBuilder) + { + var dbsetProperties = dynamicShardEntityScaner.ScanEntityTypes(); + foreach (var property in dbsetProperties) + { + var entity = modelBuilder.Entity(property.PropertyType); + var tableName = dynamicShardOption.TablePrefix + property.PropertyName; + switch (dynamicShardOption.ConnectionType) + { + case ConnectionType.Mysql: + entity.ToTable(tableName); + break; + case ConnectionType.SqlServer: + entity.ToTable(tableName, "dbo" + this.dynamicShardOption.SchemaPostfix); + break; + case ConnectionType.PostgreSql: + entity.ToTable(tableName, "dbo" + this.dynamicShardOption.SchemaPostfix); + break; + } + } + } + } +} \ No newline at end of file diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardEntityScaner.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardEntityScaner.cs new file mode 100644 index 0000000000000000000000000000000000000000..6963313681f1ae6dd79181dfdd73420929d9b78b --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Impl/DynamicShardEntityScaner.cs @@ -0,0 +1,64 @@ +using LingYanAspCoreFramework.DynamicShard.EFCore.Interface; +using LingYanAspCoreFramework.DynamicShard.Models; +using Microsoft.EntityFrameworkCore; +using System.Reflection; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Impl +{ + /// + /// 简单实体扫描器类,用于扫描数据库上下文中的实体类型 + /// + /// 数据库上下文类型 + public class DynamicShardEntityScaner : IDynamicShardEntityScaner + where TDbContext : DbContext + { + private static List dbProperties; + private static readonly object locker = new object(); + + /// + /// 扫描数据库上下文中的实体类型 + /// + /// 实体属性列表 + public IList ScanEntityTypes() + { + if (dbProperties == null) + { + lock (locker) + { + if (dbProperties == null) + { + var contextType = typeof(TDbContext); + var properties = contextType.GetProperties(); + var entityProperties = properties.Where(r => IsDbSet(r)).ToList(); + + dbProperties = new List(); + foreach (var property in entityProperties) + { + dbProperties.Add(new DbsetProperty + { + PropertyName = property.Name, + PropertyType = property.PropertyType.GetGenericArguments()[0] + }); + } + } + } + } + return dbProperties; + } + + /// + /// 判断属性是否为 DbSet 类型 + /// + /// 属性信息 + /// 如果是 DbSet 类型,返回 true;否则返回 false + private bool IsDbSet(PropertyInfo property) + { + if (property.CanRead && property.PropertyType.IsGenericType + && typeof(DbSet<>).GetGenericTypeDefinition().Equals(property.PropertyType.GetGenericTypeDefinition())) + { + return true; + } + return false; + } + } +} \ No newline at end of file diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityBuilder.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityBuilder.cs new file mode 100644 index 0000000000000000000000000000000000000000..73406e80a8209bc13a392879bdee08420056977d --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityBuilder.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Interface +{ + /// + /// 表示租户实体构建器的接口 + /// + public interface IDynamicShardEntityBuilder + { + /// + /// 更新实体模型 + /// + /// 模型构建器 + void UpdateEntities(ModelBuilder modelBuilder); + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityBuilderT.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityBuilderT.cs new file mode 100644 index 0000000000000000000000000000000000000000..97bb71879365392fe586db3a913a5ff3601afde9 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityBuilderT.cs @@ -0,0 +1,13 @@ +锘縰sing Microsoft.EntityFrameworkCore; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Interface +{ + /// + /// 琛ㄧず鐗瑰畾鏁版嵁搴撲笂涓嬫枃绫诲瀷鐨勭鎴峰疄浣撴瀯寤哄櫒鐨勬帴鍙 + /// + /// 鏁版嵁搴撲笂涓嬫枃绫诲瀷 + public interface IDynamicShardEntityBuilder : IDynamicShardEntityBuilder + where TDbContext : DbContext + { + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityScaner.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityScaner.cs new file mode 100644 index 0000000000000000000000000000000000000000..cf0f1d6038d60546a3ac368fda06817f7eba9c15 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardEntityScaner.cs @@ -0,0 +1,11 @@ +using LingYanAspCoreFramework.DynamicShard.Models; +using Microsoft.EntityFrameworkCore; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Interface +{ + public interface IDynamicShardEntityScaner + where TDbContext : DbContext + { + IList ScanEntityTypes(); + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardtDbContext.cs b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardtDbContext.cs new file mode 100644 index 0000000000000000000000000000000000000000..52d3c27f19a1468a9f658d9080e9808451c33bb7 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/EFCore/Interface/IDynamicShardtDbContext.cs @@ -0,0 +1,9 @@ +using LingYanAspCoreFramework.DynamicShard.Models; + +namespace LingYanAspCoreFramework.DynamicShard.EFCore.Interface +{ + public interface IDynamicShardtDbContext + { + DynamicShardOption DynamicShardOptionImpl { get; } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/DbsetProperty.cs b/LingYanAspCoreFramework/DynamicShard/Models/DbsetProperty.cs new file mode 100644 index 0000000000000000000000000000000000000000..03c5761ce20b6e54b95e61353d34a73e4d9100c3 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/DbsetProperty.cs @@ -0,0 +1,18 @@ +namespace LingYanAspCoreFramework.DynamicShard.Models +{ + /// + /// 表示数据库集属性的类 + /// + public class DbsetProperty + { + /// + /// 属性的类型 + /// + public Type PropertyType { get; set; } + + /// + /// 属性的名称 + /// + public string PropertyName { get; set; } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/DynamicGetMemberBinder.cs b/LingYanAspCoreFramework/DynamicShard/Models/DynamicGetMemberBinder.cs new file mode 100644 index 0000000000000000000000000000000000000000..1985c21111cac652db988170c0d9bae11654f680 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/DynamicGetMemberBinder.cs @@ -0,0 +1,29 @@ +锘縰sing System.Dynamic; +using System.Linq.Expressions; + +namespace LingYanAspCoreFramework.DynamicShard.Models +{ + public class DynamicGetMemberBinder : GetMemberBinder + { + public DynamicGetMemberBinder(string name) : base(name, false) + { + } + + public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion) + { + var expando = (ExpandoObject)target.Value; + var dict = (IDictionary)expando; + if (dict.TryGetValue(Name, out var result)) + { + return new DynamicMetaObject( + Expression.Constant(result), + BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType) + ); + } + return new DynamicMetaObject( + Expression.Constant(null), + BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType) + ); + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/DynamicSetMemberBinder.cs b/LingYanAspCoreFramework/DynamicShard/Models/DynamicSetMemberBinder.cs new file mode 100644 index 0000000000000000000000000000000000000000..d82fd9b50233f9c50a4f35629949cc9447c41486 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/DynamicSetMemberBinder.cs @@ -0,0 +1,24 @@ +锘縰sing System.Dynamic; +using System.Linq.Expressions; + +namespace LingYanAspCoreFramework.DynamicShard.Models +{ + public class DynamicSetMemberBinder : SetMemberBinder + { + public DynamicSetMemberBinder(string name) : base(name, false) + { + + } + + public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion) + { + var expando = (ExpandoObject)target.Value; + var dict = (IDictionary)expando; + dict[Name] = value.Value; + return new DynamicMetaObject( + Expression.Constant(value.Value), + BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType) + ); + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardInfo.cs b/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardInfo.cs new file mode 100644 index 0000000000000000000000000000000000000000..ebe567fec35a648a1b7ed5963fa06bad39237b42 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardInfo.cs @@ -0,0 +1,15 @@ +锘縰sing System.Dynamic; + +namespace LingYanAspCoreFramework.DynamicShard.Models +{ + /// + /// 鍒嗛厤淇℃伅 + /// + public class DynamicShardInfo : DynamicObject + { + public string ShardingDataBase { get; set; } + public string ShardingSchema { get; set; } + public string ShardingTable { get; set; } + public Dictionary RequestOtherHeader { get; set; } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardOption.cs b/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardOption.cs new file mode 100644 index 0000000000000000000000000000000000000000..30e332dc47e94f5cca0156464c9aa01efbba2fc5 --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardOption.cs @@ -0,0 +1,61 @@ +using LingYanAspCoreFramework.DynamicShard.Models.Enum; +using LingYanAspCoreFramework.Models; + +namespace LingYanAspCoreFramework.DynamicShard.Models +{ + /// + /// 租户的数据库连接策略和表结构规则 + /// + public class DynamicShardOption + { + /// + /// 数据库类型 + /// + public ConnectionType ConnectionType { get; set; } + /// + /// 数据库连接字符串 + /// + + public string ConnectionName { get; set; } + /// + /// 模式名称 + /// + public string SchemaPostfix { get; set; } + /// + /// 表名生成委托 + /// + public string TablePrefix { get; set; } + /// + /// 迁移模板命名空间 + /// + public string MigrationNameSpace { get; set; } + + public void PostSetting() + { + switch (ConnectionType) + { + case ConnectionType.Mysql: + MigrationNameSpace = "$DynamicShard.Migrations.MySql"; + if (!string.IsNullOrEmpty(SchemaPostfix)) + { + throw new CommonException(new ResponceBody(63000, $"{ConnectionType.ToString()}数据库不支持模式分片")); + } + break; + case ConnectionType.SqlServer: + MigrationNameSpace = "$DynamicShard.Migrations.SqlServer"; + break; + case ConnectionType.PostgreSql: + MigrationNameSpace = "$DynamicShard.Migrations.PostgreSql"; + break; + } + if (!string.IsNullOrEmpty(TablePrefix)) + { + TablePrefix += "_"; + } + if (!string.IsNullOrEmpty(SchemaPostfix)) + { + SchemaPostfix = "." + SchemaPostfix; + } + } + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardSettingsT.cs b/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardSettingsT.cs new file mode 100644 index 0000000000000000000000000000000000000000..940209dd5e8a9607149fe0c0608bf02002c0e9eb --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/DynamicShardSettingsT.cs @@ -0,0 +1,32 @@ +锘縰sing LingYanAspCoreFramework.DynamicShard.Models.Enum; +using Microsoft.EntityFrameworkCore; + +namespace LingYanAspCoreFramework.DynamicShard.Models +{ + /// + /// 澶氱鎴锋暟鎹簱涓婁笅鏂囩殑鍔ㄦ侀厤缃 + /// + /// 鏁版嵁搴撲笂涓嬫枃绫诲瀷 + public class DynamicShardSettings + where TDbContext : DbContext + { + /// + /// 鏁版嵁搴撹繛鎺ュ瓧绗︿覆鐢熸垚鍑芥暟 + /// + public Func> ConnectionNameFunc { get; set; } + + /// + /// 妯″紡鐢熸垚鍑芥暟 + /// + public Func SchemaNameFunc { get; set; } + + /// + /// 琛ㄥ悕鐢熸垚鍑芥暟 + /// + public Func TablePrefixFunc { get; set; } + /// + /// 鏁版嵁搴撲笂涓嬫枃閫夐」閰嶇疆 + /// + internal Action DbContextOptionDelegate; + } +} diff --git a/LingYanAspCoreFramework/DynamicShard/Models/Enum/ConnectionType.cs b/LingYanAspCoreFramework/DynamicShard/Models/Enum/ConnectionType.cs new file mode 100644 index 0000000000000000000000000000000000000000..8cae903ff5a05291948882ebce41ee8cb646d79b --- /dev/null +++ b/LingYanAspCoreFramework/DynamicShard/Models/Enum/ConnectionType.cs @@ -0,0 +1,10 @@ +namespace LingYanAspCoreFramework.DynamicShard.Models.Enum +{ + public enum ConnectionType + { + None = 0, + Mysql = 1, + SqlServer = 2, + PostgreSql = 3, + } +} diff --git a/LingYanAspCoreFramework/Envs/Configs/AppSetting.json b/LingYanAspCoreFramework/Envs/Configs/AppSetting.json index a37e63803d47428b2cf2b83da5660e3e71ec6b95..852722d20d2d8b51d612f020ded97f3d9593da40 100644 --- a/LingYanAspCoreFramework/Envs/Configs/AppSetting.json +++ b/LingYanAspCoreFramework/Envs/Configs/AppSetting.json @@ -19,7 +19,7 @@ "RedisCofigModel": { "Pattern": "Single", // 鍗曟満妯″紡 - "Single": "192.168.148.131:6379,defaultDatabase=0,password=12345678,prefix=ling", + "Single": "192.168.188.128:6379,defaultDatabase=0,password=,prefix=ling", //鍝ㄥ叺妯″紡 "SentinelModel": { "Master": "longyumaster,password=,prefix=", diff --git a/LingYanAspCoreFramework/Envs/Configs/StatusCode.json b/LingYanAspCoreFramework/Envs/Configs/StatusCode.json index 2e068e117c464e6d5395c54d604fdd636f29eda8..31ccab2895caafc354446efc12ed82e3cbb7c9dd 100644 --- a/LingYanAspCoreFramework/Envs/Configs/StatusCode.json +++ b/LingYanAspCoreFramework/Envs/Configs/StatusCode.json @@ -1,43 +1,18 @@ { - "20000": "璇锋眰鎻愮ず:鎿嶄綔鎴愬姛", + "20000": "璇锋眰鎴愬姛:瀹岀編閫氳繃", - "30000": "璧勬簮璋冩暣:閲嶅畾鍚戣祫婧", + "40000": "璇锋眰寮傚父:鏅氶敊璇", + "41000": "璇锋眰寮傚父:閴存潈閿欒", + "42000": "璇锋眰寮傚父:鎺堟潈閿欒", + "43000": "璇锋眰寮傚父:鍙傛暟閿欒", - "40000": "瀹㈡埛绔敊璇:鎿嶄綔澶辫触", - "40001": "瀹㈡埛绔敊璇:Token閴存潈璀﹀憡", - "40002": "瀹㈡埛绔敊璇:瑙掕壊缁勮鍛", - "40003": "瀹㈡埛绔敊璇:璺敱缁勮鍛", - "40004": "瀹㈡埛绔敊璇:妯″瀷鍙傛暟楠岃瘉閿欒", - - "50000": "鏈嶅姟绔敊璇:杩囩▼閿欒,鍐呭淇濆瘑", - "50001": "涓氬姟灞傝鍛:鏃犵鍚堟暟鎹", - "50002": "鏁版嵁搴撳眰閿欒:淇濆瓨澶辫触锛岄泦浣撳洖閫", - "50003": "涓氬姟灞傞敊璇:瑕佹眰鏁版嵁鍞竴鎬у師鍒", - - "60000": "妗嗘灦閿欒:妗嗘灦瑙f瀽鏈嶅姟鏃堕敊璇", - "60001": "妗嗘灦閿欒:妗嗘灦娉ㄥ叆鏈嶅姟鏃堕敊璇", - "60002": "妗嗘灦閿欒:妗嗘灦鍒濆鍖栨湇鍔℃椂閿欒", - "60003": "妗嗘灦閿欒:ffmpeg瑙f瀽鍏冩暟鎹け璐,鏈緭鍑哄疄浣撲俊鎭", - "60004": "妗嗘灦閿欒:ffmpeg瑙f瀽鍏冩暟鎹繃绋嬮敊璇", - "60005": "妗嗘灦閿欒:ffmpeg瑙f瀽鍏冩暟鎹棰戜笉瀛樺湪", - "60006": "妗嗘灦閿欒:ffmpeg瑙f瀽鍏冩暟鎹湭鐢熸垚缂╃暐鍥", - "60007": "妗嗘灦閿欒:ffmpeg鏈惎鍔", - "60008": "妗嗘灦閿欒:ffmpeg鏈粨鏉", - "60009": "妗嗘灦閿欒:鍚敤椤圭洰鏈嬀閫夌敓鎴恱ml鏂囦欢", - "60010": "妗嗘灦閿欒:璇烽厤缃姩鎬佽矾鐢卞墠缂", - "60011": "妗嗘灦閿欒:鍔犲瘑鏂囦欢澶辫触", - "60012": "妗嗘灦閿欒:瑙e瘑鏂囦欢澶辫触", - "60013": "妗嗘灦閿欒:鎺у埗鍣ㄦ湭娣诲姞娉ㄩ噴", - "60014": "妗嗘灦閿欒:璺敱鏈坊鍔犳敞閲", - "60015": "妗嗘灦閿欒:娉ㄩ噴鏂囦欢瑙f瀽澶辫触", - "60016": "妗嗘灦閿欒:鑾峰彇瀹瑰櫒閿欒", - "60017": "妗嗘灦閿欒:閰嶇疆涓叕閽ユ棤鏁", - "60018": "妗嗘灦閿欒:閰嶇疆涓閽ユ棤鏁", - "60020": "妗嗘灦閿欒:鎵嬫満鍙风煭淇¢獙璇佺爜鍙戦佸け璐", - "60021": "妗嗘灦閿欒:DNS-TXT娣诲姞澶辫触", - "60022": "妗嗘灦閿欒:DNS-TXT鍒犻櫎澶辫触", - "60023": "妗嗘灦閿欒:HTTP涓嬭浇涓婁紶绫", - "61000": "妗嗘灦閿欒:HTTP灏佽鍖呭紓甯", - "62000": "妗嗘灦閿欒:寰俊寮鏀惧钩鍙板紓甯" + "60000": "妗嗘灦寮傚父:瀹瑰櫒妯″潡閿欒", + "61000": "妗嗘灦寮傚父:HTTP妯″潡閿欒", + "62000": "妗嗘灦寮傚父:寰俊骞冲彴妯″潡閿欒", + "63000": "妗嗘灦寮傚父:鍒嗗簱鍒嗚〃妯″潡閿欒", + "64000": "妗嗘灦寮傚父:ffmpeg妯″潡閿欒", + "65000": "妗嗘灦寮傚父:闃块噷浜戝钩鍙版ā鍧楅敊璇", + "66000": "妗嗘灦寮傚父:鑵捐浜戝钩鍙版ā鍧楅敊璇", + "67000": "妗嗘灦寮傚父:鍔犲瘑瑙e瘑妯″潡閿欒" } \ No newline at end of file diff --git a/LingYanAspCoreFramework/Events/DispatcherEventSubscription.cs b/LingYanAspCoreFramework/Events/DispatcherEventSubscription.cs index b6d84d7aa3e089d91b6a716e6ba8937c034833b7..310ce4383b1fdb4c016422fac1957a49a84c6a3c 100644 --- a/LingYanAspCoreFramework/Events/DispatcherEventSubscription.cs +++ b/LingYanAspCoreFramework/Events/DispatcherEventSubscription.cs @@ -1,19 +1,19 @@ namespace LingYanAspCoreFramework.Events { /// - /// 扩展 以在特定的 中调用 委托。 + /// 锟斤拷展 锟斤拷锟斤拷锟截讹拷锟斤拷 锟叫碉拷锟斤拷 委锟叫★拷 /// public class DispatcherEventSubscription : EventSubscription { private readonly SynchronizationContext syncContext; /// - /// 创建一个新的 实例。 + /// 锟斤拷锟斤拷一锟斤拷锟铰碉拷 实锟斤拷锟斤拷 /// - ///指向 类型的委托的引用。 - ///用于UI线程调度的同步上下文。 - /// 时抛出。 - /// 的目标不是 类型时抛出。 + ///指锟斤拷 锟斤拷锟酵碉拷委锟叫碉拷锟斤拷锟矫★拷 + ///锟斤拷锟斤拷UI锟竭程碉拷锟饺碉拷同锟斤拷锟斤拷锟斤拷锟侥★拷 + ///锟斤拷 锟斤拷 时锟阶筹拷锟斤拷 + ///锟斤拷 锟斤拷目锟疥不锟斤拷 锟斤拷锟斤拷时锟阶筹拷锟斤拷 public DispatcherEventSubscription(IDelegateReference actionReference, SynchronizationContext context) : base(actionReference) { @@ -21,9 +21,9 @@ namespace LingYanAspCoreFramework.Events } /// - /// 在指定的 中异步调用指定的 。 + /// 锟斤拷指锟斤拷锟斤拷 锟斤拷锟届步锟斤拷锟斤拷指锟斤拷锟斤拷 锟斤拷 /// - /// 要执行的动作。 + /// 要执锟叫的讹拷锟斤拷锟斤拷 public override void InvokeAction(Action action) { syncContext.Post((o) => action(), null); @@ -31,22 +31,22 @@ namespace LingYanAspCoreFramework.Events } /// - /// 扩展 以在特定的 中调用 委托。 + /// 锟斤拷展 锟斤拷锟斤拷锟截讹拷锟斤拷 锟叫碉拷锟斤拷 委锟叫★拷 /// - /// 用于泛型 类型的类型。 + /// 锟斤拷锟节凤拷锟斤拷 锟斤拷 锟斤拷锟酵碉拷锟斤拷锟酵★拷 public class DispatcherEventSubscription : EventSubscription { private readonly SynchronizationContext syncContext; /// - /// 创建一个新的 实例。 + /// 锟斤拷锟斤拷一锟斤拷锟铰碉拷 实锟斤拷锟斤拷 /// - ///指向 类型的委托的引用。 - ///指向 类型的委托的引用。 - ///用于UI线程调度的同步上下文。 - /// 时抛出。 - /// 的目标不是 类型, - ///或 的目标不是 类型时抛出。 + ///指锟斤拷 锟斤拷锟酵碉拷委锟叫碉拷锟斤拷锟矫★拷 + ///指锟斤拷 锟斤拷锟酵碉拷委锟叫碉拷锟斤拷锟矫★拷 + ///锟斤拷锟斤拷UI锟竭程碉拷锟饺碉拷同锟斤拷锟斤拷锟斤拷锟侥★拷 + ///锟斤拷 锟斤拷 时锟阶筹拷锟斤拷 + ///锟斤拷 锟斤拷目锟疥不锟斤拷 锟斤拷锟酵o拷 + ///锟斤拷 锟斤拷目锟疥不锟斤拷 锟斤拷锟斤拷时锟阶筹拷锟斤拷 public DispatcherEventSubscription(IDelegateReference actionReference, IDelegateReference filterReference, SynchronizationContext context) : base(actionReference, filterReference) { @@ -54,10 +54,10 @@ namespace LingYanAspCoreFramework.Events } /// - /// 在指定的 中异步调用指定的 。 + /// 锟斤拷指锟斤拷锟斤拷 锟斤拷锟届步锟斤拷锟斤拷指锟斤拷锟斤拷 锟斤拷 /// - /// 要执行的动作。 - /// 调用时传递给 的负载。 + /// 要执锟叫的讹拷锟斤拷锟斤拷 + /// 锟斤拷锟斤拷时锟斤拷锟捷革拷 锟侥革拷锟截★拷 public override void InvokeAction(Action action, TPayload argument) { syncContext.Post((o) => action((TPayload)o), argument); diff --git a/LingYanAspCoreFramework/Events/IDelegateReference.cs b/LingYanAspCoreFramework/Events/IDelegateReference.cs index 78c3a5559322abf370ac9d354aff3d9041880d3b..9872813beadc9a0b1eb0c75e99c73545141cb865 100644 --- a/LingYanAspCoreFramework/Events/IDelegateReference.cs +++ b/LingYanAspCoreFramework/Events/IDelegateReference.cs @@ -1,14 +1,7 @@ namespace LingYanAspCoreFramework.Events { - /// - /// 表示对 的引用。 - /// public interface IDelegateReference { - /// - /// 获取引用的 对象。 - /// - /// 如果目标有效,则返回一个 实例;否则返回 Delegate Target { get; } } } \ No newline at end of file diff --git a/LingYanAspCoreFramework/Events/IEventAggregator.cs b/LingYanAspCoreFramework/Events/IEventAggregator.cs index 19a373e556926582f7b23a38b4b8073268db1484..b870700271635b56624b3df8f798bf1fbf388562 100644 --- a/LingYanAspCoreFramework/Events/IEventAggregator.cs +++ b/LingYanAspCoreFramework/Events/IEventAggregator.cs @@ -1,18 +1,7 @@ namespace LingYanAspCoreFramework.Events { - /// - /// 定义了一个接口,用于获取事件类型的实例。 - /// public interface IEventAggregator { - /// - /// 获取指定类型的事件实例。 - /// - /// 要获取的事件类型,必须继承自 并提供无参构造函数。 - /// 返回一个类型为 的事件对象实例。 - /// - /// 此方法使用了泛型约束 where TEventType : EventBase, new(),确保传入的类型是 的子类,并且该类有一个无参构造函数。 - /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")] TEventType GetEvent() where TEventType : EventBase, new(); } diff --git a/LingYanAspCoreFramework/Extensions/DeEncryptExtension.cs b/LingYanAspCoreFramework/Extensions/DeEncryptExtension.cs index 0859505369cded3156cd66d6ef8390c4c80eab0b..ea4a823bf3d0a933914e1361057331d1d9c7d5a8 100644 --- a/LingYanAspCoreFramework/Extensions/DeEncryptExtension.cs +++ b/LingYanAspCoreFramework/Extensions/DeEncryptExtension.cs @@ -116,10 +116,10 @@ namespace LingYanAspCoreFramework.Extensions } } } - catch + catch(Exception ex) { File.Delete(path + ".temp"); - throw new CommonException(new ResponceBody(60011)); + throw new CommonException(new ResponceBody(67000, ex.Message)); } } @@ -167,10 +167,10 @@ namespace LingYanAspCoreFramework.Extensions } } } - catch + catch(Exception ex) { File.Delete(path + ".temp"); - throw new CommonException(new ResponceBody(60012)); + throw new CommonException(new ResponceBody(60000,ex.Message)); } } diff --git a/LingYanAspCoreFramework/Extensions/FFMpegExtension.cs b/LingYanAspCoreFramework/Extensions/FFMpegExtension.cs index 11bd8472361a2b1b8fb398f7872beedbf08c3859..163f8669c2344b0fba78c3560e3985d4f5460372 100644 --- a/LingYanAspCoreFramework/Extensions/FFMpegExtension.cs +++ b/LingYanAspCoreFramework/Extensions/FFMpegExtension.cs @@ -38,13 +38,13 @@ namespace LingYanAspCoreFramework.Extensions Thread.Sleep(100); if (!started) { - throw new CommonException(new ResponceBody(60007)); + throw new CommonException(new ResponceBody(64000,"ffmpeg鍚姩澶辫触")); } // 绛夊緟杩涚▼閫鍑 bool exited = ffprobeProcess.WaitForExit(1000); // 澧炲姞绛夊緟鏃堕棿鍒10000姣锛10绉掞級 if (!exited) { - throw new CommonException(new ResponceBody(60008)); + throw new CommonException(new ResponceBody(64000,"ffmpeg閫鍑哄け璐")); } // 璇诲彇ffprobe鐨勬爣鍑嗚緭鍑烘祦 StreamReader outputReader = new StreamReader(ffprobeProcess.StandardOutput.BaseStream, Encoding.UTF8); @@ -59,7 +59,7 @@ namespace LingYanAspCoreFramework.Extensions var videoInfo = Newtonsoft.Json.JsonConvert.DeserializeObject(successOutput); if (videoInfo == null) { - throw new CommonException(new ResponceBody(60003)); + throw new CommonException(new ResponceBody(64000,"ffmpeg杈撳嚭json涓虹┖")); } return new ResponceBody(code: 20000, data: videoInfo); } @@ -104,7 +104,7 @@ namespace LingYanAspCoreFramework.Extensions // 妫鏌ヨ棰戞枃浠舵槸鍚﹀瓨鍦 if (!File.Exists(videoFilePath)) { - throw new CommonException(new ResponceBody(60005)); + throw new CommonException(new ResponceBody(64000,"瑙嗛涓嶅瓨鍦")); } using (var process = new Process()) { @@ -127,13 +127,13 @@ namespace LingYanAspCoreFramework.Extensions Thread.Sleep(100); if (!started) { - throw new CommonException(new ResponceBody(60007)); + throw new CommonException(new ResponceBody(64000,"鍚姩澶辫触")); } // 绛夊緟杩涚▼閫鍑 bool exited = process.WaitForExit(1000); // 澧炲姞绛夊緟鏃堕棿鍒10000姣锛10绉掞級 if (!exited) { - throw new CommonException(new ResponceBody(60008)); + throw new CommonException(new ResponceBody(64000,"閫鍑哄け璐")); } //璇诲彇ffprobe鐨勬爣鍑嗚緭鍑烘祦 StreamReader outputReader = new StreamReader(process.StandardOutput.BaseStream, Encoding.UTF8); @@ -147,7 +147,7 @@ namespace LingYanAspCoreFramework.Extensions // 妫鏌ヨ棰戞枃浠舵槸鍚﹀瓨鍦 if (!File.Exists(thumbPath)) { - throw new CommonException(new ResponceBody(60006)); + throw new CommonException(new ResponceBody(64000,"瑙嗛涓嶅瓨鍦")); } return new ResponceBody(data: thumbPath); } diff --git a/LingYanAspCoreFramework/Extensions/GeneralExtension.cs b/LingYanAspCoreFramework/Extensions/GeneralExtension.cs index 2885b49031d30d6d93def8abf81a6c7b00a8cac2..cd6b4a5009866b00ca390380a14aaafe00d68f3f 100644 --- a/LingYanAspCoreFramework/Extensions/GeneralExtension.cs +++ b/LingYanAspCoreFramework/Extensions/GeneralExtension.cs @@ -1,18 +1,15 @@ 锘縰sing LingYanAspCoreFramework.BaseRoots; using LingYanAspCoreFramework.Helpers; using LingYanAspCoreFramework.Models; -using LingYanAspCoreFramework.MultiTenants; using LingYanAspCoreFramework.SampleRoots; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc.ActionConstraints; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Infrastructure; -using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.IdentityModel.Tokens; -using ShardingCore.Extensions; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text; using System.Xml; @@ -21,6 +18,24 @@ namespace LingYanAspCoreFramework.Extensions { public static class GeneralExtension { + public static IEnumerable GetConstructibleTypes(this Assembly assembly) + { + return from t in assembly.GetLoadableDefinedTypes() + where (object)t != null && !t.IsAbstract && !t.IsGenericTypeDefinition + select t; + } + + public static IEnumerable GetLoadableDefinedTypes(this Assembly assembly) + { + try + { + return assembly.DefinedTypes; + } + catch (ReflectionTypeLoadException ex) + { + return ex.Types.Where((Type t) => t != null).Select(IntrospectionExtensions.GetTypeInfo); + } + } /// /// 鍙嶅皠鑾峰彇灞炴х殑鍊 /// @@ -30,11 +45,29 @@ namespace LingYanAspCoreFramework.Extensions /// public static T GetPropertyValue(this object obj, string propertyName) { - PropertyInfo propertyType = obj.GetType().GetProperty(propertyName); - var peropertyValue = propertyType.GetValue(obj); - return (T)peropertyValue; + PropertyInfo propertyInfo = obj.GetType().GetProperty(propertyName); + if (propertyInfo != null) + { + var propertyValue = propertyInfo.GetValue(obj); + if (propertyValue != null) + { + return (T)propertyValue; + } + } + return default(T); + } + /// + ///鍙嶅皠璁剧疆灞炴х殑鍊 + /// + /// + /// + /// + /// + public static void SetPropertyValue(this object obj, string propertyName, T value) + { + PropertyInfo propertyInfo = obj.GetType().GetProperty(propertyName); + propertyInfo.SetValue(obj, value); } - /// /// 鍒ゆ柇娉涘瀷鏂规硶 /// @@ -129,7 +162,7 @@ namespace LingYanAspCoreFramework.Extensions { return (IServiceCollection)property.GetValue(builder); } - throw new CommonException(new ResponceBody(60016, attach: "builder鏈壘鍒癐ServiceCollection绫诲瀷")); + throw new CommonException(new ResponceBody(60000, attach: "builder鏈壘鍒癐ServiceCollection绫诲瀷")); } /// @@ -195,7 +228,7 @@ namespace LingYanAspCoreFramework.Extensions { OnChallenge = context => { - throw new CommonException(new ResponceBody(40001, "閴存潈涓嶉氳繃")); + throw new CommonException(new ResponceBody(41000, "閴存潈澶辫触")); } }; }); @@ -242,7 +275,7 @@ namespace LingYanAspCoreFramework.Extensions XmlNodeList xmlItems = ProjectHelper.GetRelevantXmlNodeList(projectXmlDocuments); if (xmlItems == null) { - throw new CommonException(new ResponceBody(60015)); + throw new CommonException(new ResponceBody(60000,"xml鏂囦欢娉ㄨВ淇℃伅鑾峰彇閿欒")); } // 寰幆鎵鏈夋帴鍙 foreach (var node in actionDescs) @@ -262,7 +295,7 @@ namespace LingYanAspCoreFramework.Extensions } else { - throw new CommonException(new ResponceBody(60013, node.ControllerFullName)); + throw new CommonException(new ResponceBody(60000, node.ControllerFullName+"鎺у埗鍣ㄦ湭娣诲姞娉ㄨВ")); } XmlNode apiNode = ProjectHelper.FindMatchingXmlNode(xmlItems, node.DisplayFullName); if (apiNode == null) @@ -275,43 +308,12 @@ namespace LingYanAspCoreFramework.Extensions } else { - throw new CommonException(new ResponceBody(60014, node.DisplayFullName)); + throw new CommonException(new ResponceBody(60000,node.DisplayFullName+"鎺ュ彛鏈坊鍔犳敞閲")); } } ProjectHelper.GenerateControllerXml(actionDescs); return actionDescs; } - - /// - ///1銆侀渶瑕佹湁Migration绯荤粺鐨勭鎴风鐞嗘暟鎹簱杩佺Щ - ///2銆侀渶瑕佹湁Migration绯荤粺鐨勭鎴锋ā鐗堟暟鎹簱杩佺Щ - ///3銆佺郴缁熺殑绉熸埛绠$悊鏁版嵁搴撲笂涓嬫枃 - ///4銆佺郴缁熺鎴锋ā鐗堟暟鎹簱涓婁笅鏂 - ///5銆佸鏋滅郴缁熺鎴锋ā鐗堟暟鎹簱鏈夎櫄鎷熻矾鐢憋紝闇瑕佽櫄鎷熷寲 - /// - /// - /// - /// - public static void AddSysTenant(this IServiceProvider provider, object tid, ShardingTenantOptions shardingTenantOptions) - { - var _shardingBuilder = provider.GetService(); - var _tenantManager = provider.GetService(); - //鍒涘缓杩愯鏃 - var shardingRuntimeContext = _shardingBuilder.Build(shardingTenantOptions); - //娣诲姞绉熸埛淇℃伅 - _tenantManager.AddTenantSharding(tid, shardingRuntimeContext); - //鍒涘缓绉熸埛鐜 - using (_tenantManager.CreateScope(tid)) - //寮鍚垎鐗囧畾鏃朵换鍔 - using (var scope = provider.CreateScope()) - { - var runtimeContext = _tenantManager.GetCurrentTenantContext().GetShardingRuntimeContext(); - var tenantDbContext = (DbContext)scope.ServiceProvider.GetService(LingYanRuntimeManager.RuntimeCacheModel.TenantTemplateDbContexts.FirstOrDefault()); - tenantDbContext.Database.Migrate(); - runtimeContext.UseAutoTryCompensateTable(); - } - } - /// /// 浠庢寚瀹氱殑 URI 涓嬭浇鏂囦欢骞舵姤鍛婁笅杞借繘搴 /// @@ -330,7 +332,7 @@ namespace LingYanAspCoreFramework.Extensions long? totalBytes = response.Content.Headers.ContentLength; if (!totalBytes.HasValue) { - throw new CommonException(new ResponceBody(60023, "鏃犳硶鑾峰彇鍐呭闀垮害")); + throw new CommonException(new ResponceBody(61000, "鏃犳硶鑾峰彇鍐呭闀垮害")); } byte[] buffer = new byte[4096]; diff --git a/LingYanAspCoreFramework/Extensions/IocExtension.cs b/LingYanAspCoreFramework/Extensions/IocExtension.cs index 1d228f0a1b6df13707d2d74fbc2dfd12a2535141..e7b0986ad3adc005fe4745499fdd1e5184585721 100644 --- a/LingYanAspCoreFramework/Extensions/IocExtension.cs +++ b/LingYanAspCoreFramework/Extensions/IocExtension.cs @@ -7,7 +7,6 @@ using LingYanAspCoreFramework.Helpers; using LingYanAspCoreFramework.Https; using LingYanAspCoreFramework.Models; using LingYanAspCoreFramework.Models.WeChat; -using LingYanAspCoreFramework.MultiTenants; using LingYanAspCoreFramework.OnlinePays; using LingYanAspCoreFramework.SampleRoots; using LingYanAspCoreFramework.UnitOfWork; @@ -41,7 +40,7 @@ namespace LingYanAspCoreFramework.Extensions foreach (var module in ModuleBaseLoadingList) { //妯″潡鏁翠綋娉ㄥ唽 - LoggerHelper.WarnrningLog($"銆恵module.GetType().Name}妯″潡鍒濆鍖栥"); + LoggerHelper.WarnrningLog($"{module.GetType().Name}妯″潡鍒濆鍖"); //鏂规硶 var method = module.GetType().GetMethod("BInitializationModule"); //鍙傛暟 @@ -58,33 +57,43 @@ namespace LingYanAspCoreFramework.Extensions try { - LoggerHelper.DefaultLog("銆愰厤缃垵濮嬪寲銆..."); + LoggerHelper.DefaultLog("閰嶇疆鍒濆鍖"); LingYanRuntimeManager.Init(); - LoggerHelper.DefaultLog("銆愰厤缃郴缁焌ppsettings.json銆..."); + LoggerHelper.DefaultLog("閰嶇疆绯荤粺appsettings.json"); SampleHelper.SysAppsettings = Hostbuilder.GetPropertyValue("Configuration"); - LoggerHelper.DefaultLog("銆愬綊绾抽」鐩ā鍧椼..."); + LoggerHelper.DefaultLog("褰掔撼椤圭洰妯″潡"); LingYanRuntimeManager.RuntimeCacheModel.GetModules(); - LoggerHelper.DefaultLog("銆愯幏鍙栧鍣ㄣ..."); - var BuilderService = Hostbuilder.GetBuilderServiceCollection(); + LoggerHelper.DefaultLog("鑾峰彇瀹瑰櫒"); + var BuilderService = Hostbuilder.GetBuilderServiceCollection(); - LoggerHelper.DefaultLog("銆愭坊鍔犺法鍩熺瓥鐣ャ..."); - BuilderService.AddCors(c => c.AddPolicy(SampleHelper.CrossPolicy, p => p.WithOrigins(LingYanRuntimeManager.CrossDomains).AllowAnyHeader().AllowAnyMethod().AllowCredentials())); - LoggerHelper.DefaultLog("銆愭坊鍔燗PI绔偣銆..."); + LoggerHelper.DefaultLog("娣诲姞璺ㄥ煙绛栫暐"); + BuilderService.AddCors(c => + c.AddPolicy(SampleHelper.CrossPolicy, p => p.WithOrigins(LingYanRuntimeManager.CrossDomains).AllowAnyHeader().AllowAnyMethod().AllowCredentials())); + LoggerHelper.DefaultLog("娣诲姞API绔偣"); BuilderService.AddEndpointsApiExplorer(); - LoggerHelper.DefaultLog("銆愭坊鍔燬ignalR銆..."); + LoggerHelper.DefaultLog("娣诲姞SignalR"); BuilderService.AddSignalR(); - LoggerHelper.DefaultLog("銆愭坊鍔犳湰鍦癕emoryCache缂撳瓨銆..."); + LoggerHelper.DefaultLog("娣诲姞鏈湴MemoryCache缂撳瓨"); BuilderService.AddSingleton(); - LoggerHelper.DefaultLog("銆愭帶鍒跺櫒娉ㄥ唽鍏ㄥ眬杩囨护鍣+娉ㄥ唽id-JSON杞崲鍣╨ong<==>string銆..."); + LoggerHelper.DefaultLog("鎺у埗鍣ㄦ敞鍐屽叏灞杩囨护鍣+娉ㄥ唽id-JSON杞崲鍣╨ong<==>string"); BuilderService.AddControllers(mvcOption => - { + { LingYanRuntimeManager.RuntimeCacheModel.ModuleFiler.ForEach(filer => { mvcOption.Filters.Add(filer); }); - }).AddNewtonsoftJson(options => { options.SerializerSettings.Converters.Add(new LongToStringConverter()); }); - - LoggerHelper.DefaultLog("銆愭坊鍔犲畨鍏ㄥ畾涔夈..."); + }).AddNewtonsoftJson(options => + { + options.SerializerSettings.Converters.Add(new LongToStringConverter()); + options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + }); + //LoggerHelper.DefaultLog("閰嶇疆鍏ㄥ眬杞崲JsonSerializerSettings"); + //JsonSerializerSettings globalSettings = new JsonSerializerSettings + //{ + // Converters = new List { new LongToStringConverter() }, + // ReferenceLoopHandling = ReferenceLoopHandling.Ignore + //}; + LoggerHelper.DefaultLog("娣诲姞瀹夊叏瀹氫箟"); BuilderService.AddSwaggerGen(swaggerGenOption => { //鎺ュ彛鏂囨。鍒嗙粍 @@ -92,7 +101,7 @@ namespace LingYanAspCoreFramework.Extensions { Title = ProjectHelper.GetProjectName(), Version = "v1", - Description = $"椤圭洰:銆恵ProjectHelper.GetProjectName()}銆戯紝寮鍙戣咃細銆愮伒鐏点", + Description = $"椤圭洰:{ProjectHelper.GetProjectName()}锛屽紑鍙戣咃細鐏电伒", Contact = new OpenApiContact { Name = "ling", @@ -108,7 +117,7 @@ namespace LingYanAspCoreFramework.Extensions //娉ㄨВ閰嶇疆 if (!File.Exists(SampleHelper.BaseDir.GetLocalUrl(ProjectHelper.GetProjectName() + ".xml"))) { - throw new CommonException(new ResponceBody(60009)); + throw new CommonException(new ResponceBody(60000, "椤圭洰鏈嬀閫夌敓鎴愭椂xml娉ㄨВ鏂囦欢杈撳嚭")); } else { @@ -146,51 +155,47 @@ namespace LingYanAspCoreFramework.Extensions } }); }); - LoggerHelper.DefaultLog("銆愭敞鍐屾巿鏉冨鐞嗗櫒銆..."); + LoggerHelper.DefaultLog("娉ㄥ唽鎺堟潈澶勭悊鍣"); BuilderService.RegisterAuthorzeHandler(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.DefaultLog("銆愭敞鍐孞WT閴存潈-鎺堟潈瀵瑰簲绛栫暐銆..."); + LoggerHelper.DefaultLog("娉ㄥ唽JWT閴存潈-鎺堟潈瀵瑰簲绛栫暐"); BuilderService.RegisterAuthenticationAndAuthorization(SampleHelper.BearerScheme, SampleHelper.EmpowerPolicy, LingYanRuntimeManager.JwtModel, () => new BaseAuthorizationRequirement(BuilderService.BuildServiceProvider().CreateScope())); - LoggerHelper.DefaultLog("銆怘ttpContext涓婁笅鏂囩殑璁块棶銆..."); - BuilderService.AddHttpContextAccessor(); - LoggerHelper.DefaultLog("銆愬鍣ㄦ敞鍐屽畼鏂归氱敤鏈嶅姟銆..."); + LoggerHelper.DefaultLog("HttpContext涓婁笅鏂囩殑璁块棶"); + BuilderService.AddHttpContextAccessor(); + LoggerHelper.DefaultLog("瀹瑰櫒娉ㄥ唽瀹樻柟閫氱敤鏈嶅姟"); if (Hostbuilder is WebApplicationBuilder web) { - LoggerHelper.DefaultLog("銆愭棩蹇楁竻闄よ嚜甯﹀苟娣诲姞Nlog鏃ュ織閰嶇疆銆..."); + LoggerHelper.DefaultLog("鏃ュ織娓呴櫎鑷甫骞舵坊鍔燦log鏃ュ織閰嶇疆"); web.Logging.ClearProviders(); web.Logging.AddNLog(LingYanRuntimeManager.CommonConfigModel.NlogConfig); } - LoggerHelper.DefaultLog("銆愭敞鍐屼粨鍌ㄤ笌宸ヤ綔鍗曞厓銆..."); + LoggerHelper.DefaultLog("娉ㄥ唽浠撳偍涓庡伐浣滃崟鍏"); BuilderService.RegisterRepository(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.DefaultLog("銆愭敞鍐岄鍩烳anager銆..."); + LoggerHelper.DefaultLog("娉ㄥ唽棰嗗煙Manager"); BuilderService.RegisterManager(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.DefaultLog("銆愭敞鍐屾湇鍔Service銆..."); - BuilderService.RegisterTService(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.DefaultLog("銆愭敞鍐屽疄渚嬨..."); + LoggerHelper.DefaultLog("娉ㄥ唽鏈嶅姟TService"); + BuilderService.RegisterTService(LingYanRuntimeManager.RuntimeCacheModel); + LoggerHelper.DefaultLog("娉ㄥ唽瀹炰緥"); BuilderService.RegisterTInstance(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.DefaultLog("銆愭敞鍐屾暟鎹簱涓婁笅鏂囥..."); + LoggerHelper.DefaultLog("娉ㄥ唽鏁版嵁搴撲笂涓嬫枃"); BuilderService.RegisterDbContext(LingYanRuntimeManager.RuntimeCacheModel); - - LoggerHelper.DefaultLog("銆愭敞鍐孯edis銆..."); + + LoggerHelper.DefaultLog("娉ㄥ唽Redis"); BuilderService.RegisterRedis(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.DefaultLog("銆愭敞鍐屽姩鎬佽矾鐢便..."); + LoggerHelper.DefaultLog("娉ㄥ唽鍔ㄦ佽矾鐢"); BuilderService.RegisterDynamicWebApi(); - LoggerHelper.DefaultLog("銆愭敞鍐屽绉熸埛鏈嶅姟銆..."); - BuilderService.RegisterTenantService(); - LoggerHelper.DefaultLog("銆愭敞鍐屽绉熸埛妯$増鏁版嵁涓婁笅鏂囥..."); - BuilderService.RegisterTenantTemplateDbContext(LingYanRuntimeManager.RuntimeCacheModel); - - LoggerHelper.DefaultLog("銆愭敞鍐孒ttpClient銆..."); + + LoggerHelper.DefaultLog("娉ㄥ唽HttpClient"); BuilderService.AddHttpClient(); - LoggerHelper.DefaultLog("銆愭敞鍐孡ingYanHttpClient銆..."); - BuilderService.AddSingleton(); + LoggerHelper.DefaultLog("娉ㄥ唽LingYanHttpClient"); + BuilderService.AddSingleton(); - LoggerHelper.DefaultLog("銆愭敞鍐屾敮浠樺疂鍖呫..."); + LoggerHelper.DefaultLog("娉ㄥ唽鏀粯瀹濆寘"); BuilderService.AddAlipay(); - LoggerHelper.DefaultLog("銆愭敞鍐屽井淇℃敮浠樺寘銆..."); - BuilderService.AddWeChatPay(); + LoggerHelper.DefaultLog("娉ㄥ唽寰俊鏀粯鍖"); + BuilderService.AddWeChatPay(); - LoggerHelper.DefaultLog("銆愰厤缃枃浠舵墿灞曠被鍨嬨..."); + LoggerHelper.DefaultLog("閰嶇疆鏂囦欢鎵╁睍绫诲瀷"); BuilderService.Configure(option => { foreach (var item in LingYanRuntimeManager.FileContentTypeConfig) @@ -198,7 +203,7 @@ namespace LingYanAspCoreFramework.Extensions option.Mappings[item.Key] = item.Value; } }); - LoggerHelper.DefaultLog("銆愰厤缃ā鍨嬪弬鏁伴獙璇併..."); + LoggerHelper.DefaultLog("閰嶇疆妯″瀷鍙傛暟楠岃瘉"); BuilderService.Configure(options => { options.InvalidModelStateResponseFactory = actionContext => @@ -209,39 +214,32 @@ namespace LingYanAspCoreFramework.Extensions .Select(e => e.ErrorMessage) .ToList(); var errorMessage = string.Join("|", errors); - throw new CommonException(new ResponceBody(40004, errorMessage)); + throw new CommonException(new ResponceBody(43000, errorMessage)); }; }); - LoggerHelper.DefaultLog("銆愰厤缃〃鍗曘..."); + LoggerHelper.DefaultLog("閰嶇疆琛ㄥ崟"); BuilderService.ConfigureFormSize(); - LoggerHelper.DefaultLog("銆愰厤缃敮浠樺疂銆..."); + LoggerHelper.DefaultLog("閰嶇疆鏀粯瀹"); BuilderService.Configure(SampleHelper.LingAppsettings.GetSection("Alipay")); - LoggerHelper.DefaultLog("銆愰厤缃井淇℃敮浠樸..."); + LoggerHelper.DefaultLog("閰嶇疆寰俊鏀粯"); BuilderService.Configure(SampleHelper.LingAppsettings.GetSection("WeChatPay")); - LoggerHelper.DefaultLog("銆愰厤缃井淇″紑鏀惧钩鍙般..."); + LoggerHelper.DefaultLog("閰嶇疆寰俊寮鏀惧钩鍙"); BuilderService.Configure(SampleHelper.LingAppsettings.GetSection("WeChatDevOption")); - LoggerHelper.DefaultLog("銆愭敞鍐屽垎椤垫暟缁勩..."); + LoggerHelper.DefaultLog("娉ㄥ唽鍒嗛〉鏁扮粍"); BuilderService.AddTransient(typeof(IPagedList<>), typeof(PagedList<>)); - LoggerHelper.DefaultLog("銆愭敞鍐屾湰鍦颁簨浠舵荤嚎銆..."); + LoggerHelper.DefaultLog("娉ㄥ唽鏈湴浜嬩欢鎬荤嚎"); BuilderService.AddSingleton(); - LoggerHelper.DefaultLog("銆愭敞鍐屾敮浠樻柟娉曘..."); + LoggerHelper.DefaultLog("娉ㄥ唽鏀粯鏂规硶"); BuilderService.AddSingleton(); - LoggerHelper.DefaultLog("銆愭敞鍐屽井淇″紑鏀惧钩鍙版湇鍔°..."); + LoggerHelper.DefaultLog("娉ㄥ唽寰俊寮鏀惧钩鍙版湇鍔"); BuilderService.AddSingleton(); - - LoggerHelper.DefaultLog("銆愰厤缃叏灞杞崲JsonSerializerSettings銆..."); - JsonSerializerSettings globalSettings = new JsonSerializerSettings - { - Converters = new List { new LongToStringConverter() }, - ReferenceLoopHandling = ReferenceLoopHandling.Ignore - }; - LoggerHelper.DefaultLog("銆愭敞鍐岄」鐩ā鍧椼..."); + LoggerHelper.DefaultLog("娉ㄥ唽椤圭洰妯″潡"); Hostbuilder.RegisterModule(LingYanRuntimeManager.RuntimeCacheModel); } catch (Exception ex) { - throw new CommonException(new ResponceBody(60001), ex); + throw new CommonException(new ResponceBody(60000, ex.Message), ex); } } @@ -254,16 +252,16 @@ namespace LingYanAspCoreFramework.Extensions { var hostService = app.GetBuilderServiceProvider(); var contentTypeProvider = hostService.GetService>()?.Value; - LoggerHelper.WarnrningLog($"銆愬叏灞鍒濆鍖栧紑濮嬨..."); + LoggerHelper.WarnrningLog($"鍏ㄥ眬鍒濆鍖栧紑濮"); if (app is WebApplication web) { - LoggerHelper.WarnrningLog($"銆愬惎鐢⊿wagger涓棿浠跺拰鍙鍖栫晫闈€..."); + LoggerHelper.WarnrningLog($"鍚敤Swagger涓棿浠跺拰鍙鍖栫晫闈"); if (web.Environment.IsDevelopment() || LingYanRuntimeManager.ShowSwaggerUI) { web.UseSwagger(); web.UseSwaggerUI(); } - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄥ紑鍙戠幆澧冨紓甯搁〉闈€..."); + LoggerHelper.WarnrningLog($"鍚敤寮鍙戠幆澧冨紓甯搁〉闈"); if (web.Environment.IsDevelopment()) { web.UseDeveloperExceptionPage(); @@ -273,32 +271,28 @@ namespace LingYanAspCoreFramework.Extensions web.UseExceptionHandler("/Error"); web.UseHsts(); } - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄥ紓甯哥粺涓澶勭悊涓棿浠躲..."); + LoggerHelper.WarnrningLog($"鍚敤寮傚父缁熶竴澶勭悊涓棿浠"); web.UseMiddleware(); - LoggerHelper.WarnrningLog($"銆愬惎鐢℉TTPS閲嶅畾鍚戜腑闂翠欢銆..."); + LoggerHelper.WarnrningLog($"鍚敤HTTPS閲嶅畾鍚戜腑闂翠欢"); web.UseHttpsRedirection(); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄨ矾鐢变腑闂翠欢銆..."); + LoggerHelper.WarnrningLog($"鍚敤璺敱涓棿浠"); web.UseRouting(); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄨ法鍩熺瓥鐣ャ..."); + LoggerHelper.WarnrningLog($"鍚敤璺ㄥ煙绛栫暐"); web.UseCors(SampleHelper.CrossPolicy); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄩ壌鏉冧腑闂翠欢銆..."); + LoggerHelper.WarnrningLog($"鍚敤閴存潈涓棿浠"); web.UseAuthentication(); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄦ巿鏉冧腑闂翠欢銆..."); + LoggerHelper.WarnrningLog($"鍚敤鎺堟潈涓棿浠"); web.UseAuthorization(); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄩ」鐩嚜瀹氫箟鐨勪腑闂翠欢銆..."); + LoggerHelper.WarnrningLog($"鍚敤椤圭洰鑷畾涔夌殑涓棿浠"); foreach (var item in LingYanRuntimeManager.RuntimeCacheModel.ModuleTMiddleware) { web.UseMiddleware(item); } - LoggerHelper.WarnrningLog($"銆愰」鐩悇妯″潡鍒濆鍖栥..."); + LoggerHelper.WarnrningLog($"椤圭洰鍚勬ā鍧楀垵濮嬪寲"); LingYanRuntimeManager.RuntimeCacheModel.ModuleAssemblyBaseLoadingKeyValue.Values.InitModules(app); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄥ绉熸埛涓棿浠躲..."); - web.UseMiddleware(); - LoggerHelper.WarnrningLog($"銆愬绉熸埛閰嶇疆鍒濆鍖栥..."); - hostService.InitTenant(LingYanRuntimeManager.RuntimeCacheModel); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄥ叏灞寮鍚韩浠介獙璇併..."); + LoggerHelper.WarnrningLog($"鍚敤鍏ㄥ眬寮鍚韩浠介獙璇"); web.MapControllers().RequireAuthorization(); - LoggerHelper.WarnrningLog($"銆愬惎鐢ㄩ潤鎬佹枃浠跺す-鑷畾涔変腑闂翠欢浠ョ伒娲荤殑瀹炵幇閴存潈鎺堟潈銆..."); + LoggerHelper.WarnrningLog($"鍚敤闈欐佹枃浠跺す-鑷畾涔変腑闂翠欢浠ョ伒娲荤殑瀹炵幇閴存潈鎺堟潈"); web.UseStaticFiles(new StaticFileOptions { ContentTypeProvider = contentTypeProvider, @@ -311,7 +305,7 @@ namespace LingYanAspCoreFramework.Extensions FileProvider = new PhysicalFileProvider(SampleHelper.BaseDir.GetLocalPath(SampleHelper.UnAuthorDir)), RequestPath = $"/{LingYanRuntimeManager.CommonConfigModel.UnAuthorDir}" }); - LoggerHelper.WarnrningLog($"銆愰厤缃湇鍔″惎鍔ㄧ洃鍚鍙c..."); + LoggerHelper.WarnrningLog($"閰嶇疆鏈嶅姟鍚姩鐩戝惉绔彛"); foreach (var port in LingYanRuntimeManager.ListeningPorts) { web.Urls.Add(port); @@ -320,7 +314,7 @@ namespace LingYanAspCoreFramework.Extensions } catch (Exception ex) { - throw new CommonException(new ResponceBody(60002), ex); + throw new CommonException(new ResponceBody(60000, ex.Message), ex); } } } diff --git a/LingYanAspCoreFramework/Extensions/ProjectGetExtension.cs b/LingYanAspCoreFramework/Extensions/ProjectGetExtension.cs index d4eb1767691d39418d2e6a5d4bc0313b02b0141b..9c5e68e44c4d382bb455a8c1e7919883430650d4 100644 --- a/LingYanAspCoreFramework/Extensions/ProjectGetExtension.cs +++ b/LingYanAspCoreFramework/Extensions/ProjectGetExtension.cs @@ -33,9 +33,7 @@ namespace LingYanAspCoreFramework.Extensions //鑾峰彇涓棿浠 assembly.GetMiddleware(lYBuilderRuntimeModel); //鑾峰彇鏁版嵁搴撳疄浣 - assembly.GetBaseEntitys(lYBuilderRuntimeModel); - //鑾峰緱澶氱鎴峰熀绫诲疄鐜 - assembly.GetTenantBaseEntitys(lYBuilderRuntimeModel); + assembly.GetBaseEntitys(lYBuilderRuntimeModel); //鑾峰緱DbContext assembly.GetDbContexts(lYBuilderRuntimeModel); //鑾峰緱Manager @@ -93,27 +91,7 @@ namespace LingYanAspCoreFramework.Extensions { lYBuilderRuntimeModel.ModuleTMiddleware.AddRange(moduleEntity); } - } - /// - /// 鑾峰彇澶氱鎴峰疄浣 - /// - /// - internal static void GetTenantBaseEntitys(this Assembly assembly, RuntimeCacheModel lYBuilderRuntimeModel) - { - var moduleEntity = assembly.GetTypes() - .Where(x => x.BaseType != null && x.BaseType.IsGenericType && - ((x.BaseType.GetGenericTypeDefinition() == typeof(BaseSysOwner<>) || - x.BaseType.GetGenericTypeDefinition() == typeof(BaseSysOwnerTenantConfig<>)) && - x.BaseType.GetGenericArguments().Length > 0 && - !assembly.GetTypes().Any(z => z.BaseType == x))).ToList(); - if (moduleEntity != null && moduleEntity.Count > 0) - { - moduleEntity.ForEach(f => - { - lYBuilderRuntimeModel.ModuleTenantBaseEntitys.TryAdd(f.BaseType.Name.Replace("`1", ""), f); - }); - } - } + } /// /// 鑾峰彇鍩虹瀹炰綋 /// @@ -123,8 +101,7 @@ namespace LingYanAspCoreFramework.Extensions { var moduleEntitys = assembly.GetTypes() .Where(x => x.BaseType != null && !x.BaseType.IsGenericType && - (x.BaseType == typeof(BaseUser) || x.BaseType == typeof(BaseRole) || x.BaseType == typeof(BaseRoute) || - x.BaseType == typeof(BaseUserRoleGroup) || x.BaseType == typeof(BaseRoleRouteGroup)) + (x.BaseType == typeof(BaseEntity)) && !assembly.GetTypes().Any(z => z.BaseType == x)).ToList(); foreach (var entity in moduleEntitys) { @@ -147,24 +124,7 @@ namespace LingYanAspCoreFramework.Extensions { moduleDbContext.ForEach(dbcontext => { - var longyudb = dbcontext.GetCustomAttribute(); - var value = longyudb.GetPropertyValue("DbContextType"); - if (value != DbContextType.TenantTemplateDbContext) - { - lYBuilderRuntimeModel.ModuleDbContextList.TryAdd(dbcontext, dbcontext.GetCustomAttribute().DbContextType); - } - else if (value == DbContextType.TenantTemplateDbContext) - { - lYBuilderRuntimeModel.TenantTemplateDbContexts.Add(dbcontext); - lYBuilderRuntimeModel.VirtualTableList.TryAdd(ShardingKeyType.Mod, longyudb.GetPropertyValue("ShardingTable").Where(w => - w.BaseType != null && w.BaseType.IsGenericType && - w.BaseType.GetGenericTypeDefinition().Name == "AbstractSimpleShardingModKeyIntVirtualTableRoute`1" && - w.BaseType.GetGenericArguments().Length > 0).ToList()); - lYBuilderRuntimeModel.VirtualTableList.TryAdd(ShardingKeyType.Time, longyudb.GetPropertyValue("ShardingTable").Where(w => - w.BaseType != null && w.BaseType.IsGenericType && - w.BaseType.GetGenericTypeDefinition().Name != "AbstractSimpleShardingModKeyIntVirtualTableRoute`1" && - w.BaseType.GetGenericArguments().Length > 0).ToList()); - } + lYBuilderRuntimeModel.ModuleDbContextList.Add(dbcontext); }); } } diff --git a/LingYanAspCoreFramework/Extensions/ProjectRegisterExtension.cs b/LingYanAspCoreFramework/Extensions/ProjectRegisterExtension.cs index ffec1a044dda964c0225fcd06f17044779545b49..be361aea09522b91c60d68c912d864c3aa9d3a69 100644 --- a/LingYanAspCoreFramework/Extensions/ProjectRegisterExtension.cs +++ b/LingYanAspCoreFramework/Extensions/ProjectRegisterExtension.cs @@ -3,7 +3,6 @@ using LingYanAspCoreFramework.Attributes; using LingYanAspCoreFramework.DynamicApis; using LingYanAspCoreFramework.Helpers; using LingYanAspCoreFramework.Models; -using LingYanAspCoreFramework.MultiTenants; using LingYanAspCoreFramework.SampleRoots; using LingYanAspCoreFramework.UnitOfWork; using Microsoft.AspNetCore.Authorization; @@ -12,10 +11,7 @@ using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -using ShardingCore; -using ShardingCore.Core.RuntimeContexts; using System.Reflection; -using Yitter.IdGenerator; namespace LingYanAspCoreFramework.Extensions { @@ -48,7 +44,7 @@ namespace LingYanAspCoreFramework.Extensions /// internal static void RegisterRepository(this IServiceCollection BuilderService, RuntimeCacheModel lYBuilderRuntimeModel) { - foreach (var dbcontext in lYBuilderRuntimeModel.ModuleDbContextList.Keys) + foreach (var dbcontext in lYBuilderRuntimeModel.ModuleDbContextList) { var dbsetGener = typeof(DbSet<>); var entitys = dbcontext.GetProperties().Where(w => w.PropertyType.IsGenericType && w.PropertyType.GetGenericTypeDefinition() == dbsetGener) @@ -127,7 +123,7 @@ namespace LingYanAspCoreFramework.Extensions /// internal static void RegisterDbContext(this IServiceCollection BuilderService, RuntimeCacheModel lYBuilderRuntimeModel) { - foreach (var dbContextType in lYBuilderRuntimeModel.ModuleDbContextList.Keys) + foreach (var dbContextType in lYBuilderRuntimeModel.ModuleDbContextList) { var attribute = dbContextType.GetCustomAttribute(); if (attribute != null && !string.IsNullOrEmpty(attribute.ConnectionString)) @@ -178,16 +174,12 @@ namespace LingYanAspCoreFramework.Extensions backBody = null; break; } - if (backBody != null && backBody.Nodes.Count > 0 && backBody.Nodes.Any(a => a.Value.IsAvailable)) + if (backBody?.Nodes.Count > 0 && backBody.Nodes.Any(a => a.Value.IsAvailable)) { LoggerHelper.DefaultLog("銆怰edis娉ㄥ唽鎴愬姛銆..."); RedisHelper.Initialization(backBody); } - else - { - backBody.Dispose(); - LoggerHelper.ErrorLog("銆怰edis鍙栨秷娉ㄥ唽銆..."); - } + LoggerHelper.DefaultLog("銆怰edis鍙栨秷娉ㄥ唽銆..."); } /// @@ -199,7 +191,7 @@ namespace LingYanAspCoreFramework.Extensions BuilderService.AddControllers(options => { //璺敱瑙勫垯 - options.UseCentralRouteJsonConfig(SampleHelper.LingAppsettings); + options.UseCentralRouteJsonConfig(); }).ConfigureApplicationPartManager(t => { //璺敱鎵皠 @@ -231,49 +223,5 @@ namespace LingYanAspCoreFramework.Extensions }); } - /// - /// 娉ㄥ唽澶氱鎴锋ā鐗堟暟鎹笂涓嬫枃 - /// - /// - internal static void RegisterTenantTemplateDbContext(this IServiceCollection BuilderService, RuntimeCacheModel lYBuilderRuntimeModel) - { - //Add-Migration InitialCreate -Context TenantDbContext -OutputDir Migrations\SqlServer -Args "--provider SqlServer" - //Add-Migration InitialCreate -Context TenantDbContext -OutputDir Migrations\MySql -Args "--provider MySql" - //鍙嶅皠鑾峰彇娉ㄥ唽鏁版嵁搴撲笂涓嬫枃鎵╁睍 - var addDbContextMethod = typeof(EntityFrameworkServiceCollectionExtensions).GetMethods() - .Where(m => m.Name == "AddDbContext" && m.GetParameters()[1].ParameterType == typeof(Action)) - .FirstOrDefault(); - //鍙嶅皠鑾峰彇鍒濆鍖栧绉熸埛鎵╁睍 - var useDefaultShardingMethod = typeof(ShardingCoreExtension).GetMethods() - .Where(m => m.Name == "UseDefaultSharding" && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == typeof(DbContextOptionsBuilder) - && m.GetParameters()[1].ParameterType == typeof(IShardingRuntimeContext)).FirstOrDefault(); - //娉ㄥ唽鏁版嵁搴撲笂涓嬫枃鐨勫鎵樸佸鏋滄湁涓婁笅鏂囬偅涔堝垱寤虹鎴穌bcontext鍚﹀垯灏辨槸鍚姩鍛戒护Add-Migration - var optionsAction = new Action((provider, optionBuilder) => - { - var tenantManager = provider.GetService(); - var currentTenantContext = tenantManager.GetCurrentTenantContext(); - if (currentTenantContext != null) - { - var shardingRuntimeContext = currentTenantContext.GetShardingRuntimeContext(); - useDefaultShardingMethod.MakeGenericMethod(lYBuilderRuntimeModel.TenantTemplateDbContexts.FirstOrDefault()).Invoke(null, new object[] { optionBuilder, shardingRuntimeContext }); - } - }); - //娉ㄥ唽澶氱鎴锋暟鎹笂涓嬫枃妯$増 - if (lYBuilderRuntimeModel.TenantTemplateDbContexts.FirstOrDefault() != null) - { - addDbContextMethod.MakeGenericMethod(lYBuilderRuntimeModel.TenantTemplateDbContexts.FirstOrDefault()).Invoke(null, new object[] { BuilderService, optionsAction, ServiceLifetime.Scoped, ServiceLifetime.Scoped }); - } - } - - /// - /// 娉ㄥ唽澶氱鎴风鐞 - /// - /// - internal static void RegisterTenantService(this IServiceCollection BuilderService) - { - BuilderService.AddSingleton(); - BuilderService.AddSingleton(); - BuilderService.AddSingleton(); - } } } \ No newline at end of file diff --git a/LingYanAspCoreFramework/Helpers/AlibabaCloudHelper.cs b/LingYanAspCoreFramework/Helpers/AlibabaCloudHelper.cs index 91fefef8b9dd4bd34a0247861b69683069d6df65..567315cebc10a5101eb57d3a0f86360ea2b36e24 100644 --- a/LingYanAspCoreFramework/Helpers/AlibabaCloudHelper.cs +++ b/LingYanAspCoreFramework/Helpers/AlibabaCloudHelper.cs @@ -22,7 +22,7 @@ namespace LingYanAspCoreFramework.Helpers { if (!ValidateHelper.IsMobile(userPhone)) { - throw new CommonException(new ResponceBody(60020,"鎵嬫満鍙风爜楠岃瘉涓嶉氳繃")); + throw new CommonException(new ResponceBody(65000, "鎵嬫満鍙风爜楠岃瘉涓嶉氳繃")); } AlibabaCloud.SDK.Dysmsapi20170525.Client client = CreateCilentExtension(); AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest sendSmsRequest = new AlibabaCloud.SDK.Dysmsapi20170525.Models.SendSmsRequest @@ -40,7 +40,7 @@ namespace LingYanAspCoreFramework.Helpers } else { - throw new CommonException(new ResponceBody(60020, "鐭俊鍙戦佸け璐")); + throw new CommonException(new ResponceBody(65000, "鐭俊鍙戦佸け璐")); } } } diff --git a/LingYanAspCoreFramework/Helpers/LoggerHelper.cs b/LingYanAspCoreFramework/Helpers/LoggerHelper.cs index 1854c96f3d6b9479568aa6035d2e8318e3ec73fa..1f2e2e9688030dca5d9b778d85a12d5783a8fd56 100644 --- a/LingYanAspCoreFramework/Helpers/LoggerHelper.cs +++ b/LingYanAspCoreFramework/Helpers/LoggerHelper.cs @@ -26,6 +26,7 @@ namespace LingYanAspCoreFramework.Helpers { Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine(str); + Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("========================================================="); Console.ResetColor(); } @@ -38,6 +39,7 @@ namespace LingYanAspCoreFramework.Helpers { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine(str); + Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("========================================================="); Console.ResetColor(); } @@ -48,8 +50,9 @@ namespace LingYanAspCoreFramework.Helpers /// public static void DefaultLog(string str) { - Console.ForegroundColor = ConsoleColor.DarkBlue; + Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(str); + Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("========================================================="); Console.ResetColor(); } diff --git a/LingYanAspCoreFramework/Helpers/TencentCloudHelper.cs b/LingYanAspCoreFramework/Helpers/TencentCloudHelper.cs index 0fb21b9a38a735dfa190fa277499a54104ee0044..5016e6f76da933988c226f4fa77e3d77e89e1a1a 100644 --- a/LingYanAspCoreFramework/Helpers/TencentCloudHelper.cs +++ b/LingYanAspCoreFramework/Helpers/TencentCloudHelper.cs @@ -1,12 +1,10 @@ 锘縰sing LingYanAspCoreFramework.Models; -using Microsoft.Extensions.Configuration; using TencentCloud.Common; using TencentCloud.Common.Profile; using TencentCloud.Dnspod.V20210323; using TencentCloud.Dnspod.V20210323.Models; using TencentCloud.Sms.V20210111; using TencentCloud.Sms.V20210111.Models; -using TencentCloud.Tse.V20201207; namespace LingYanAspCoreFramework.Helpers { @@ -51,7 +49,7 @@ namespace LingYanAspCoreFramework.Helpers } else { - throw new CommonException(new ResponceBody(60020, "鐭俊鍙戦佸け璐")); + throw new CommonException(new ResponceBody(66000, "鐭俊鍙戦佸け璐")); } } public static async Task DomainAddTxTRecord(string domain, string recordValue) diff --git a/LingYanAspCoreFramework/Https/LingYanHttpClient.cs b/LingYanAspCoreFramework/Https/LingYanHttpClient.cs deleted file mode 100644 index 56344796185e02dd0f65922ea4b649d221f29561..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/Https/LingYanHttpClient.cs +++ /dev/null @@ -1,445 +0,0 @@ -锘縰sing LingYanAspCoreFramework.Models; -using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using System.Net.Http.Headers; -using System.Web; - -namespace LingYanAspCoreFramework.Https -{ - public class LingYanHttpClient - { - private readonly IHttpClientFactory _httpClientFactory; - private readonly ILogger _logger; - - public LingYanHttpClient(IHttpClientFactory httpClientFactory, ILogger logger) - { - _httpClientFactory = httpClientFactory; - _logger = logger; - } - - /// - /// 鍙戦 GET 璇锋眰 - /// - /// 杩斿洖鏁版嵁鐨勭被鍨 - /// 璇锋眰鐨 URL - /// 鏌ヨ鍙傛暟 - /// 璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// 杩斿洖鏁版嵁 - public async Task GetAsync(string url, Dictionary queryParams = null, Dictionary dicHeaders = null, int timeoutSecond = 180, string clientName = null, HttpMessageHandler handler = null) - { - try - { - var client = BuildHttpClient(dicHeaders, timeoutSecond, clientName, handler); - if (queryParams != null) - { - url = AppendQueryParams(url, queryParams); - } - var response = await client.GetAsync(url); - var responseContent = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) - { - return JsonConvert.DeserializeObject(responseContent); - } - else - { - throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); - } - } - catch (HttpRequestException ex) - { - _logger.LogError($"HttpGet:{url} HttpRequestException:{ex}"); - throw new Exception($"HttpGet:{url} HttpRequestException", ex); - } - catch (TaskCanceledException ex) - { - _logger.LogError($"HttpGet:{url} TaskCanceledException:{ex}"); - throw new Exception($"HttpGet:{url} TaskCanceledException", ex); - } - catch (OperationCanceledException ex) - { - _logger.LogError($"HttpGet:{url} OperationCanceledException:{ex}"); - throw new Exception($"HttpGet:{url} OperationCanceledException", ex); - } - catch (Exception ex) - { - _logger.LogError($"HttpGet:{url} Error:{ex}"); - throw new Exception($"HttpGet:{url} Error", ex); - } - } - - /// - /// 鍙戦 POST 璇锋眰 - /// - /// 杩斿洖鏁版嵁鐨勭被鍨 - /// 璇锋眰鐨 URL - /// 璇锋眰浣 - /// 璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// 杩斿洖鏁版嵁 - public async Task PostAsync(string url, object requestBody, Dictionary dicHeaders = null, int timeoutSecond = 180, string clientName = null, HttpMessageHandler handler = null) - { - try - { - var client = BuildHttpClient(dicHeaders, timeoutSecond, clientName, handler); - var requestContent = GenerateHttpContent(requestBody, dicHeaders); - var response = await client.PostAsync(url, requestContent); - var responseContent = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) - { - return JsonConvert.DeserializeObject(responseContent); - } - else - { - throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); - } - } - catch (HttpRequestException ex) - { - _logger.LogError($"HttpPost:{url} HttpRequestException:{ex}"); - throw new Exception($"HttpPost:{url} HttpRequestException", ex); - } - catch (TaskCanceledException ex) - { - _logger.LogError($"HttpPost:{url} TaskCanceledException:{ex}"); - throw new Exception($"HttpPost:{url} TaskCanceledException", ex); - } - catch (OperationCanceledException ex) - { - _logger.LogError($"HttpPost:{url} OperationCanceledException:{ex}"); - throw new Exception($"HttpPost:{url} OperationCanceledException", ex); - } - catch (Exception ex) - { - _logger.LogError($"HttpPost:{url},body:{requestBody} Error:{ex}"); - throw new Exception($"HttpPost:{url} Error", ex); - } - } - - /// - /// 鍙戦 PUT 璇锋眰 - /// - /// 杩斿洖鏁版嵁鐨勭被鍨 - /// 璇锋眰鐨 URL - /// 璇锋眰浣 - /// 璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// 杩斿洖鏁版嵁 - public async Task PutAsync(string url, object requestBody, Dictionary dicHeaders = null, int timeoutSecond = 180, string clientName = null, HttpMessageHandler handler = null) - { - try - { - var client = BuildHttpClient(dicHeaders, timeoutSecond, clientName, handler); - var requestContent = GenerateHttpContent(requestBody, dicHeaders); - var response = await client.PutAsync(url, requestContent); - var responseContent = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) - { - return JsonConvert.DeserializeObject(responseContent); - } - else - { - throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); - } - } - catch (HttpRequestException ex) - { - _logger.LogError($"HttpPut:{url} HttpRequestException:{ex}"); - throw new Exception($"HttpPut:{url} HttpRequestException", ex); - } - catch (TaskCanceledException ex) - { - _logger.LogError($"HttpPut:{url} TaskCanceledException:{ex}"); - throw new Exception($"HttpPut:{url} TaskCanceledException", ex); - } - catch (OperationCanceledException ex) - { - _logger.LogError($"HttpPut:{url} OperationCanceledException:{ex}"); - throw new Exception($"HttpPut:{url} OperationCanceledException", ex); - } - catch (Exception ex) - { - _logger.LogError($"HttpPut:{url},Body:{requestBody}, Error:{ex}"); - throw new Exception($"HttpPut:{url} Error", ex); - } - } - - /// - /// 鍙戦 PATCH 璇锋眰 - /// - /// 杩斿洖鏁版嵁鐨勭被鍨 - /// 璇锋眰鐨 URL - /// 璇锋眰浣 - /// 璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// 杩斿洖鏁版嵁 - public async Task PatchAsync(string url, object requestBody, Dictionary dicHeaders = null, int timeoutSecond = 180, string clientName = null, HttpMessageHandler handler = null) - { - try - { - var client = BuildHttpClient(dicHeaders, timeoutSecond, clientName, handler); - var requestContent = GenerateHttpContent(requestBody, dicHeaders); - var response = await client.PatchAsync(url, requestContent); - var responseContent = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) - { - return JsonConvert.DeserializeObject(responseContent); - } - else - { - throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); - } - } - catch (HttpRequestException ex) - { - _logger.LogError($"HttpPatch:{url} HttpRequestException:{ex}"); - throw new Exception($"HttpPatch:{url} HttpRequestException", ex); - } - catch (TaskCanceledException ex) - { - _logger.LogError($"HttpPatch:{url} TaskCanceledException:{ex}"); - throw new Exception($"HttpPatch:{url} TaskCanceledException", ex); - } - catch (OperationCanceledException ex) - { - _logger.LogError($"HttpPatch:{url} OperationCanceledException:{ex}"); - throw new Exception($"HttpPatch:{url} OperationCanceledException", ex); - } - catch (Exception ex) - { - _logger.LogError($"HttpPatch:{url},body:{requestBody}, Error:{ex}"); - throw new Exception($"HttpPatch:{url} Error", ex); - } - } - - /// - /// 鍙戦 DELETE 璇锋眰 - /// - /// 杩斿洖鏁版嵁鐨勭被鍨 - /// 璇锋眰鐨 URL - /// 璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// 杩斿洖鏁版嵁 - public async Task DeleteAsync(string url, Dictionary dicHeaders = null, int timeoutSecond = 180,string clientName = null, HttpMessageHandler handler = null) - { - try - { - var client = BuildHttpClient(dicHeaders, timeoutSecond, clientName, handler); - var response = await client.DeleteAsync(url); - var responseContent = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) - { - return JsonConvert.DeserializeObject(responseContent); - } - else - { - throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); - } - } - catch (HttpRequestException ex) - { - _logger.LogError($"HttpDelete:{url} HttpRequestException:{ex}"); - throw new Exception($"HttpDelete:{url} HttpRequestException", ex); - } - catch (TaskCanceledException ex) - { - _logger.LogError($"HttpDelete:{url} TaskCanceledException:{ex}"); - throw new Exception($"HttpDelete:{url} TaskCanceledException", ex); - } - catch (OperationCanceledException ex) - { - _logger.LogError($"HttpDelete:{url} OperationCanceledException:{ex}"); - throw new Exception($"HttpDelete:{url} OperationCanceledException", ex); - } - catch (Exception ex) - { - _logger.LogError($"HttpDelete:{url}, Error:{ex}"); - throw new Exception($"HttpDelete:{url} Error", ex); - } - } - - /// - /// 鍙戦侀氱敤璇锋眰 - /// - /// 杩斿洖鏁版嵁鐨勭被鍨 - /// 璇锋眰鐨 URL - /// HTTP 鏂规硶 - /// 璇锋眰浣 - /// 鏌ヨ鍙傛暟 - /// 璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// 杩斿洖鏁版嵁 - public async Task ExecuteAsync(string url, HttpMethod method,object requestBody = null, Dictionary queryParams = null, Dictionary dicHeaders = null, int timeoutSecond = 180, string clientName = null, HttpMessageHandler handler = null) - { - try - { - var client = BuildHttpClient(dicHeaders, timeoutSecond, clientName, handler); - if (queryParams != null) - { - url = AppendQueryParams(url, queryParams); - } - var request = GenerateHttpRequestMessage(url, requestBody, method, dicHeaders); - var response = await client.SendAsync(request); - var responseContent = await response.Content.ReadAsStringAsync(); - if (response.IsSuccessStatusCode) - { - var type = typeof(T); - if (type.IsPrimitive || type == typeof(string)) - { - return (T)Convert.ChangeType(responseContent, typeof(T)); - } - else - { - return JsonConvert.DeserializeObject(responseContent); - } - } - else - { - throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); - } - } - catch (HttpRequestException ex) - { - _logger.LogError($"{method}:{url} HttpRequestException:{ex}"); - throw new Exception($"{method}:{url} HttpRequestException", ex); - } - catch (TaskCanceledException ex) - { - _logger.LogError($"{method}:{url} TaskCanceledException:{ex}"); - throw new Exception($"{method}:{url} TaskCanceledException", ex); - } - catch (OperationCanceledException ex) - { - _logger.LogError($"{method}:{url} OperationCanceledException:{ex}"); - throw new Exception($"{method}:{url} OperationCanceledException", ex); - } - catch (Exception ex) - { - _logger.LogError($"{method}:{url},body:{requestBody}, Error:{ex}"); - throw new Exception($"{method}:{url} Error", ex); - } - } - - /// - /// 鏋勫缓 HttpClient - /// - /// 榛樿璇锋眰澶 - /// 瓒呮椂鏃堕棿锛堢锛 - /// HttpClient 鍚嶇О - /// 鑷畾涔 HttpMessageHandler - /// HttpClient 瀹炰緥 - private HttpClient BuildHttpClient(Dictionary dicDefaultHeaders, int? timeoutSecond, string clientName = null, HttpMessageHandler handler = null) - { - HttpClient httpClient; - if (handler != null) - { - httpClient = new HttpClient(handler); - } - else if (!string.IsNullOrEmpty(clientName)) - { - httpClient = _httpClientFactory.CreateClient(clientName); - } - else - { - httpClient = _httpClientFactory.CreateClient(); - } - - httpClient.DefaultRequestHeaders.Clear(); - httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - if (dicDefaultHeaders != null) - { - foreach (var headerItem in dicDefaultHeaders) - { - httpClient.DefaultRequestHeaders.Add(headerItem.Key, headerItem.Value); - } - } - if (timeoutSecond != null) - { - httpClient.Timeout = TimeSpan.FromSeconds(timeoutSecond.Value); - } - return httpClient; - } - - /// - /// 鐢熸垚 HttpRequestMessage - /// - /// 璇锋眰鐨 URL - /// 璇锋眰浣 - /// HTTP 鏂规硶 - /// 璇锋眰澶 - /// HttpRequestMessage 瀹炰緥 - private HttpRequestMessage GenerateHttpRequestMessage(string url, object requestBody, HttpMethod method, Dictionary dicHeaders) - { - var request = new HttpRequestMessage(method, url); - if (requestBody != null) - { - request.Content = GenerateHttpContent(requestBody, dicHeaders); - } - if (dicHeaders != null) - { - foreach (var header in dicHeaders) - { - request.Headers.Add(header.Key, header.Value); - } - } - return request; - } - - /// - /// 鐢熸垚 HttpContent - /// - /// 璇锋眰浣 - /// 璇锋眰澶 - /// HttpContent 瀹炰緥 - private HttpContent GenerateHttpContent(object requestBody, Dictionary dicHeaders) - { - HttpContent content; - switch (requestBody) - { - case string str: - content = new StringContent(str, System.Text.Encoding.UTF8, "application/json"); - break; - case byte[] bytes: - content = new ByteArrayContent(bytes); - content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); - break; - case Dictionary formData: - content = new FormUrlEncodedContent(formData); - break; - case MultipartFormDataContent multipartFormData: - content = multipartFormData; - break; - default: - var json = JsonConvert.SerializeObject(requestBody); - content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); - break; - } - if (dicHeaders != null) - { - foreach (var headerItem in dicHeaders) - { - content.Headers.Add(headerItem.Key, headerItem.Value); - } - } - return content; - } - - /// - /// 娣诲姞鏌ヨ鍙傛暟鍒 URL - /// - /// 璇锋眰鐨 URL - /// 鏌ヨ鍙傛暟 - /// 甯︽煡璇㈠弬鏁扮殑 URL - private string AppendQueryParams(string url, Dictionary queryParams) - { - var uriBuilder = new UriBuilder(url); - var query = HttpUtility.ParseQueryString(uriBuilder.Query); - foreach (var param in queryParams) - { - query[param.Key] = param.Value; - } - uriBuilder.Query = query.ToString(); - return uriBuilder.ToString(); - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/Https/PollyHttpClient.cs b/LingYanAspCoreFramework/Https/PollyHttpClient.cs new file mode 100644 index 0000000000000000000000000000000000000000..f2aeb8526a5cb5572dada10a0708d9c915fecf5b --- /dev/null +++ b/LingYanAspCoreFramework/Https/PollyHttpClient.cs @@ -0,0 +1,69 @@ +锘縰sing LingYanAspCoreFramework.Models; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Newtonsoft.Json; +using Polly; +using Polly.Retry; + +namespace LingYanAspCoreFramework.Https +{ + public partial class PollyHttpClient + { + private readonly IHttpClientFactory _httpClientFactory; + private readonly ILogger _logger; + private readonly AsyncRetryPolicy _retryPolicy; + private readonly PollyHttpClientOption _options; + + public PollyHttpClient(IHttpClientFactory httpClientFactory, ILogger logger, IOptions options) + { + _httpClientFactory = httpClientFactory; + _logger = logger; + _options = options.Value; + _retryPolicy = Policy.HandleResult(r => !r.IsSuccessStatusCode) + .WaitAndRetryAsync(_options.RetryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), + (response, timespan, retryCount, context) => + { + _logger.LogWarning($"璇锋眰澶辫触,绛夊緟{timespan}鍚庨噸璇,閲嶈瘯娆℃暟{retryCount}"); + }); + } + + public async Task ExecuteAsync(string url, HttpMethod method, object requestBody = null, Dictionary queryParams = null, Dictionary dicHeaders = null, int? timeoutSecond = null, string clientName = null, HttpMessageHandler handler = null) + { + try + { + var client = BuildHttpClient(dicHeaders, timeoutSecond ?? _options.DefaultTimeout, clientName, handler); + if (queryParams != null) + { + url = AppendQueryParams(url, queryParams); + } + var request = GenerateHttpRequestMessage(url, requestBody, method, dicHeaders); + var response = await _retryPolicy.ExecuteAsync(() => client.SendAsync(request)); + var responseContent = await response.Content.ReadAsStringAsync(); + LogRequestAndResponse(url, requestBody, responseContent, response.IsSuccessStatusCode); + if (response.IsSuccessStatusCode) + { + var type = typeof(T); + if (type.IsPrimitive || type == typeof(string)) + { + return (T)Convert.ChangeType(responseContent, typeof(T)); + } + else + { + return JsonConvert.DeserializeObject(responseContent); + } + } + else + { + throw new CommonException(new ResponceBody(61000, response.StatusCode.ToString() + responseContent)); + } + } + catch (Exception ex) + { + _logger.LogError($"{method}:{url} 閿欒:{ex}"); + throw; + } + } + + + } +} \ No newline at end of file diff --git a/LingYanAspCoreFramework/Https/PollyHttpClientOption.cs b/LingYanAspCoreFramework/Https/PollyHttpClientOption.cs new file mode 100644 index 0000000000000000000000000000000000000000..c18464efd6975d3ed0df731e02d25077ac9003f3 --- /dev/null +++ b/LingYanAspCoreFramework/Https/PollyHttpClientOption.cs @@ -0,0 +1,8 @@ +锘縩amespace LingYanAspCoreFramework.Https +{ + public class PollyHttpClientOption + { + public int RetryCount { get; set; } = 3; + public int DefaultTimeout { get; set; } = 180; + } +} diff --git a/LingYanAspCoreFramework/Https/PollyHttpClientPart.cs b/LingYanAspCoreFramework/Https/PollyHttpClientPart.cs new file mode 100644 index 0000000000000000000000000000000000000000..ae1ec8a86254ad351375fc83fba09a61cc724a1e --- /dev/null +++ b/LingYanAspCoreFramework/Https/PollyHttpClientPart.cs @@ -0,0 +1,138 @@ +锘縰sing Microsoft.Extensions.Logging; +using Newtonsoft.Json; +using System.Net.Http.Headers; +using System.Web; + +namespace LingYanAspCoreFramework.Https +{ + public partial class PollyHttpClient + { + public Task GetAsync(string url, Dictionary queryParams = null, Dictionary dicHeaders = null, int? timeoutSecond = null, string clientName = null, HttpMessageHandler handler = null) + { + return ExecuteAsync(url, HttpMethod.Get, null, queryParams, dicHeaders, timeoutSecond, clientName, handler); + } + + public Task PostAsync(string url, object requestBody, Dictionary dicHeaders = null, int? timeoutSecond = null, string clientName = null, HttpMessageHandler handler = null) + { + return ExecuteAsync(url, HttpMethod.Post, requestBody, null, dicHeaders, timeoutSecond, clientName, handler); + } + + public Task PutAsync(string url, object requestBody, Dictionary dicHeaders = null, int? timeoutSecond = null, string clientName = null, HttpMessageHandler handler = null) + { + return ExecuteAsync(url, HttpMethod.Put, requestBody, null, dicHeaders, timeoutSecond, clientName, handler); + } + + public Task PatchAsync(string url, object requestBody, Dictionary dicHeaders = null, int? timeoutSecond = null, string clientName = null, HttpMessageHandler handler = null) + { + return ExecuteAsync(url, HttpMethod.Patch, requestBody, null, dicHeaders, timeoutSecond, clientName, handler); + } + + public Task DeleteAsync(string url, Dictionary dicHeaders = null, int? timeoutSecond = null, string clientName = null, HttpMessageHandler handler = null) + { + return ExecuteAsync(url, HttpMethod.Delete, null, null, dicHeaders, timeoutSecond, clientName, handler); + } + + + private HttpClient BuildHttpClient(Dictionary dicDefaultHeaders, int timeoutSecond, string clientName = null, HttpMessageHandler handler = null) + { + HttpClient httpClient; + if (handler != null) + { + httpClient = new HttpClient(handler); + } + else if (!string.IsNullOrEmpty(clientName)) + { + httpClient = _httpClientFactory.CreateClient(clientName); + } + else + { + httpClient = _httpClientFactory.CreateClient(); + } + + httpClient.DefaultRequestHeaders.Clear(); + httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + if (dicDefaultHeaders != null) + { + foreach (var headerItem in dicDefaultHeaders) + { + httpClient.DefaultRequestHeaders.Add(headerItem.Key, headerItem.Value); + } + } + httpClient.Timeout = TimeSpan.FromSeconds(timeoutSecond); + return httpClient; + } + + private HttpRequestMessage GenerateHttpRequestMessage(string url, object requestBody, HttpMethod method, Dictionary dicHeaders) + { + var request = new HttpRequestMessage(method, url); + if (requestBody != null) + { + request.Content = GenerateHttpContent(requestBody, dicHeaders); + } + if (dicHeaders != null) + { + foreach (var header in dicHeaders) + { + request.Headers.Add(header.Key, header.Value); + } + } + return request; + } + + private HttpContent GenerateHttpContent(object requestBody, Dictionary dicHeaders) + { + HttpContent content; + switch (requestBody) + { + case string str: + content = new StringContent(str, System.Text.Encoding.UTF8, "application/json"); + break; + case byte[] bytes: + content = new ByteArrayContent(bytes); + content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); + break; + case Dictionary formData: + content = new FormUrlEncodedContent(formData); + break; + case MultipartFormDataContent multipartFormData: + content = multipartFormData; + break; + default: + var json = JsonConvert.SerializeObject(requestBody); + content = new StringContent(json, System.Text.Encoding.UTF8, "application/json"); + break; + } + if (dicHeaders != null) + { + foreach (var headerItem in dicHeaders) + { + content.Headers.Add(headerItem.Key, headerItem.Value); + } + } + return content; + } + + private string AppendQueryParams(string url, Dictionary queryParams) + { + var uriBuilder = new UriBuilder(url); + var query = HttpUtility.ParseQueryString(uriBuilder.Query); + foreach (var param in queryParams) + { + query[param.Key] = param.Value; + } + uriBuilder.Query = query.ToString(); + return uriBuilder.ToString(); + } + + private void LogRequestAndResponse(string url, object requestBody, string responseContent, bool isSuccessStatusCode) + { + _logger.LogInformation($"璺敱: {url}"); + if (requestBody != null) + { + _logger.LogInformation($"璇锋眰浣: {JsonConvert.SerializeObject(requestBody)}"); + } + _logger.LogInformation($"杩斿洖浣: {responseContent}"); + _logger.LogInformation($"鐘舵: {isSuccessStatusCode}"); + } + } +} diff --git a/LingYanAspCoreFramework/LingYanAspCoreFramework.csproj b/LingYanAspCoreFramework/LingYanAspCoreFramework.csproj index 4518a530a615a5157fb5b098955b95df896127b3..1beed3fc7701aa09df270a81e6d97a5521b43fcc 100644 --- a/LingYanAspCoreFramework/LingYanAspCoreFramework.csproj +++ b/LingYanAspCoreFramework/LingYanAspCoreFramework.csproj @@ -5,7 +5,7 @@ enable True LingYanAspCoreFramework - 2.0.7 + 8.0.0 閬靛畧DDD棰嗗煙璁捐鎬濇兂锛岄拡瀵笰SP.NET CORE鐨勫悗绔垎灞傛鏋讹紝灏佽濂界伒娲荤殑浠撳偍銆佸伐浣滃崟鍏冿紝鍚勭鏈嶅姟鏈夌壒鎬ф爣璁板彲浠ヨ嚜鍔ㄦ敞鍏 LingYanSpace @@ -27,39 +27,50 @@ - - - - + + + + + + + - + + - + + - + + + true + contentFiles\any\any\Envs\ + + + True diff --git a/LingYanAspCoreFramework/Models/RuntimeCacheModel.cs b/LingYanAspCoreFramework/Models/RuntimeCacheModel.cs index 0633c81934d013304f99cacf9d834f0fe11a97d9..8ee93c03881f9f586f68ca46e845880c28a5e9b4 100644 --- a/LingYanAspCoreFramework/Models/RuntimeCacheModel.cs +++ b/LingYanAspCoreFramework/Models/RuntimeCacheModel.cs @@ -1,5 +1,4 @@ 锘縰sing LingYanAspCoreFramework.Attributes; -using Microsoft.Extensions.Configuration; using System.Reflection; namespace LingYanAspCoreFramework.Models @@ -8,7 +7,7 @@ namespace LingYanAspCoreFramework.Models { //閿负缂栬瘧搴擄紝鍊间负鍔犺浇鍩虹被 internal Dictionary ModuleAssemblyBaseLoadingKeyValue { get; set; } - internal Dictionary ModuleDbContextList { get; set; } + internal List ModuleDbContextList { get; set; } internal Dictionary ModuleTenantBaseEntitys { get; set; } internal Dictionary ModuleTBaseEntitys { get; set; } internal List ModuleAuthorizeHandler { get; set; } @@ -16,20 +15,16 @@ namespace LingYanAspCoreFramework.Models internal List ModuleManagerList { get; set; } internal List ModuleTService { get; set; } internal List ModuleTInstance { get; set; } - internal Dictionary> VirtualTableList { get; set; } - internal List TenantTemplateDbContexts { get; set; } internal List ModuleFiler { get; set; } public RuntimeCacheModel() { this.ModuleAssemblyBaseLoadingKeyValue = new Dictionary(); - this.ModuleDbContextList = new Dictionary(); + this.ModuleDbContextList = new List(); this.ModuleTenantBaseEntitys = new Dictionary(); this.ModuleManagerList = new List(); this.ModuleTService = new List(); - this.ModuleTInstance = new List(); - this.VirtualTableList = new Dictionary>(); - this.TenantTemplateDbContexts = new List(); + this.ModuleTInstance = new List(); this.ModuleFiler = new List(); this.ModuleTBaseEntitys = new Dictionary(); this.ModuleTMiddleware = new List(); diff --git a/LingYanAspCoreFramework/Models/WeChat/WeChatDevOption.cs b/LingYanAspCoreFramework/Models/WeChat/WeChatDevOption.cs index 901312258c3fb74265f60f6776ce20fb729de4d1..c7806e2ab4037a10ea4aabd1953869c3a7fa24ab 100644 --- a/LingYanAspCoreFramework/Models/WeChat/WeChatDevOption.cs +++ b/LingYanAspCoreFramework/Models/WeChat/WeChatDevOption.cs @@ -1,10 +1,4 @@ -锘縰sing System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace LingYanAspCoreFramework.Models.WeChat +锘縩amespace LingYanAspCoreFramework.Models.WeChat { public class WeChatDevOption { diff --git a/LingYanAspCoreFramework/MultiTenants/IMigrationNamespace.cs b/LingYanAspCoreFramework/MultiTenants/IMigrationNamespace.cs deleted file mode 100644 index eab78d0967e75a2e5dad9bfa6a0590bcc884c0a1..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/IMigrationNamespace.cs +++ /dev/null @@ -1,7 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.MultiTenants -{ - public interface IMigrationNamespace - { - string GetNamespace(); - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/IShardingBuilder.cs b/LingYanAspCoreFramework/MultiTenants/IShardingBuilder.cs deleted file mode 100644 index 9115798f6e5a7905d4d8641771af6899fce6f0e1..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/IShardingBuilder.cs +++ /dev/null @@ -1,9 +0,0 @@ -锘縰sing ShardingCore.Core.RuntimeContexts; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public interface IShardingBuilder - { - IShardingRuntimeContext Build(ShardingTenantOptions tenantOptions); - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/ITenantContextAccessor.cs b/LingYanAspCoreFramework/MultiTenants/ITenantContextAccessor.cs deleted file mode 100644 index 0df975b6b17d4c45a7d78bf05861a66d2ecf7b27..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/ITenantContextAccessor.cs +++ /dev/null @@ -1,7 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.MultiTenants -{ - public interface ITenantContextAccessor - { - TenantContext? TenantContext { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/ITenantManager.cs b/LingYanAspCoreFramework/MultiTenants/ITenantManager.cs deleted file mode 100644 index 79782203a45d491b6e13a4428a31e13463f71b71..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/ITenantManager.cs +++ /dev/null @@ -1,15 +0,0 @@ -锘縰sing ShardingCore.Core.RuntimeContexts; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public interface ITenantManager - { - bool AddTenantSharding(object tenantId, IShardingRuntimeContext shardingRuntimeContext); - - TenantScope CreateScope(object tenantId); - - List GetAll(); - - TenantContext GetCurrentTenantContext(); - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/MigrationExtension.cs b/LingYanAspCoreFramework/MultiTenants/MigrationExtension.cs deleted file mode 100644 index db7f8c2b54bc887808f068a8f1ff0757b85deb10..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/MigrationExtension.cs +++ /dev/null @@ -1,20 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public static class MigrationExtension - { - public static DbContextOptionsBuilder UseMigrationNamespace(this DbContextOptionsBuilder optionsBuilder, IMigrationNamespace migrationNamespace) - { - var shardingWrapExtension = optionsBuilder.CreateOrGetExtension(migrationNamespace); - ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(shardingWrapExtension); - return optionsBuilder; - } - - private static MigrationNamespaceExtension CreateOrGetExtension( - this DbContextOptionsBuilder optionsBuilder, IMigrationNamespace migrationNamespace) - => optionsBuilder.Options.FindExtension() ?? - new MigrationNamespaceExtension(migrationNamespace); - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/MigrationNamespaceExtension.cs b/LingYanAspCoreFramework/MultiTenants/MigrationNamespaceExtension.cs deleted file mode 100644 index 1a556f9792a67efd7117edeea4fb1cf1a7992408..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/MigrationNamespaceExtension.cs +++ /dev/null @@ -1,48 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.Extensions.DependencyInjection; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class MigrationNamespaceExtension : IDbContextOptionsExtension - { - public IMigrationNamespace MigrationNamespace { get; } - - public MigrationNamespaceExtension(IMigrationNamespace migrationNamespace) - { - MigrationNamespace = migrationNamespace; - } - - public void ApplyServices(IServiceCollection services) - { - services.AddSingleton(sp => MigrationNamespace); - } - - public void Validate(IDbContextOptions options) - { - } - - public DbContextOptionsExtensionInfo Info => new MigrationNamespaceExtensionInfo(this); - - private class MigrationNamespaceExtensionInfo : DbContextOptionsExtensionInfo - { - private readonly MigrationNamespaceExtension _migrationNamespaceExtension; - - public MigrationNamespaceExtensionInfo(IDbContextOptionsExtension extension) : base(extension) - { - _migrationNamespaceExtension = (MigrationNamespaceExtension)extension; - } - - public override int GetServiceProviderHashCode() => - _migrationNamespaceExtension.MigrationNamespace.GetNamespace().GetHashCode(); - - public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other) => true; - - public override void PopulateDebugInfo(IDictionary debugInfo) - { - } - - public override bool IsDatabaseProvider => false; - public override string LogFragment => "MigrationNamespaceExtension"; - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/MultiDatabaseMigrationsAssembly.cs b/LingYanAspCoreFramework/MultiTenants/MultiDatabaseMigrationsAssembly.cs deleted file mode 100644 index fcfb046fbcdf8f2924b01046f1ba7d54df420241..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/MultiDatabaseMigrationsAssembly.cs +++ /dev/null @@ -1,136 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using System.Reflection; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class MultiDatabaseMigrationsAssembly : IMigrationsAssembly - { - public string MigrationNamespace { get; } - private readonly IMigrationsIdGenerator _idGenerator; - private readonly IDiagnosticsLogger _logger; - private IReadOnlyDictionary? _migrations; - private ModelSnapshot? _modelSnapshot; - private readonly Type _contextType; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public MultiDatabaseMigrationsAssembly( - IMigrationNamespace migrationNamespace, - ICurrentDbContext currentContext, - IDbContextOptions options, - IMigrationsIdGenerator idGenerator, - IDiagnosticsLogger logger) - { - _contextType = currentContext.Context.GetType(); - - var assemblyName = RelationalOptionsExtension.Extract(options)?.MigrationsAssembly; - Assembly = assemblyName == null - ? _contextType.Assembly - : Assembly.Load(new AssemblyName(assemblyName)); - - MigrationNamespace = migrationNamespace.GetNamespace(); - _idGenerator = idGenerator; - _logger = logger; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual IReadOnlyDictionary Migrations - { - get - { - IReadOnlyDictionary Create() - { - var result = new SortedList(); - var items - = from t in Assembly.GetConstructibleTypes() - where t.IsSubclassOf(typeof(Migration)) - && t.Namespace.Equals(MigrationNamespace) - && t.GetCustomAttribute()?.ContextType == _contextType - let id = t.GetCustomAttribute()?.Id - orderby id - select (id, t); - foreach (var (id, t) in items) - { - if (id == null) - { - _logger.MigrationAttributeMissingWarning(t); - - continue; - } - - result.Add(id, t); - } - - return result; - } - - return _migrations ??= Create(); - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual ModelSnapshot? ModelSnapshot - => _modelSnapshot ??= (from t in Assembly.GetConstructibleTypes() - where t.IsSubclassOf(typeof(ModelSnapshot)) - && MigrationNamespace.Equals(t?.Namespace) - && t.GetCustomAttribute()?.ContextType == _contextType - select (ModelSnapshot)Activator.CreateInstance(t.AsType())!) - .FirstOrDefault(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual Assembly Assembly { get; } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual string? FindMigrationId(string nameOrId) - => Migrations.Keys - .Where( - _idGenerator.IsValidId(nameOrId) - // ReSharper disable once ImplicitlyCapturedClosure - ? id => string.Equals(id, nameOrId, StringComparison.OrdinalIgnoreCase) - : id => string.Equals(_idGenerator.GetName(id), nameOrId, StringComparison.OrdinalIgnoreCase)) - .FirstOrDefault(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual Migration CreateMigration(TypeInfo migrationClass, string activeProvider) - { - Console.WriteLine(migrationClass.FullName); - - var migration = (Migration)Activator.CreateInstance(migrationClass.AsType())!; - migration.ActiveProvider = activeProvider; - - return migration; - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/MySqlMigrationNamespace.cs b/LingYanAspCoreFramework/MultiTenants/MySqlMigrationNamespace.cs deleted file mode 100644 index eaed21a7e385226d09ad4e6fd718a8df1c2d289e..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/MySqlMigrationNamespace.cs +++ /dev/null @@ -1,10 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.MultiTenants -{ - public class MySqlMigrationNamespace : IMigrationNamespace - { - public string GetNamespace() - { - return "ShardingCoreMultiTenantSys.Migrations.MySql"; - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/ShardingBuilder.cs b/LingYanAspCoreFramework/MultiTenants/ShardingBuilder.cs deleted file mode 100644 index 0725282800677fd5e9a31515a05415948ebfb9a1..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/ShardingBuilder.cs +++ /dev/null @@ -1,123 +0,0 @@ -锘縰sing LingYanAspCoreFramework.Attributes; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using ShardingCore; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Core.ServiceProviders; -using ShardingCore.Core.ShardingConfigurations; -using ShardingCore.Core.ShardingConfigurations.Abstractions; -using ShardingCore.TableExists; -using ShardingCore.TableExists.Abstractions; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class ShardingBuilder : IShardingBuilder - { - private readonly IServiceProvider _serviceProvider; - - public ShardingBuilder(IServiceProvider serviceProvider) - { - _serviceProvider = serviceProvider; - } - - public IShardingRuntimeContext Build(ShardingTenantOptions tenantOptions) - { - Type shardingRuntimeBuilderType = typeof(ShardingRuntimeBuilder<>); - Type dbContextType = LingYanRuntimeManager.RuntimeCacheModel.TenantTemplateDbContexts.FirstOrDefault(); - Type constructedType = shardingRuntimeBuilderType.MakeGenericType(dbContextType); - var shardingRuntimeBuilderInstance = Activator.CreateInstance(constructedType); - // 鍏蜂綋鍖栧悗鐨勭被鍨嬬‘瀹氬悗锛岃幏鍙栧叿浣撳寲鍚庣殑绫诲瀷鐨凪ethodInfo - Type specificType = shardingRuntimeBuilderInstance.GetType(); - //鑾峰彇閰嶇疆璺敱鏂规硶淇℃伅 - var UseRouteConfigMethodInfo = specificType.GetMethods().FirstOrDefault(f => f.Name == "UseRouteConfig" && f.GetParameters()[0].ParameterType == typeof(Action)); - //閰嶇疆璺敱濮旀墭 - var UseRouteConfigDelegate = new Action((option) => - { - if (LingYanRuntimeManager.RuntimeCacheModel.VirtualTableList.Keys.Count > 0) - { - if (tenantOptions.ShardingKeyType == ShardingKeyType.Mod) - { - LingYanRuntimeManager.RuntimeCacheModel.VirtualTableList[ShardingKeyType.Mod].ForEach(modShardingTable => - { - option.AddShardingTableRoute(modShardingTable); - }); - } - if (tenantOptions.ShardingKeyType == ShardingKeyType.Time) - { - LingYanRuntimeManager.RuntimeCacheModel.VirtualTableList[ShardingKeyType.Time].ForEach(modShardingTable => - { - option.AddShardingTableRoute(modShardingTable); - }); - } - } - }); - //鎵ц閰嶇疆 - UseRouteConfigMethodInfo.Invoke(shardingRuntimeBuilderInstance, new object[] { UseRouteConfigDelegate }); - //鍙嶅皠閰嶇疆鏁版嵁搴撴柟娉曚俊鎭 - var UseConfigMethodInfo = specificType.GetMethods().FirstOrDefault(f => f.Name == "UseConfig" && f.GetParameters()[0].ParameterType == typeof(Action)); - //閰嶇疆鏁版嵁搴撳鎵 - var UseConfigDelegate = new Action((provider, option) => - { - option.ThrowIfQueryRouteNotMatch = false; - option.UseShardingQuery((conStr, builder) => - { - if (tenantOptions.DataBaseType == DataBaseType.MYSQL) - { - builder.UseMySql(conStr, MySqlServerVersion.AutoDetect(conStr)) - .UseMigrationNamespace(new MySqlMigrationNamespace()); - } - builder.UseLoggerFactory(provider.GetService()) - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking) - .ReplaceService(); - }); - option.UseShardingTransaction((connection, builder) => - { - if (tenantOptions.DataBaseType == DataBaseType.MYSQL) - { - builder.UseMySql(connection, MySqlServerVersion.AutoDetect(connection.ConnectionString)) - .UseMigrationNamespace(new MySqlMigrationNamespace());//杩佺Щ鍙細鐢╟onnection string鍒涘缓鎵浠ュ彲浠ヤ笉鍔 - } - builder.UseLoggerFactory(provider.GetService()) - .UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); - }); - option.AddDefaultDataSource(tenantOptions.DefaultDataSourceName, tenantOptions.DefaultConnectionString); - //杩佺Щ閰嶇疆 - option.UseShardingMigrationConfigure(b => - { - if (tenantOptions.DataBaseType == DataBaseType.MYSQL) - { - b.ReplaceService(); - } - }); - }); - //鎵ц - UseConfigMethodInfo.Invoke(shardingRuntimeBuilderInstance, new object[] { UseConfigDelegate }); - //鍙嶅皠娣诲姞鏈嶅姟閰嶇疆鏂规硶淇℃伅 - var AddServiceConfigureMethodInfo = specificType.GetMethods().FirstOrDefault(f => f.Name == "AddServiceConfigure" && f.GetParameters()[0].ParameterType == typeof(Action)); - //娣诲姞鏈嶅姟閰嶇疆濮旀墭 - var AddServiceConfigureDelegate = new Action((service) => - { - service.AddSingleton(tenantOptions); - }); - //鎵ц - AddServiceConfigureMethodInfo.Invoke(shardingRuntimeBuilderInstance, new object[] { AddServiceConfigureDelegate }); - if (tenantOptions.DataBaseType == DataBaseType.MYSQL) - { - //鍙嶅皠鏇挎崲鏈嶅姟鏂规硶淇℃伅 - var ReplaceServiceMethodInfo = specificType.GetMethod("ReplaceService").MakeGenericMethod(typeof(ITableEnsureManager), typeof(MySqlTableEnsureManager)); - ReplaceServiceMethodInfo.Invoke(shardingRuntimeBuilderInstance, new object[] { ServiceLifetime.Singleton }); - } - if (tenantOptions.DataBaseType == DataBaseType.MSSQL) - { - //鍙嶅皠鏇挎崲鏈嶅姟鏂规硶淇℃伅 - var ReplaceServiceMethodInfo = specificType.GetMethod("ReplaceService").MakeGenericMethod(typeof(ITableEnsureManager), typeof(SqlServerTableEnsureManager)); - ReplaceServiceMethodInfo.Invoke(shardingRuntimeBuilderInstance, new object[] { ServiceLifetime.Singleton }); - } - //鍙嶅皠鏋勫缓鍒嗙墖杩愯鏃舵柟娉曚俊鎭 - var BuildMethodInfo = specificType.GetMethods().FirstOrDefault(w => w.Name == "Build" && w.GetParameters() != null && w.GetParameters().Count() == 1 && w.GetParameters()[0].ParameterType == typeof(IServiceProvider)); - return (IShardingRuntimeContext)BuildMethodInfo.Invoke(shardingRuntimeBuilderInstance, new object[] { _serviceProvider }); - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/ShardingMySqlMigrationsSqlGenerator.cs b/LingYanAspCoreFramework/MultiTenants/ShardingMySqlMigrationsSqlGenerator.cs deleted file mode 100644 index 76234136e7a3f00771ad2400fb168a776c5601d1..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/ShardingMySqlMigrationsSqlGenerator.cs +++ /dev/null @@ -1,34 +0,0 @@ -锘縰sing Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Migrations.Operations; -using Microsoft.EntityFrameworkCore.Update; -using Pomelo.EntityFrameworkCore.MySql.Infrastructure.Internal; -using Pomelo.EntityFrameworkCore.MySql.Migrations; -using ShardingCore.Core.RuntimeContexts; -using ShardingCore.Helpers; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class ShardingMySqlMigrationsSqlGenerator : MySqlMigrationsSqlGenerator - { - private readonly IShardingRuntimeContext _shardingRuntimeContext; - - public ShardingMySqlMigrationsSqlGenerator(IShardingRuntimeContext shardingRuntimeContext, MigrationsSqlGeneratorDependencies dependencies, ICommandBatchPreparer commandBatchPreparer, IMySqlOptions options) : base(dependencies, commandBatchPreparer, options) - { - _shardingRuntimeContext = shardingRuntimeContext; - } - - 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(_shardingRuntimeContext, operation, builder, Dependencies.SqlGenerationHelper, addCmds); - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/ShardingTenantOptions.cs b/LingYanAspCoreFramework/MultiTenants/ShardingTenantOptions.cs deleted file mode 100644 index b13a24466d86201db3b83e3cda6ed362dc3a9c3d..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/ShardingTenantOptions.cs +++ /dev/null @@ -1,37 +0,0 @@ -锘縰sing LingYanAspCoreFramework.Attributes; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class ShardingTenantOptions - { - /// - /// 榛樿鏁版嵁婧愬悕绉 - /// - public string DefaultDataSourceName { get; set; } - - /// - /// 榛樿鏁版嵁搴撳湴鍧 - /// - public string DefaultConnectionString { get; set; } - - /// - /// 鏁版嵁搴撶被鍨 - /// - public DataBaseType DataBaseType { get; set; } - - /// - /// 鍒嗙墖妯″紡 鍙栨ā杩樻槸鎸夋湀 - /// - public ShardingKeyType ShardingKeyType { get; set; } - - /// - /// 鏃堕棿鍒嗙墖寮濮嬫椂闂 - /// - public DateTime BeginTimeForSharding { get; set; } - - /// - /// 鍒嗙墖杩佺Щ鐨勫懡鍚嶇┖闂 - /// - public string MigrationNamespace { get; set; } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/SharedTypeExtensions.cs b/LingYanAspCoreFramework/MultiTenants/SharedTypeExtensions.cs deleted file mode 100644 index dadeccd3fd24edd0f050b2069d11401e0d13c9bb..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/SharedTypeExtensions.cs +++ /dev/null @@ -1,661 +0,0 @@ -锘縰sing System.Diagnostics; -using System.Linq.Expressions; -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Text; - -#nullable enable - -// ReSharper disable once CheckNamespace -namespace System -{ - [DebuggerStepThrough] - internal static class SharedTypeExtensions - { - private static readonly Dictionary _builtInTypeNames = new() - { - { typeof(bool), "bool" }, - { typeof(byte), "byte" }, - { typeof(char), "char" }, - { typeof(decimal), "decimal" }, - { typeof(double), "double" }, - { typeof(float), "float" }, - { typeof(int), "int" }, - { typeof(long), "long" }, - { typeof(object), "object" }, - { typeof(sbyte), "sbyte" }, - { typeof(short), "short" }, - { typeof(string), "string" }, - { typeof(uint), "uint" }, - { typeof(ulong), "ulong" }, - { typeof(ushort), "ushort" }, - { typeof(void), "void" } - }; - - public static Type UnwrapNullableType(this Type type) - => Nullable.GetUnderlyingType(type) ?? type; - - public static bool IsNullableValueType(this Type type) - => type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); - - public static bool IsNullableType(this Type type) - => !type.IsValueType || type.IsNullableValueType(); - - public static bool IsValidEntityType(this Type type) - => type.IsClass - && !type.IsArray; - - public static bool IsPropertyBagType(this Type type) - { - if (type.IsGenericTypeDefinition) - { - return false; - } - - var types = GetGenericTypeImplementations(type, typeof(IDictionary<,>)); - return types.Any( - t => t.GetGenericArguments()[0] == typeof(string) - && t.GetGenericArguments()[1] == typeof(object)); - } - - public static Type MakeNullable(this Type type, bool nullable = true) - => type.IsNullableType() == nullable - ? type - : nullable - ? typeof(Nullable<>).MakeGenericType(type) - : type.UnwrapNullableType(); - - public static bool IsNumeric(this Type type) - { - type = type.UnwrapNullableType(); - - return type.IsInteger() - || type == typeof(decimal) - || type == typeof(float) - || type == typeof(double); - } - - public static bool IsInteger(this Type type) - { - type = type.UnwrapNullableType(); - - return type == typeof(int) - || type == typeof(long) - || type == typeof(short) - || type == typeof(byte) - || type == typeof(uint) - || type == typeof(ulong) - || type == typeof(ushort) - || type == typeof(sbyte) - || type == typeof(char); - } - - public static bool IsSignedInteger(this Type type) - => type == typeof(int) - || type == typeof(long) - || type == typeof(short) - || type == typeof(sbyte); - - public static bool IsAnonymousType(this Type type) - => type.Name.StartsWith("<>", StringComparison.Ordinal) - && type.GetCustomAttributes(typeof(CompilerGeneratedAttribute), inherit: false).Length > 0 - && type.Name.Contains("AnonymousType"); - - public static bool IsTupleType(this Type type) - { - if (type == typeof(Tuple)) - { - return true; - } - - if (type.IsGenericType) - { - var genericDefinition = type.GetGenericTypeDefinition(); - if (genericDefinition == typeof(Tuple<>) - || genericDefinition == typeof(Tuple<,>) - || genericDefinition == typeof(Tuple<,,>) - || genericDefinition == typeof(Tuple<,,,>) - || genericDefinition == typeof(Tuple<,,,,>) - || genericDefinition == typeof(Tuple<,,,,,>) - || genericDefinition == typeof(Tuple<,,,,,,>) - || genericDefinition == typeof(Tuple<,,,,,,,>) - || genericDefinition == typeof(Tuple<,,,,,,,>)) - { - return true; - } - } - - return false; - } - - public static PropertyInfo? GetAnyProperty(this Type type, string name) - { - var props = type.GetRuntimeProperties().Where(p => p.Name == name).ToList(); - if (props.Count > 1) - { - throw new AmbiguousMatchException(); - } - - return props.SingleOrDefault(); - } - - public static MethodInfo GetRequiredMethod(this Type type, string name, params Type[] parameters) - { - var method = type.GetTypeInfo().GetMethod(name, parameters); - - if (method == null - && parameters.Length == 0) - { - method = type.GetMethod(name); - } - - if (method == null) - { - throw new InvalidOperationException(); - } - - return method; - } - - public static PropertyInfo GetRequiredProperty(this Type type, string name) - => type.GetTypeInfo().GetProperty(name) - ?? throw new InvalidOperationException($"Could not find property '{name}' on type '{type}'"); - - public static FieldInfo GetRequiredDeclaredField(this Type type, string name) - => type.GetTypeInfo().GetDeclaredField(name) - ?? throw new InvalidOperationException($"Could not find field '{name}' on type '{type}'"); - - public static MethodInfo GetRequiredDeclaredMethod(this Type type, string name) - => type.GetTypeInfo().GetDeclaredMethod(name) - ?? throw new InvalidOperationException($"Could not find method '{name}' on type '{type}'"); - - public static MethodInfo GetRequiredDeclaredMethod(this Type type, string name, Func methodSelector) - => type.GetTypeInfo().GetDeclaredMethods(name).Single(methodSelector); - - public static PropertyInfo GetRequiredDeclaredProperty(this Type type, string name) - => type.GetTypeInfo().GetDeclaredProperty(name) - ?? throw new InvalidOperationException($"Could not find property '{name}' on type '{type}'"); - - public static MethodInfo GetRequiredRuntimeMethod(this Type type, string name, params Type[] parameters) - => type.GetTypeInfo().GetRuntimeMethod(name, parameters) - ?? throw new InvalidOperationException($"Could not find method '{name}' on type '{type}'"); - - public static PropertyInfo GetRequiredRuntimeProperty(this Type type, string name) - => type.GetTypeInfo().GetRuntimeProperty(name) - ?? throw new InvalidOperationException($"Could not find property '{name}' on type '{type}'"); - - public static bool IsInstantiable(this Type type) - => !type.IsAbstract - && !type.IsInterface - && (!type.IsGenericType || !type.IsGenericTypeDefinition); - - public static Type UnwrapEnumType(this Type type) - { - var isNullable = type.IsNullableType(); - var underlyingNonNullableType = isNullable ? type.UnwrapNullableType() : type; - if (!underlyingNonNullableType.IsEnum) - { - return type; - } - - var underlyingEnumType = Enum.GetUnderlyingType(underlyingNonNullableType); - return isNullable ? MakeNullable(underlyingEnumType) : underlyingEnumType; - } - - public static Type GetSequenceType(this Type type) - { - var sequenceType = TryGetSequenceType(type); - if (sequenceType == null) - { - throw new ArgumentException($"The type {type.Name} does not represent a sequence"); - } - - return sequenceType; - } - - public static Type? TryGetSequenceType(this Type type) - => type.TryGetElementType(typeof(IEnumerable<>)) - ?? type.TryGetElementType(typeof(IAsyncEnumerable<>)); - - public static Type? TryGetElementType(this Type type, Type interfaceOrBaseType) - { - if (type.IsGenericTypeDefinition) - { - return null; - } - - var types = GetGenericTypeImplementations(type, interfaceOrBaseType); - - Type? singleImplementation = null; - foreach (var implementation in types) - { - if (singleImplementation == null) - { - singleImplementation = implementation; - } - else - { - singleImplementation = null; - break; - } - } - - return singleImplementation?.GenericTypeArguments.FirstOrDefault(); - } - - public static bool IsCompatibleWith(this Type propertyType, Type fieldType) - { - if (propertyType.IsAssignableFrom(fieldType) - || fieldType.IsAssignableFrom(propertyType)) - { - return true; - } - - var propertyElementType = propertyType.TryGetSequenceType(); - var fieldElementType = fieldType.TryGetSequenceType(); - - return propertyElementType != null - && fieldElementType != null - && IsCompatibleWith(propertyElementType, fieldElementType); - } - - public static IEnumerable GetGenericTypeImplementations(this Type type, Type interfaceOrBaseType) - { - var typeInfo = type.GetTypeInfo(); - if (!typeInfo.IsGenericTypeDefinition) - { - var baseTypes = interfaceOrBaseType.GetTypeInfo().IsInterface - ? typeInfo.ImplementedInterfaces - : type.GetBaseTypes(); - foreach (var baseType in baseTypes) - { - if (baseType.IsGenericType - && baseType.GetGenericTypeDefinition() == interfaceOrBaseType) - { - yield return baseType; - } - } - - if (type.IsGenericType - && type.GetGenericTypeDefinition() == interfaceOrBaseType) - { - yield return type; - } - } - } - - public static IEnumerable GetBaseTypes(this Type type) - { - var currentType = type.BaseType; - - while (currentType != null) - { - yield return currentType; - - currentType = currentType.BaseType; - } - } - - public static List GetBaseTypesAndInterfacesInclusive(this Type type) - { - var baseTypes = new List(); - var typesToProcess = new Queue(); - typesToProcess.Enqueue(type); - - while (typesToProcess.Count > 0) - { - type = typesToProcess.Dequeue(); - baseTypes.Add(type); - - if (type.IsNullableValueType()) - { - typesToProcess.Enqueue(Nullable.GetUnderlyingType(type)!); - } - - if (type.IsConstructedGenericType) - { - typesToProcess.Enqueue(type.GetGenericTypeDefinition()); - } - - if (!type.IsGenericTypeDefinition - && !type.IsInterface) - { - if (type.BaseType != null) - { - typesToProcess.Enqueue(type.BaseType); - } - - foreach (var @interface in GetDeclaredInterfaces(type)) - { - typesToProcess.Enqueue(@interface); - } - } - } - - return baseTypes; - } - - public static IEnumerable GetTypesInHierarchy(this Type type) - { - var currentType = type; - - while (currentType != null) - { - yield return currentType; - - currentType = currentType.BaseType; - } - } - - public static IEnumerable GetDeclaredInterfaces(this Type type) - { - var interfaces = type.GetInterfaces(); - if (type.BaseType == typeof(object) - || type.BaseType == null) - { - return interfaces; - } - - return interfaces.Except(type.BaseType.GetInterfaces()); - } - - public static ConstructorInfo GetDeclaredConstructor(this Type type, Type[]? types) - { - types ??= Array.Empty(); - - return type.GetTypeInfo().DeclaredConstructors - .SingleOrDefault( - c => !c.IsStatic - && c.GetParameters().Select(p => p.ParameterType).SequenceEqual(types))!; - } - - public static IEnumerable GetPropertiesInHierarchy(this Type type, string name) - { - var currentType = type; - do - { - var typeInfo = currentType.GetTypeInfo(); - foreach (var propertyInfo in typeInfo.DeclaredProperties) - { - if (propertyInfo.Name.Equals(name, StringComparison.Ordinal) - && !(propertyInfo.GetMethod ?? propertyInfo.SetMethod)!.IsStatic) - { - yield return propertyInfo; - } - } - - currentType = typeInfo.BaseType; - } - while (currentType != null); - } - - // Looking up the members through the whole hierarchy allows to find inherited private members. - public static IEnumerable GetMembersInHierarchy(this Type type) - { - var currentType = type; - - do - { - // Do the whole hierarchy for properties first since looking for fields is slower. - foreach (var propertyInfo in currentType.GetRuntimeProperties().Where(pi => !(pi.GetMethod ?? pi.SetMethod)!.IsStatic)) - { - yield return propertyInfo; - } - - foreach (var fieldInfo in currentType.GetRuntimeFields().Where(f => !f.IsStatic)) - { - yield return fieldInfo; - } - - currentType = currentType.BaseType; - } - while (currentType != null); - } - - public static IEnumerable GetMembersInHierarchy(this Type type, string name) - => type.GetMembersInHierarchy().Where(m => m.Name == name); - - private static readonly Dictionary _commonTypeDictionary = new() - { -#pragma warning disable IDE0034 // Simplify 'default' expression - default causes default(object) - { typeof(int), default(int) }, - { typeof(Guid), default(Guid) }, - { typeof(DateOnly), default(DateOnly) }, - { typeof(DateTime), default(DateTime) }, - { typeof(DateTimeOffset), default(DateTimeOffset) }, - { typeof(TimeOnly), default(TimeOnly) }, - { typeof(long), default(long) }, - { typeof(bool), default(bool) }, - { typeof(double), default(double) }, - { typeof(short), default(short) }, - { typeof(float), default(float) }, - { typeof(byte), default(byte) }, - { typeof(char), default(char) }, - { typeof(uint), default(uint) }, - { typeof(ushort), default(ushort) }, - { typeof(ulong), default(ulong) }, - { typeof(sbyte), default(sbyte) } -#pragma warning restore IDE0034 // Simplify 'default' expression - }; - - public static object? GetDefaultValue(this Type type) - { - if (!type.IsValueType) - { - return null; - } - - // A bit of perf code to avoid calling Activator.CreateInstance for common types and - // to avoid boxing on every call. This is about 50% faster than just calling CreateInstance - // for all value types. - return _commonTypeDictionary.TryGetValue(type, out var value) - ? value - : Activator.CreateInstance(type); - } - - public static IEnumerable GetConstructibleTypes(this Assembly assembly) - => assembly.GetLoadableDefinedTypes().Where( - t => !t.IsAbstract - && !t.IsGenericTypeDefinition); - - public static IEnumerable GetLoadableDefinedTypes(this Assembly assembly) - { - try - { - return assembly.DefinedTypes; - } - catch (ReflectionTypeLoadException ex) - { - return ex.Types.Where(t => t != null).Select(IntrospectionExtensions.GetTypeInfo!); - } - } - - public static bool IsQueryableType(this Type type) - { - if (type.IsGenericType - && type.GetGenericTypeDefinition() == typeof(IQueryable<>)) - { - return true; - } - - return type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IQueryable<>)); - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public static string DisplayName(this Type type, bool fullName = true, bool compilable = false) - { - var stringBuilder = new StringBuilder(); - ProcessType(stringBuilder, type, fullName, compilable); - return stringBuilder.ToString(); - } - - private static void ProcessType(StringBuilder builder, Type type, bool fullName, bool compilable) - { - if (type.IsGenericType) - { - var genericArguments = type.GetGenericArguments(); - ProcessGenericType(builder, type, genericArguments, genericArguments.Length, fullName, compilable); - } - else if (type.IsArray) - { - ProcessArrayType(builder, type, fullName, compilable); - } - else if (_builtInTypeNames.TryGetValue(type, out var builtInName)) - { - builder.Append(builtInName); - } - else if (!type.IsGenericParameter) - { - if (compilable) - { - if (type.IsNested) - { - ProcessType(builder, type.DeclaringType!, fullName, compilable); - builder.Append('.'); - } - else if (fullName) - { - builder.Append(type.Namespace).Append('.'); - } - - builder.Append(type.Name); - } - else - { - builder.Append(fullName ? type.FullName : type.Name); - } - } - } - - private static void ProcessArrayType(StringBuilder builder, Type type, bool fullName, bool compilable) - { - var innerType = type; - while (innerType.IsArray) - { - innerType = innerType.GetElementType()!; - } - - ProcessType(builder, innerType, fullName, compilable); - - while (type.IsArray) - { - builder.Append('['); - builder.Append(',', type.GetArrayRank() - 1); - builder.Append(']'); - type = type.GetElementType()!; - } - } - - private static void ProcessGenericType( - StringBuilder builder, - Type type, - Type[] genericArguments, - int length, - bool fullName, - bool compilable) - { - if (type.IsConstructedGenericType - && type.GetGenericTypeDefinition() == typeof(Nullable<>)) - { - ProcessType(builder, type.UnwrapNullableType(), fullName, compilable); - builder.Append('?'); - return; - } - - var offset = type.IsNested ? type.DeclaringType!.GetGenericArguments().Length : 0; - - if (compilable) - { - if (type.IsNested) - { - ProcessType(builder, type.DeclaringType!, fullName, compilable); - builder.Append('.'); - } - else if (fullName) - { - builder.Append(type.Namespace); - builder.Append('.'); - } - } - else - { - if (fullName) - { - if (type.IsNested) - { - ProcessGenericType(builder, type.DeclaringType!, genericArguments, offset, fullName, compilable); - builder.Append('+'); - } - else - { - builder.Append(type.Namespace); - builder.Append('.'); - } - } - } - - var genericPartIndex = type.Name.IndexOf('`'); - if (genericPartIndex <= 0) - { - builder.Append(type.Name); - return; - } - - builder.Append(type.Name, 0, genericPartIndex); - builder.Append('<'); - - for (var i = offset; i < length; i++) - { - ProcessType(builder, genericArguments[i], fullName, compilable); - if (i + 1 == length) - { - continue; - } - - builder.Append(','); - if (!genericArguments[i + 1].IsGenericParameter) - { - builder.Append(' '); - } - } - - builder.Append('>'); - } - - public static IEnumerable GetNamespaces(this Type type) - { - if (_builtInTypeNames.ContainsKey(type)) - { - yield break; - } - - yield return type.Namespace!; - - if (type.IsGenericType) - { - foreach (var typeArgument in type.GenericTypeArguments) - { - foreach (var ns in typeArgument.GetNamespaces()) - { - yield return ns; - } - } - } - } - - public static ConstantExpression GetDefaultValueConstant(this Type type) - => (ConstantExpression)_generateDefaultValueConstantMethod - .MakeGenericMethod(type).Invoke(null, Array.Empty())!; - - private static readonly MethodInfo _generateDefaultValueConstantMethod = - typeof(SharedTypeExtensions).GetTypeInfo().GetDeclaredMethod(nameof(GenerateDefaultValueConstant))!; - - private static ConstantExpression GenerateDefaultValueConstant() - => Expression.Constant(default(TDefault), typeof(TDefault)); - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/TenantContext.cs b/LingYanAspCoreFramework/MultiTenants/TenantContext.cs deleted file mode 100644 index 65093608c34f25158b8b9de8a8acc7679c5d3b4c..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/TenantContext.cs +++ /dev/null @@ -1,19 +0,0 @@ -锘縰sing ShardingCore.Core.RuntimeContexts; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class TenantContext - { - private readonly IShardingRuntimeContext _shardingRuntimeContext; - - public TenantContext(IShardingRuntimeContext shardingRuntimeContext) - { - _shardingRuntimeContext = shardingRuntimeContext; - } - - public IShardingRuntimeContext GetShardingRuntimeContext() - { - return _shardingRuntimeContext; - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/TenantContextAccessor.cs b/LingYanAspCoreFramework/MultiTenants/TenantContextAccessor.cs deleted file mode 100644 index 580da021c386c41a9e9f247b5377b587260c682e..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/TenantContextAccessor.cs +++ /dev/null @@ -1,13 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.MultiTenants -{ - public class TenantContextAccessor : ITenantContextAccessor - { - private static readonly AsyncLocal _tenantContext = new AsyncLocal(); - - public TenantContext? TenantContext - { - get => _tenantContext.Value; - set => _tenantContext.Value = value; - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/TenantExtension.cs b/LingYanAspCoreFramework/MultiTenants/TenantExtension.cs deleted file mode 100644 index feb6ee13836d2a86b10d1a2219471aaa9d67a907..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/TenantExtension.cs +++ /dev/null @@ -1,62 +0,0 @@ -锘縰sing LingYanAspCoreFramework.Attributes; -using LingYanAspCoreFramework.Models; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.DependencyInjection; -using Newtonsoft.Json; -using ShardingCore.Extensions; -using System.Collections; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public static class TenantExtension - { - public static void InitTenant(this IServiceProvider serviceProvider, RuntimeCacheModel lYBuilderRuntimeModel) - { - var tenantManager = serviceProvider.GetService(); - var shardingBuilder = serviceProvider.GetService(); - using (var scope = serviceProvider.CreateScope()) - { - if (lYBuilderRuntimeModel.ModuleDbContextList.Count > 0) - { - //澶氱鎴烽厤缃〃杩愯杩佺Щ - var configDbContextType = lYBuilderRuntimeModel.ModuleDbContextList.Where(pair => pair.Value == DbContextType.TenantConfigDbContext).Select(pair => pair.Key).FirstOrDefault(); - if (configDbContextType != null) - { - var configDbContext = (DbContext)scope.ServiceProvider.GetService(configDbContextType); - configDbContext.Database.Migrate(); - var SetMethod = configDbContext.GetType().GetMethods().FirstOrDefault(f => f.Name == "Set").MakeGenericMethod(lYBuilderRuntimeModel.ModuleTenantBaseEntitys["BaseSysOwnerTenantConfig"]); - var dbSet = SetMethod.Invoke(configDbContext, null); - var toListMethod = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(lYBuilderRuntimeModel.ModuleTenantBaseEntitys["BaseSysOwnerTenantConfig"]); - var sysUserTenantConfigs = toListMethod.Invoke(null, new object[] { dbSet }) as IEnumerable; - if (sysUserTenantConfigs != null) - { - foreach (dynamic sysUserTenantConfig in sysUserTenantConfigs) - { - var shardingTenantOptions = JsonConvert.DeserializeObject(sysUserTenantConfig.ConfigJson); - - var shardingRuntimeContext = shardingBuilder.Build(shardingTenantOptions); - - tenantManager.AddTenantSharding(sysUserTenantConfig.CompanyId, shardingRuntimeContext); - } - } - } - } - } - var tenantIds = tenantManager.GetAll(); - foreach (var tenantId in tenantIds) - { - using (tenantManager.CreateScope(tenantId)) - using (var scope = serviceProvider.CreateScope()) - { - var shardingRuntimeContext = tenantManager.GetCurrentTenantContext().GetShardingRuntimeContext(); - //寮鍚畾鏃朵换鍔 - //shardingRuntimeContext.UseAutoShardingCreate(); - var tenantDbContext = (DbContext)scope.ServiceProvider.GetService(lYBuilderRuntimeModel.TenantTemplateDbContexts.FirstOrDefault()); - tenantDbContext.Database.Migrate(); - //琛ュ伩琛 - shardingRuntimeContext.UseAutoTryCompensateTable(); - } - } - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/TenantManager.cs b/LingYanAspCoreFramework/MultiTenants/TenantManager.cs deleted file mode 100644 index 8986d40b6b38a1bd791c495bf8387a3dbd379c63..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/TenantManager.cs +++ /dev/null @@ -1,41 +0,0 @@ -锘縰sing ShardingCore.Core.RuntimeContexts; -using System.Collections.Concurrent; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class TenantManager : ITenantManager - { - private readonly ITenantContextAccessor _tenantContextAccessor; - private readonly ConcurrentDictionary _cache = new(); - - public TenantManager(ITenantContextAccessor tenantContextAccessor) - { - _tenantContextAccessor = tenantContextAccessor; - } - - public List GetAll() - { - return _cache.Keys.ToList(); - } - - public TenantContext GetCurrentTenantContext() - { - return _tenantContextAccessor.TenantContext; - } - - public bool AddTenantSharding(object tenantId, IShardingRuntimeContext shardingRuntimeContext) - { - return _cache.TryAdd(tenantId, shardingRuntimeContext); - } - - public TenantScope CreateScope(object tenantId) - { - if (!_cache.TryGetValue(tenantId, out var shardingRuntimeContext)) - { - throw new InvalidOperationException("鏈壘鍒板搴旂鎴风殑閰嶇疆"); - } - _tenantContextAccessor.TenantContext = new TenantContext(shardingRuntimeContext); - return new TenantScope(_tenantContextAccessor); - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/TenantScope.cs b/LingYanAspCoreFramework/MultiTenants/TenantScope.cs deleted file mode 100644 index a1149fe6976651009327b957a46e9c090bda5d51..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/TenantScope.cs +++ /dev/null @@ -1,17 +0,0 @@ -锘縩amespace LingYanAspCoreFramework.MultiTenants -{ - public class TenantScope : IDisposable - { - public TenantScope(ITenantContextAccessor tenantContextAccessor) - { - TenantContextAccessor = tenantContextAccessor; - } - - public ITenantContextAccessor TenantContextAccessor { get; } - - public void Dispose() - { - TenantContextAccessor.TenantContext = null; - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/MultiTenants/TenantSelectMiddleware.cs b/LingYanAspCoreFramework/MultiTenants/TenantSelectMiddleware.cs deleted file mode 100644 index fe208bf948a0995ab185ce05cf6e875395c16356..0000000000000000000000000000000000000000 --- a/LingYanAspCoreFramework/MultiTenants/TenantSelectMiddleware.cs +++ /dev/null @@ -1,59 +0,0 @@ -锘縰sing Microsoft.AspNetCore.Http; - -namespace LingYanAspCoreFramework.MultiTenants -{ - public class TenantSelectMiddleware - { - private readonly RequestDelegate _next; - private readonly ITenantManager _tenantManager; - - public TenantSelectMiddleware(RequestDelegate next, ITenantManager tenantManager) - { - _next = next; - _tenantManager = tenantManager; - } - - /// - /// 1.涓棿浠剁殑鏂规硶蹇呴』鍙獻nvoke锛屼笖涓簆ublic锛岄潪static銆 - /// 2.Invoke鏂规硶绗竴涓弬鏁板繀椤绘槸HttpContext绫诲瀷銆 - /// 3.Invoke鏂规硶蹇呴』杩斿洖Task銆 - /// 4.Invoke鏂规硶鍙互鏈夊涓弬鏁帮紝闄ttpContext澶栧叾瀹冨弬鏁颁細灏濊瘯浠庝緷璧栨敞鍏ュ鍣ㄤ腑鑾峰彇銆 - /// 5.Invoke鏂规硶涓嶈兘鏈夐噸杞姐 - /// - /// Author : Napoleon - /// Created : 2020/1/30 21:30 - public async Task Invoke(HttpContext context) - { - if (context.Request.Path.ToString().StartsWith(LingYanRuntimeManager.CommonConfigModel.TenantRoutePrefix.ToLower(), StringComparison.CurrentCultureIgnoreCase)) - { - if (!context.User.Identity.IsAuthenticated) - { - await _next(context); - return; - } - - var tenantId = context.User.Claims.FirstOrDefault((o) => o.Type == "uid")?.Value; - if (string.IsNullOrWhiteSpace(tenantId)) - { - await DoUnAuthorized(context, "not found tenant id"); - return; - } - - using (_tenantManager.CreateScope(tenantId)) - { - await _next(context); - } - } - else - { - await _next(context); - } - } - - private async Task DoUnAuthorized(HttpContext context, string msg) - { - context.Response.StatusCode = 403; - await context.Response.WriteAsync(msg); - } - } -} \ No newline at end of file diff --git a/LingYanAspCoreFramework/SampleRoots/SampleCommonExceptionMiddleware.cs b/LingYanAspCoreFramework/SampleRoots/SampleCommonExceptionMiddleware.cs index 885991ca4bfb6eb826e7f3953857b27af8c7c964..a8e66820f20347b70944d908a973048dcfe68b69 100644 --- a/LingYanAspCoreFramework/SampleRoots/SampleCommonExceptionMiddleware.cs +++ b/LingYanAspCoreFramework/SampleRoots/SampleCommonExceptionMiddleware.cs @@ -31,7 +31,7 @@ namespace LingYanAspCoreFramework.SampleRoots } else { - logger.LogError(LoggerHelper.ExcetionEvent,ex.StackTrace); + logger.LogError(LoggerHelper.ExcetionEvent,ex.Message); context.Response.StatusCode = StatusCodes.Status403Forbidden; context.Response.ContentType = "application/json"; await context.Response.WriteAsJsonAsync(new ResponceBody(40000, ex.Message)); diff --git a/LingYanAspCoreFramework/SampleRoots/SampleGeneralHelper.cs b/LingYanAspCoreFramework/SampleRoots/SampleGeneralHelper.cs index d47991ac695fe558838a4281ee0e2066bd8a3850..84c7984cb4d2e748be8b6f7b1cb433dbbac30ad0 100644 --- a/LingYanAspCoreFramework/SampleRoots/SampleGeneralHelper.cs +++ b/LingYanAspCoreFramework/SampleRoots/SampleGeneralHelper.cs @@ -57,7 +57,7 @@ namespace LingYanAspCoreFramework.SampleRoots int footerIndex = pem.IndexOf(footer); if (headerIndex == -1 || footerIndex == -1 || headerIndex >= footerIndex) { - throw new CommonException(new ResponceBody(60017)); + throw new CommonException(new ResponceBody(67000,"鎻愬彇鍏挜鍐呭澶辫触")); } // 鎻愬彇涓棿鐨勫瘑閽ラ儴鍒 string publicKey = pem.Substring(headerIndex, footerIndex - headerIndex).Trim(); @@ -78,7 +78,7 @@ namespace LingYanAspCoreFramework.SampleRoots int footerIndex = pem.IndexOf(footer); if (headerIndex == -1 || footerIndex == -1 || headerIndex >= footerIndex) { - throw new CommonException(new ResponceBody(60018)); + throw new CommonException(new ResponceBody(67000,"鎻愬彇绉侀挜鍐呭澶辫触")); } // 鎻愬彇涓棿鐨勫瘑閽ラ儴鍒 string publicKey = pem.Substring(headerIndex, footerIndex - headerIndex).Trim(); @@ -121,15 +121,15 @@ namespace LingYanAspCoreFramework.SampleRoots } catch (HttpRequestException ex) { - throw new CommonException(new ResponceBody(60023, ex.Message)); + throw new CommonException(new ResponceBody(61000, ex.Message)); } catch (IOException ex) { - throw new CommonException(new ResponceBody(60023, ex.Message)); + throw new CommonException(new ResponceBody(61000, ex.Message)); } catch (Exception ex) { - throw new CommonException(new ResponceBody(60023, ex.Message)); + throw new CommonException(new ResponceBody(61000, ex.Message)); } } } @@ -145,7 +145,7 @@ namespace LingYanAspCoreFramework.SampleRoots { if (httpDonwloadTasks == null || httpDonwloadTasks.Count == 0) { - throw new CommonException(new ResponceBody(60023, "鏂囦欢涓嬭浇浠诲姟鍒楄〃涓嶈兘涓虹┖鎴栨暟閲忎负0")); + throw new CommonException(new ResponceBody(61000, "鏂囦欢涓嬭浇浠诲姟鍒楄〃涓嶈兘涓虹┖鎴栨暟閲忎负0")); } long totalBytesReceived = 0; long totalBytesToReceive = 0; @@ -166,11 +166,11 @@ namespace LingYanAspCoreFramework.SampleRoots } catch (HttpRequestException ex) { - throw new CommonException(new ResponceBody(60023, $"鏃犳硶鑾峰彇鏂囦欢 {task.NetworkUrl} 鐨勫ぇ灏: {ex.Message}")); + throw new CommonException(new ResponceBody(61000, $"鏃犳硶鑾峰彇鏂囦欢 {task.NetworkUrl} 鐨勫ぇ灏: {ex.Message}")); } catch (Exception ex) { - throw new CommonException(new ResponceBody(60023, ex.Message)); + throw new CommonException(new ResponceBody(61000, ex.Message)); } } foreach (var task in httpDonwloadTasks) @@ -186,7 +186,7 @@ namespace LingYanAspCoreFramework.SampleRoots } catch (Exception ex) { - throw new CommonException(new ResponceBody(60023, $"涓嬭浇鏂囦欢 {task.NetworkUrl} 澶辫触: {ex.Message}")); + throw new CommonException(new ResponceBody(61000, $"涓嬭浇鏂囦欢 {task.NetworkUrl} 澶辫触: {ex.Message}")); } } } diff --git a/LingYanAspCoreFramework/SampleRoots/SampleGlobalAuthorizationFilterAttribute.cs b/LingYanAspCoreFramework/SampleRoots/SampleGlobalAuthorizationFilterAttribute.cs index a0ad1d0edf82f3b2ecc9da242661028dc83c9f4d..b93f97d9b6b3f022c5d436ed31b93cf23b4ad5f4 100644 --- a/LingYanAspCoreFramework/SampleRoots/SampleGlobalAuthorizationFilterAttribute.cs +++ b/LingYanAspCoreFramework/SampleRoots/SampleGlobalAuthorizationFilterAttribute.cs @@ -9,18 +9,17 @@ using Microsoft.Extensions.Logging; namespace LingYanAspCoreFramework.SampleRoots { - public class SampleGlobalAuthorizationFilterAttribute : Attribute, IAuthorizationFilter - where TBaseRole : BaseRole, new() - where TBaseRoute : BaseRoute, new() + public class SampleGlobalAuthorizationFilterAttribute : Attribute, IAsyncAuthorizationFilter + where TBaseRole : BaseRole, new() + where TBaseRoute : BaseRoute, new() { - public virtual async void OnAuthorization(AuthorizationFilterContext context) + public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { LoggerHelper.ResolveFilterLogger(context).LogDebug(LoggerHelper.AuthorEvent, "娓稿璁板綍"); context.HttpContext.Items[SampleHelper.ClaimLogStart] = DateTime.Now; - //閴村畾鏄惁鍏朵粬鍦版柟鐧诲綍 - var methodInfo = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo; // 棣栧厛妫鏌ユ柟娉曚笂鏄惁鏈塠AllowAnonymous]鐗规 - bool hasAllowAnonymousOnMethod = methodInfo.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any(); + bool hasAllowAnonymousOnMethod = (context.ActionDescriptor as ControllerActionDescriptor). + MethodInfo.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any(); // 濡傛灉鏂规硶涓婃病鏈夋壘鍒帮紝妫鏌ユ帶鍒跺櫒绾у埆 bool hasAllowAnonymousOnController = (context.ActionDescriptor as ControllerActionDescriptor). ControllerTypeInfo.GetCustomAttributes(typeof(AllowAnonymousAttribute), true).Any(); @@ -29,12 +28,12 @@ namespace LingYanAspCoreFramework.SampleRoots var userId = context.HttpContext.Items?.FirstOrDefault(f => f.Key == SampleHelper.ClaimUserId).Value?.ToString(); //鎶㈠崰鐧诲綍鐘舵 var requestHeaderToke = context.HttpContext.Request.Headers.FirstOrDefault(f => f.Key == "Authorization").Value.ToString(); - var redisToken =await RedisHelper.HGetAsync(SampleHelper.RedisUserToken, userId); + var redisToken = await RedisHelper.HGetAsync(SampleHelper.RedisUserToken, userId); if (!string.IsNullOrEmpty(requestHeaderToke) && !string.IsNullOrEmpty(redisToken)) { if (requestHeaderToke != redisToken) { - context.Result = new OkObjectResult(new ResponceBody(40001, "Token琚姠鍗犲凡鍒锋柊", null)); + context.Result = new OkObjectResult(new ResponceBody(41000, "Token琚姠鍗犲凡鍒锋柊", null)); return; } } @@ -43,20 +42,21 @@ namespace LingYanAspCoreFramework.SampleRoots await ValidateAuthor(context, requestUrl, userId); } } + public virtual async Task ValidateAuthor(AuthorizationFilterContext context, string requestUrl, string userId) { // 鑾峰彇鐢ㄦ埛鐨勬墍鏈夎鑹睮D鍒楄〃 - var userRolesJson =await RedisHelper.HGetAsync>(SampleHelper.RedisUserRole, userId); + var userRolesJson = await RedisHelper.HGetAsync>(SampleHelper.RedisUserRole, userId); if (userRolesJson == null || userRolesJson.Count == 0) { - context.Result = new OkObjectResult(new ResponceBody(40002, "瑙掕壊鏈垎閰", null)); + context.Result = new OkObjectResult(new ResponceBody(42000, "瑙掕壊鏈垎閰", null)); return; } // 鑾峰彇姣忎釜瑙掕壊鐨勮矾鐢变俊鎭苟鍚堝苟 var allRequestRoutes = new List(); foreach (var roleEntity in userRolesJson) { - var routeEntitys =await RedisHelper.HGetAsync>(SampleHelper.RedisRoleRoute, roleEntity.Id.ToString()); + var routeEntitys = await RedisHelper.HGetAsync>(SampleHelper.RedisRoleRoute, roleEntity.Id.ToString()); if (routeEntitys != null && routeEntitys.Count > 0) { allRequestRoutes.AddRange(routeEntitys); @@ -65,14 +65,14 @@ namespace LingYanAspCoreFramework.SampleRoots // 妫鏌ュ悎骞跺悗鐨勮矾鐢变俊鎭 if (allRequestRoutes == null || allRequestRoutes.Count == 0) { - context.Result = new OkObjectResult(new ResponceBody(40003, "鏉冮檺鏈垎閰", null)); + context.Result = new OkObjectResult(new ResponceBody(42000, "璺敱鏈垎閰", null)); return; } //鍒ゆ柇璺敱鏄惁鍦ㄨ鑹叉潈闄愬唴 var isInRole = allRequestRoutes.Any(a => a.RouteTemplate.ToLower().Equals(requestUrl)); if (!isInRole) { - context.Result = new OkObjectResult(new ResponceBody(40003, "鏉冮檺绾у埆涓嶈冻", null)); + context.Result = new OkObjectResult(new ResponceBody(42000, "鏉冮檺涓嶈冻", null)); return; } } diff --git a/LingYanAspCoreFramework/SampleRoots/SampleGlobalPermissionHandle.cs b/LingYanAspCoreFramework/SampleRoots/SampleGlobalPermissionHandle.cs index c6ee96f8acc4687531e3b3c7f90905145d5aabc8..11feab6691dcefc2ee0e705cab1e703c232f38a4 100644 --- a/LingYanAspCoreFramework/SampleRoots/SampleGlobalPermissionHandle.cs +++ b/LingYanAspCoreFramework/SampleRoots/SampleGlobalPermissionHandle.cs @@ -20,12 +20,12 @@ namespace LingYanAspCoreFramework.SampleRoots var userIdClaim = context.User.Claims.FirstOrDefault(f => f.Type == SampleHelper.ClaimUserId); if (userIdClaim == null) { - throw new CommonException(new ResponceBody(40001,"Token涓嶅睘浜庢湰绯荤粺")); + throw new CommonException(new ResponceBody(41000, "Token涓嶅睘浜庢湰绯荤粺")); } var userId = userIdClaim.Value.DecryptWithRSA(SampleHelper.RSAPrivateKey); if (string.IsNullOrEmpty(userId)) { - throw new CommonException(new ResponceBody(40001,"Token濂藉儚琚鏀")); + throw new CommonException(new ResponceBody(41000, "Token濂藉儚琚鏀")); } else { diff --git a/LingYanAspCoreFramework/SampleRoots/SampleQrCodeHelper.cs b/LingYanAspCoreFramework/SampleRoots/SampleQrCodeHelper.cs new file mode 100644 index 0000000000000000000000000000000000000000..f37bcf299a8022221506d797419335624e9cf8fa --- /dev/null +++ b/LingYanAspCoreFramework/SampleRoots/SampleQrCodeHelper.cs @@ -0,0 +1,190 @@ +锘縰sing SkiaSharp; +using SkiaSharp.QrCode; +using System.Text; + +namespace LingYanAspCoreFramework.SampleRoots +{ + class SampleQrCodeHelper + { + public class QRCodeConfig + { + public string Text { get; set; } = default!; + public int Width { get; set; } + public int Height { get; set; } + public byte[]? LogoImgae { get; set; } + public int KeepWhiteBorderPixelVal { get; set; } = 0; + public string BackgroundColor { get; set; } = "ffffff"; + public string CodeColor { get; set; } = "000000"; + } + public static byte[] CreateQRCode(string content, int width, int hight) + { + using var generator = new QRCodeGenerator(); + var qr = generator.CreateQrCode(content, ECCLevel.H); + var info = new SKImageInfo(width, hight); + using var surface = SKSurface.Create(info); + var canvas = surface.Canvas; + canvas.Render(qr, info.Width, info.Height); + using var image = surface.Snapshot(); + using var data = image.Encode(SKEncodedImageFormat.Png, 100); + return data.ToArray(); + } + public static byte[] CreateLogoQRCode(QRCodeConfig qRCodeConfig) + { + qRCodeConfig.Text = qRCodeConfig.Text ?? throw new ArgumentNullException(nameof(qRCodeConfig)); + var keepWhiteBorderPixelVal = qRCodeConfig.KeepWhiteBorderPixelVal is >= -1 and < 10 ? qRCodeConfig.KeepWhiteBorderPixelVal : -1; + var width = qRCodeConfig.Width is > 100 and < 1200 ? qRCodeConfig.Width : 500; + var height = qRCodeConfig.Height is > 100 and < 1200 ? qRCodeConfig.Height : 500; ; + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + var qRCodeWriter = new ZXing.QrCode.QRCodeWriter(); + var hints = new Dictionary + { + { ZXing.EncodeHintType.CHARACTER_SET, "UTF-8" }, + { ZXing.EncodeHintType.QR_VERSION, 8 }, + { ZXing.EncodeHintType.ERROR_CORRECTION, ZXing.QrCode.Internal.ErrorCorrectionLevel.H } + }; + var bitMatrix = qRCodeWriter.encode(qRCodeConfig.Text, ZXing.BarcodeFormat.QR_CODE, width, height, hints); + var w = bitMatrix.Width; + var h = bitMatrix.Height; + var sKBitmap = new SKBitmap(w, h); + var blackStartPointX = 0; + var blackStartPointY = 0; + var blackEndPointX = w; + var blackEndPointY = h; + using var sKCanvas = new SKCanvas(sKBitmap); + var sKColorBlack = SKColor.Parse(qRCodeConfig.CodeColor); + var sKColorWihte = SKColor.Parse(qRCodeConfig.BackgroundColor); + sKCanvas.Clear(sKColorWihte); + var blackStartPointIsNotWriteDown = true; + for (var y = 0; y < h; y++) + { + for (var x = 0; x < w; x++) + { + var flag = bitMatrix[x, y]; + if (flag) + { + if (blackStartPointIsNotWriteDown) + { + blackStartPointX = x; + blackStartPointY = y; + blackStartPointIsNotWriteDown = false; + } + blackEndPointX = x; + blackEndPointY = y; + sKCanvas.DrawPoint(x, y, sKColorBlack); + } + else + { + sKCanvas.DrawPoint(x, y, sKColorWihte); + } + } + } + var qrcodeRealWidth = blackEndPointX - blackStartPointX; + var qrcodeRealHeight = blackEndPointY - blackStartPointY; + if (keepWhiteBorderPixelVal > -1) + { + var borderMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / 10); + if (keepWhiteBorderPixelVal > borderMaxWidth) + { + keepWhiteBorderPixelVal = borderMaxWidth; + } + var nQrcodeRealWidth = width - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal; + var nQrcodeRealHeight = height - keepWhiteBorderPixelVal - keepWhiteBorderPixelVal; + + var sKBitmap2 = new SKBitmap(width, height); + var sKCanvas2 = new SKCanvas(sKBitmap2); + sKCanvas2.Clear(sKColorWihte); + sKCanvas2.DrawBitmap( + sKBitmap, + new SKRect + { + Location = new SKPoint { X = blackStartPointX, Y = blackStartPointY }, + Size = new SKSize { Height = qrcodeRealHeight, Width = qrcodeRealWidth } + }, + new SKRect + { + Location = new SKPoint { X = keepWhiteBorderPixelVal, Y = keepWhiteBorderPixelVal }, + Size = new SKSize { Width = nQrcodeRealWidth, Height = nQrcodeRealHeight } + }); + + blackStartPointX = keepWhiteBorderPixelVal; + blackStartPointY = keepWhiteBorderPixelVal; + qrcodeRealWidth = nQrcodeRealWidth; + qrcodeRealHeight = nQrcodeRealHeight; + + sKCanvas2.Dispose(); + sKBitmap.Dispose(); + sKBitmap = sKBitmap2; + } + if (qRCodeConfig is { LogoImgae.Length: > 0 }) + { + using SKBitmap sKBitmapLogo = SKBitmap.Decode(qRCodeConfig.LogoImgae); + if (!sKBitmapLogo.IsEmpty) + { + using var sKPaint2 = new SKPaint + { + FilterQuality = SKFilterQuality.None, + IsAntialias = true + }; + var logoTargetMaxWidth = (int)Math.Floor((double)qrcodeRealWidth / 6); + var logoTargetMaxHeight = (int)Math.Floor((double)qrcodeRealHeight / 6); + var qrcodeCenterX = (int)Math.Floor((double)qrcodeRealWidth / 2); + var qrcodeCenterY = (int)Math.Floor((double)qrcodeRealHeight / 2); + var logoResultWidth = sKBitmapLogo.Width; + var logoResultHeight = sKBitmapLogo.Height; + if (logoResultWidth > logoTargetMaxWidth) + { + var r = (double)logoTargetMaxWidth / logoResultWidth; + logoResultWidth = logoTargetMaxWidth; + logoResultHeight = (int)Math.Floor(logoResultHeight * r); + } + if (logoResultHeight > logoTargetMaxHeight) + { + var r = (double)logoTargetMaxHeight / logoResultHeight; + logoResultHeight = logoTargetMaxHeight; + logoResultWidth = (int)Math.Floor(logoResultWidth * r); + } + var pointX = qrcodeCenterX - (int)Math.Floor((double)logoResultWidth / 2) + blackStartPointX; + var pointY = qrcodeCenterY - (int)Math.Floor((double)logoResultHeight / 2) + blackStartPointY; + + using var sKCanvas3 = new SKCanvas(sKBitmap); + using var sKPaint = new SKPaint + { + FilterQuality = SKFilterQuality.Medium, + IsAntialias = true + }; + sKCanvas3.DrawBitmap( + sKBitmapLogo, + new SKRect + { + Location = new SKPoint { X = 0, Y = 0 }, + Size = new SKSize { Height = sKBitmapLogo.Height, Width = sKBitmapLogo.Width } + }, + new SKRect + { + Location = new SKPoint { X = pointX, Y = pointY }, + Size = new SKSize { Height = logoResultHeight, Width = logoResultWidth } + }, sKPaint); + } + } + using SKImage sKImage = SKImage.FromBitmap(sKBitmap); + sKBitmap.Dispose(); + using var data = sKImage.Encode(SKEncodedImageFormat.Png, 100); + return data.ToArray(); + } + public static byte[] ConvertImageToByteArray(string imagePath, SKEncodedImageFormat format = SKEncodedImageFormat.Png, int quality = 100) + { + // 鍔犺浇鍥剧墖 + using (SKBitmap skBitmap = SKBitmap.Decode(imagePath)) + { + // 鍒涘缓涓涓唴瀛樻祦鏉ヤ繚瀛樼紪鐮佸悗鐨勫浘鍍 + using (var memoryStream = new MemoryStream()) + { + // 灏嗗浘鐗囩紪鐮佷负鎸囧畾鏍煎紡 + skBitmap.Encode(memoryStream, format, quality); + // 灏嗗唴瀛樻祦杞崲涓哄瓧鑺傛暟缁 + return memoryStream.ToArray(); + } + } + } + } +} diff --git a/LingYanAspCoreFramework/WeChatDevs/WeChatDevService.cs b/LingYanAspCoreFramework/WeChatDevs/WeChatDevService.cs index 01e0e7ebdacb122788e887a448bd8dcc66ebbb58..325b4a2df1700a5509c4f93e0f3c4f8678de928a 100644 --- a/LingYanAspCoreFramework/WeChatDevs/WeChatDevService.cs +++ b/LingYanAspCoreFramework/WeChatDevs/WeChatDevService.cs @@ -10,10 +10,10 @@ namespace LingYanAspCoreFramework.WeChatDevs { public class WeChatDevService : IWeChatDevService { - private readonly LingYanHttpClient lingYanHttpClient; + private readonly PollyHttpClient lingYanHttpClient; private readonly IOptions options; - public WeChatDevService(LingYanHttpClient lingYanHttpClient, IOptions options) + public WeChatDevService(PollyHttpClient lingYanHttpClient, IOptions options) { this.lingYanHttpClient = lingYanHttpClient; this.options = options; diff --git a/README.en.md b/README.en.md deleted file mode 100644 index b0e441fce249adf782a2f72a2994ba500c9764bd..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# LingYan_ASPFramework - -#### Description -閫傜敤浜嶢sp.Net Core鐨勫悗绔鏋 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index 4b7d11519d36a235d04e37b37434ade71540222b..ef45762eecd4a883686aaf0afa2dead4b7aa490d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,26 @@ -# LingYan_ASPFramework +# LingYanASPFramework -#### 浠嬬粛 -閫傜敤浜嶢sp.Net Core鐨勫悗绔鏋 +#### 妗嗘灦绠浠 + +##### 浜ゆ祦瀛︿範 + +QQ缇わ細571927325锛屽井淇★細13028792031 + +##### 鍏充簬LingYanAspCoreFramework + +璇ユ鏋剁敱.NET棰嗗煙寮鍙戜汉鍛-鍙告櫒鑰佸笀-寮鍙戯紝閫傚簲浜嶤#绯诲垪鍚勭鏂瑰悜锛岄噰鐢―DD棰嗗煙椹卞姩鎬濇兂锛岀壒鎬ц嚜鍔ㄦ敞鍏ユ湇鍔℃浛浠f墜鍐欐敞鍏ユ湇鍔★紝妯″潡鍖栧熀绫讳繚璇佹瘡涓灞傞兘鍙互杩涜鑷畾涔夋墿灞曠殑鏈嶅姟娉ㄥ叆鍜屾湇鍔″垵濮嬪寲锛岄拡瀵笶FCore灏佽甯歌浣跨敤鐨勫伐浣滃崟鍏冧笌浠撳偍鍙婂垎椤靛姛鑳斤紝鑷爺鍩轰簬EFCore鐨勫姩鎬佸垎搴撳垎妯″紡鍒嗚〃妗嗘灦浠ラ傚簲澶ф暟鎹満鏅佸绉熸埛鍦烘櫙銆 + +瀹樼綉锛歔鐏电嚂绌洪棿瀹樼綉](https://www.lingyanspace.com/) + +B绔欙細[鐏电嚂绌洪棿B绔橾(https://space.bilibili.com/237905456) + +鍗氬锛歔鐏电嚂绌洪棿鍗氬](https://book.lingyanspace.com/) #### 浣跨敤璇存槑 + 1銆佹ā鍧楀寲娉ㄥ叆锛屾ā鍧楀唴绫诲簲褰撶户鎵緽aseModule锛屾鎶借薄绫绘湁涓夌褰㈠紡 BaseModule绫诲瀷 + ``` public class RESTApiModule : BaseModule {