From 9133eae4e0dd307d7d87e1900d3acd4af10d5ebc Mon Sep 17 00:00:00 2001
From: HuiJiOnGit <40553940+HuiJiOnGit@users.noreply.github.com>
Date: Thu, 21 Jan 2021 17:18:10 +0800
Subject: [PATCH 001/190] Update .gitignore
Add.vscode ignores folders
---
.gitignore | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.gitignore b/.gitignore
index 9a7ee7a9..5ac1fe08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,6 +35,9 @@ bld/
# Visual Studio 2017 auto generated files
Generated\ Files/
+# Visual Studio Code
+.vscode
+
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
From ff03c4a462459b4523cae744b5c3a58004486355 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 17 Jan 2023 17:00:31 +0800
Subject: [PATCH 002/190] feat:update to net 7.0
---
Blog.Core.Api/Blog.Core.Api.csproj | 14 ++++-----
Blog.Core.Api/Program.cs | 12 ++------
Blog.Core.Common/Blog.Core.Common.csproj | 20 ++++++-------
Blog.Core.Common/Helper/SM/SM4.cs | 1 -
Blog.Core.EventBus/Blog.Core.EventBus.csproj | 10 +++----
.../Blog.Core.Extensions.csproj | 30 +++++++++----------
.../Middlewares/RequRespLogMiddleware.cs | 1 -
.../ServiceExtensions/HttpRuntimeCache.cs | 3 +-
.../Blog.Core.FrameWork.csproj | 2 +-
Blog.Core.Gateway/Blog.Core.Gateway.csproj | 10 +++----
.../Blog.Core.IServices.csproj | 2 +-
Blog.Core.Model/Blog.Core.Model.csproj | 8 ++---
Blog.Core.Publish.Docker.Jenkins.sh | 2 +-
Blog.Core.Publish.bat | 4 +--
.../Blog.Core.Repository.csproj | 8 ++---
.../Blog.Core.Serilog.Es.csproj | 14 ++++-----
Blog.Core.Services/Blog.Core.Services.csproj | 2 +-
Blog.Core.Tasks/Blog.Core.Tasks.csproj | 4 +--
Blog.Core.Tests/Blog.Core.Tests.csproj | 6 ++--
.../Ocelot.Provider.Nacos.csproj | 12 ++++----
20 files changed, 78 insertions(+), 87 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 38575a55..9016c427 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -4,7 +4,7 @@
Exe
- net6.0
+ net7.0
enable
Linux
@@ -49,13 +49,13 @@
-
-
+
+
-
-
-
-
+
+
+
+
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index b3bf2387..6f4cf041 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -13,7 +13,6 @@
using Blog.Core.Hubs;
using Blog.Core.IServices;
using Blog.Core.Tasks;
-using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
@@ -170,15 +169,8 @@
app.UseMiniProfilerMiddleware();
//app.UseExceptionHandlerMidd();
-app.UseEndpoints(endpoints =>
-{
- endpoints.MapControllerRoute(
- name: "default",
- pattern: "{controller=Home}/{action=Index}/{id?}");
-
- endpoints.MapHub("/api2/chatHub");
-});
-
+app.MapControllers();
+app.MapHub("/api2/chatHub");
var scope = app.Services.GetRequiredService().CreateScope();
var myContext = scope.ServiceProvider.GetRequiredService();
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index 43f65ab9..b3d20137 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
@@ -16,21 +16,21 @@
-
-
+
+
-
-
+
+
-
+
-
-
+
+
-
-
+
+
diff --git a/Blog.Core.Common/Helper/SM/SM4.cs b/Blog.Core.Common/Helper/SM/SM4.cs
index 4b1f1996..e0984558 100644
--- a/Blog.Core.Common/Helper/SM/SM4.cs
+++ b/Blog.Core.Common/Helper/SM/SM4.cs
@@ -207,7 +207,6 @@ public SByte[] sm4_crypt_ecb(SM4_Context ctx, SByte[] input)
int length = input.Length;
SByte[] bins = new SByte[length];
SByte[] bous = new SByte[length];
- SByte[] output = null;
Array.Copy(input, 0, bins, 0, length);
diff --git a/Blog.Core.EventBus/Blog.Core.EventBus.csproj b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
index 070c0a48..bb75b1b0 100644
--- a/Blog.Core.EventBus/Blog.Core.EventBus.csproj
+++ b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
@@ -1,20 +1,20 @@
- net6.0
+ net7.0
-
+
-
+
-
+
-
+
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index aca15b55..3323fd2b 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -1,35 +1,35 @@
- net6.0
+ net7.0
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
+
diff --git a/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs b/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs
index 6ff8d044..4c61ed3b 100644
--- a/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs
@@ -7,7 +7,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
-using Ubiety.Dns.Core.Common;
namespace Blog.Core.Extensions.Middlewares
{
diff --git a/Blog.Core.Extensions/ServiceExtensions/HttpRuntimeCache.cs b/Blog.Core.Extensions/ServiceExtensions/HttpRuntimeCache.cs
index b9b4d7b3..ac7713f6 100644
--- a/Blog.Core.Extensions/ServiceExtensions/HttpRuntimeCache.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/HttpRuntimeCache.cs
@@ -38,7 +38,8 @@ public V Get(string key)
public IEnumerable GetAllKey()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
- var entries = _memoryCache.GetType().GetField("_entries", flags).GetValue(_memoryCache);
+ var coherentState = _memoryCache.GetType().GetField("_coherentState", flags).GetValue(_memoryCache);
+ var entries = coherentState.GetType().GetField("_entries", flags).GetValue(coherentState);
var cacheItems = entries as IDictionary;
var keys = new List();
if (cacheItems == null) return keys;
diff --git a/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj b/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj
index b167521c..4f60a46d 100644
--- a/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj
+++ b/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
diff --git a/Blog.Core.Gateway/Blog.Core.Gateway.csproj b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
index 47398520..819eaa36 100644
--- a/Blog.Core.Gateway/Blog.Core.Gateway.csproj
+++ b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
@@ -15,13 +15,13 @@
-
-
-
+
+
+
-
+
diff --git a/Blog.Core.IServices/Blog.Core.IServices.csproj b/Blog.Core.IServices/Blog.Core.IServices.csproj
index 820e1511..8ccfcc2f 100644
--- a/Blog.Core.IServices/Blog.Core.IServices.csproj
+++ b/Blog.Core.IServices/Blog.Core.IServices.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
diff --git a/Blog.Core.Model/Blog.Core.Model.csproj b/Blog.Core.Model/Blog.Core.Model.csproj
index de7e6467..120f3222 100644
--- a/Blog.Core.Model/Blog.Core.Model.csproj
+++ b/Blog.Core.Model/Blog.Core.Model.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
@@ -16,9 +16,9 @@
-
-
-
+
+
+
diff --git a/Blog.Core.Publish.Docker.Jenkins.sh b/Blog.Core.Publish.Docker.Jenkins.sh
index 3c561c67..d82c2d2f 100644
--- a/Blog.Core.Publish.Docker.Jenkins.sh
+++ b/Blog.Core.Publish.Docker.Jenkins.sh
@@ -4,7 +4,7 @@ cd Blog.Core.Api
dotnet publish
echo "Successfully!!!! ^ please see the file ."
-cd bin/Debug/net6.0/publish/
+cd bin/Debug/net7.0/publish/
#rm -f appsettings.json
#\cp -rf /var/jenkins_home/workspace/SecurityConfig/Blog.Core/appsettings.json appsettings.json
diff --git a/Blog.Core.Publish.bat b/Blog.Core.Publish.bat
index f022508d..cebbbf58 100644
--- a/Blog.Core.Publish.bat
+++ b/Blog.Core.Publish.bat
@@ -8,11 +8,11 @@ dotnet build
cd Blog.Core.Api
-dotnet publish -o ..\Blog.Core.Api\bin\Debug\net6.0\
+dotnet publish -o ..\Blog.Core.Api\bin\Debug\net7.0\
md ..\.PublishFiles
-xcopy ..\Blog.Core.Api\bin\Debug\net6.0\*.* ..\.PublishFiles\ /s /e
+xcopy ..\Blog.Core.Api\bin\Debug\net7.0\*.* ..\.PublishFiles\ /s /e
echo "Successfully!!!! ^ please see the file .PublishFiles"
diff --git a/Blog.Core.Repository/Blog.Core.Repository.csproj b/Blog.Core.Repository/Blog.Core.Repository.csproj
index 5c9764b0..3547007f 100644
--- a/Blog.Core.Repository/Blog.Core.Repository.csproj
+++ b/Blog.Core.Repository/Blog.Core.Repository.csproj
@@ -1,14 +1,14 @@
- net6.0
+ net7.0
-
-
-
+
+
+
diff --git a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
index 5cf82020..d98cfafb 100644
--- a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
+++ b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
@@ -1,17 +1,17 @@
- net6.0
+ net7.0
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/Blog.Core.Services/Blog.Core.Services.csproj b/Blog.Core.Services/Blog.Core.Services.csproj
index ae5e969a..fbfa7bbc 100644
--- a/Blog.Core.Services/Blog.Core.Services.csproj
+++ b/Blog.Core.Services/Blog.Core.Services.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
diff --git a/Blog.Core.Tasks/Blog.Core.Tasks.csproj b/Blog.Core.Tasks/Blog.Core.Tasks.csproj
index 5e173559..968fb795 100644
--- a/Blog.Core.Tasks/Blog.Core.Tasks.csproj
+++ b/Blog.Core.Tasks/Blog.Core.Tasks.csproj
@@ -1,11 +1,11 @@
- net6.0
+ net7.0
-
+
diff --git a/Blog.Core.Tests/Blog.Core.Tests.csproj b/Blog.Core.Tests/Blog.Core.Tests.csproj
index 2ceef163..fd488226 100644
--- a/Blog.Core.Tests/Blog.Core.Tests.csproj
+++ b/Blog.Core.Tests/Blog.Core.Tests.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
false
false
@@ -19,8 +19,8 @@
-
-
+
+
all
diff --git a/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj b/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj
index c713416a..23fd3e3d 100644
--- a/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj
+++ b/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj
@@ -1,7 +1,7 @@
- net6.0
+ net7.0
softlgl
softlgl
https://github.com/softlgl/Ocelot.Provider.Nacos
@@ -11,10 +11,10 @@
-
-
-
-
-
+
+
+
+
+
From 8d1c0bde1480da0ffe1b1565990bb18c679b86ad Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 17 Jan 2023 19:04:36 +0800
Subject: [PATCH 003/190] Update Dockerfile
---
Dockerfile | 18 +++++++++++-------
1 file changed, 11 insertions(+), 7 deletions(-)
diff --git a/Dockerfile b/Dockerfile
index 95bdaf92..69a3d132 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,28 +5,32 @@
#如果你想先手动dotnet build成可执行的二进制文件,然后再构建镜像,请看.Api层下的dockerfile。
-FROM mcr.microsoft.com/dotnet/aspnet:6.0-bullseye-slim AS base
+#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
+
+FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base
WORKDIR /app
EXPOSE 80
-FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim AS build
+FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build
WORKDIR /src
COPY ["Blog.Core.Api/Blog.Core.Api.csproj", "Blog.Core.Api/"]
COPY ["Blog.Core.Extensions/Blog.Core.Extensions.csproj", "Blog.Core.Extensions/"]
-COPY ["Blog.Core.Tasks/Blog.Core.Tasks.csproj", "Blog.Core.Tasks/"]
-COPY ["Blog.Core.IServices/Blog.Core.IServices.csproj", "Blog.Core.IServices/"]
-COPY ["Blog.Core.Model/Blog.Core.Model.csproj", "Blog.Core.Model/"]
+COPY ["Blog.Core.EventBus/Blog.Core.EventBus.csproj", "Blog.Core.EventBus/"]
COPY ["Blog.Core.Common/Blog.Core.Common.csproj", "Blog.Core.Common/"]
+COPY ["Blog.Core.Model/Blog.Core.Model.csproj", "Blog.Core.Model/"]
+COPY ["Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj", "Blog.Core.Serilog.Es/"]
+COPY ["Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj", "Ocelot.Provider.Nacos/"]
COPY ["Blog.Core.Services/Blog.Core.Services.csproj", "Blog.Core.Services/"]
+COPY ["Blog.Core.IServices/Blog.Core.IServices.csproj", "Blog.Core.IServices/"]
COPY ["Blog.Core.Repository/Blog.Core.Repository.csproj", "Blog.Core.Repository/"]
-COPY ["Blog.Core.EventBus/Blog.Core.EventBus.csproj", "Blog.Core.EventBus/"]
+COPY ["Blog.Core.Tasks/Blog.Core.Tasks.csproj", "Blog.Core.Tasks/"]
RUN dotnet restore "Blog.Core.Api/Blog.Core.Api.csproj"
COPY . .
WORKDIR "/src/Blog.Core.Api"
RUN dotnet build "Blog.Core.Api.csproj" -c Release -o /app/build
FROM build AS publish
-RUN dotnet publish "Blog.Core.Api.csproj" -c Release -o /app/publish
+RUN dotnet publish "Blog.Core.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
From 2dd3ed1e02bbe34c07e714780f4045a4dc37d8bb Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 17 Jan 2023 19:06:07 +0800
Subject: [PATCH 004/190] Update dotnetcore.yml
---
.github/workflows/dotnetcore.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml
index faa57fc4..2dd1ed9c 100644
--- a/.github/workflows/dotnetcore.yml
+++ b/.github/workflows/dotnetcore.yml
@@ -12,7 +12,7 @@ jobs:
- name: Setup .NET Core
uses: actions/setup-dotnet@v1
with:
- dotnet-version: 6.0.x
+ dotnet-version: 7.0.x
- name: Build with dotnet
run: dotnet build --configuration Release
- name: Build image
From 509208737997c6e3d6de193132ca386b635cb042 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 29 Jan 2023 09:39:18 +0800
Subject: [PATCH 005/190] feat: change sqlsugar column to postpresql
---
Blog.Core.Model/Models/AccessTrendLog.cs | 2 +-
Blog.Core.Model/Models/GblLogAudit.cs | 18 +++++++++---------
Blog.Core.Model/Models/sysUserInfo.cs | 2 +-
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/Blog.Core.Model/Models/AccessTrendLog.cs b/Blog.Core.Model/Models/AccessTrendLog.cs
index 0bad6836..4a87b13e 100644
--- a/Blog.Core.Model/Models/AccessTrendLog.cs
+++ b/Blog.Core.Model/Models/AccessTrendLog.cs
@@ -11,7 +11,7 @@ public class AccessTrendLog : RootEntityTkey
///
/// 用户
///
- [SugarColumn(Length = 128, IsNullable = true, ColumnDataType = "nvarchar")]
+ [SugarColumn(Length = 128, IsNullable = true)]
public string User { get; set; }
///
diff --git a/Blog.Core.Model/Models/GblLogAudit.cs b/Blog.Core.Model/Models/GblLogAudit.cs
index 58e04dd6..4b1bd9cd 100644
--- a/Blog.Core.Model/Models/GblLogAudit.cs
+++ b/Blog.Core.Model/Models/GblLogAudit.cs
@@ -18,52 +18,52 @@ public class GblLogAudit
///
///HttpContext.TraceIdentifier 事件链路ID(获取或设置一个唯一标识符,用于在跟踪日志中表示此请求。)
///
- [SugarColumn(ColumnDescription = "事件链路ID", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "varchar", Length = 255)]
+ [SugarColumn(ColumnDescription = "事件链路ID", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 255)]
public string TraceId { get; set; }
///
///时间
///
- [SugarColumn(ColumnDescription = "时间", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "datetime")]
+ [SugarColumn(ColumnDescription = "时间", IsNullable = false, IsPrimaryKey = false, IsIdentity = false)]
public DateTime Date { get; set; } = DateTime.Now;
///
///线程
///
- [SugarColumn(ColumnDescription = "线程", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "varchar", Length = 255)]
+ [SugarColumn(ColumnDescription = "线程", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 255)]
public string Thread { get; set; }
///
///等级
///
- [SugarColumn(ColumnDescription = "等级", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "varchar", Length = 255)]
+ [SugarColumn(ColumnDescription = "等级", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 255)]
public string Level { get; set; }
///
///记录器
///
- [SugarColumn(ColumnDescription = "记录器", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "varchar", Length = 255)]
+ [SugarColumn(ColumnDescription = "记录器", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 255)]
public string Logger { get; set; }
///
///日志类型
///
- [SugarColumn(ColumnDescription = "日志类型", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "varchar", Length = 255)]
+ [SugarColumn(ColumnDescription = "日志类型", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 255)]
public string LogType { get; set; }
///
///数据类型
///
- [SugarColumn(ColumnDescription = "数据类型", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "varchar", Length = 255)]
+ [SugarColumn(ColumnDescription = "数据类型", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 255)]
public string DataType { get; set; }
///
///错误信息
///
- [SugarColumn(ColumnDescription = "错误信息", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "text")]
+ [SugarColumn(ColumnDescription = "错误信息", IsNullable = false, IsPrimaryKey = false, IsIdentity = false, Length = 5000)]
public string Message { get; set; }
///
///异常
///
- [SugarColumn(ColumnDescription = "异常", IsNullable = true, IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "text")]
+ [SugarColumn(ColumnDescription = "异常", IsNullable = true, IsPrimaryKey = false, IsIdentity = false, Length = 5000)]
public string Exception { get; set; }
}
diff --git a/Blog.Core.Model/Models/sysUserInfo.cs b/Blog.Core.Model/Models/sysUserInfo.cs
index 8aafb164..c60e4bce 100644
--- a/Blog.Core.Model/Models/sysUserInfo.cs
+++ b/Blog.Core.Model/Models/sysUserInfo.cs
@@ -33,7 +33,7 @@ public SysUserInfo(string loginName, string loginPWD)
///
[SugarColumn(Length = 200, IsNullable = true, ColumnDescription = "登录账号")]
//:eg model 根据sqlsugar的完整定义可以如下定义,ColumnDescription可定义表字段备注
- //[SugarColumn(IsNullable = false, ColumnDescription = "登录账号", IsPrimaryKey = false, IsIdentity = false, ColumnDataType = "nvarchar", Length = 50)]
+ //[SugarColumn(IsNullable = false, ColumnDescription = "登录账号", IsPrimaryKey = false, IsIdentity = false, Length = 50)]
//ColumnDescription 表字段备注, 已在MSSQL测试,配合 [SugarTable("SysUserInfo", "用户表")]//('数据库表名','数据库表备注')
//可以完整生成 表备注和各个字段的中文备注
//2022/10/11
From a30f18499682fd8e4e2b433a122a8b81cd94451d Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 29 Jan 2023 16:19:30 +0800
Subject: [PATCH 006/190] feat: add authing sso
---
Blog.Core.Api/Program.cs | 6 ++-
Blog.Core.Api/appsettings.json | 6 +++
Blog.Core.Common/GlobalVar/GlobalVars.cs | 6 +++
.../Blog.Core.Extensions.csproj | 3 +-
.../Authentication_AuthingSetup.cs | 53 +++++++++++++++++++
5 files changed, 71 insertions(+), 3 deletions(-)
create mode 100644 Blog.Core.Extensions/ServiceExtensions/Authentication_AuthingSetup.cs
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index b3bf2387..7a9a25c0 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -56,6 +56,7 @@
builder.Services.AddUiFilesZipSetup(builder.Environment);
Permissions.IsUseIds4 = AppSettings.app(new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool();
+Permissions.IsUseAuthing = AppSettings.app(new string[] { "Startup", "Authing", "Enabled" }).ObjToBool();
RoutePrefix.Name = AppSettings.app(new string[] { "AppSettings", "SvcName" }).ObjToString();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
@@ -79,9 +80,10 @@
builder.Services.AddNacosSetup(builder.Configuration);
builder.Services.AddAuthorizationSetup();
-if (Permissions.IsUseIds4)
+if (Permissions.IsUseIds4 || Permissions.IsUseAuthing)
{
- builder.Services.AddAuthentication_Ids4Setup();
+ if (Permissions.IsUseIds4) builder.Services.AddAuthentication_Ids4Setup();
+ else if (Permissions.IsUseAuthing) builder.Services.AddAuthentication_AuthingSetup();
}
else
{
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 2adeb137..d639a62e 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -189,6 +189,12 @@
"AuthorizationUrl": "http://localhost:5004", // 认证中心域名
"ApiName": "blog.core.api" // 资源服务器
},
+ "Authing": {
+ "Enabled": true,
+ "Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
+ "Audience": "63d51c4205c2849803be5178",
+ "JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
+ },
"RedisMq": {
"Enabled": false //redis 消息队列
},
diff --git a/Blog.Core.Common/GlobalVar/GlobalVars.cs b/Blog.Core.Common/GlobalVar/GlobalVars.cs
index cb281e26..84dd9e19 100644
--- a/Blog.Core.Common/GlobalVar/GlobalVars.cs
+++ b/Blog.Core.Common/GlobalVar/GlobalVars.cs
@@ -20,6 +20,12 @@ public static class Permissions
/// true:表示启动IDS4
/// false:表示使用JWT
public static bool IsUseIds4 = false;
+
+ ///
+ /// 当前项目是否启用Authing权限方案
+ /// true:表示启动
+ /// false:表示使用JWT
+ public static bool IsUseAuthing = false;
}
///
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index aca15b55..50969b05 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -11,7 +11,7 @@
-
+
@@ -20,6 +20,7 @@
+
diff --git a/Blog.Core.Extensions/ServiceExtensions/Authentication_AuthingSetup.cs b/Blog.Core.Extensions/ServiceExtensions/Authentication_AuthingSetup.cs
new file mode 100644
index 00000000..4c2c68c8
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/Authentication_AuthingSetup.cs
@@ -0,0 +1,53 @@
+using Blog.Core.AuthHelper;
+using Blog.Core.Common;
+using Blog.Core.Common.HttpContextUser;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.IdentityModel.Tokens;
+using NetDevPack.Security.JwtExtensions;
+using System;
+
+namespace Blog.Core.Extensions
+{
+ ///
+ /// Authing权限 认证服务
+ ///
+ public static class Authentication_AuthingSetup
+ {
+ public static void AddAuthentication_AuthingSetup(this IServiceCollection services)
+ {
+ if (services == null) throw new ArgumentNullException(nameof(services));
+
+ var tokenValidationParameters = new TokenValidationParameters
+ {
+ ValidIssuer = AppSettings.app(new string[] { "Startup", "Authing", "Issuer" }),
+ ValidAudience = AppSettings.app(new string[] { "Startup", "Authing", "Audience" }),
+ ValidAlgorithms = new string[] { "RS256" },
+ //ValidateLifetime = true,
+ //ClockSkew = TimeSpan.FromSeconds(30),
+ //RequireExpirationTime = true,
+ };
+
+ services.AddAuthentication(o =>
+ {
+ //认证middleware配置
+ o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
+ o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
+ o.DefaultChallengeScheme = nameof(ApiResponseHandler);
+ o.DefaultForbidScheme = nameof(ApiResponseHandler);
+ })
+ .AddJwtBearer(o =>
+ {
+ //主要是jwt token参数设置
+ o.TokenValidationParameters = tokenValidationParameters;
+ o.RequireHttpsMetadata = false;
+ o.SaveToken = false;
+ o.IncludeErrorDetails = true;
+ o.SetJwksOptions(new JwkOptions(AppSettings.app(new string[] { "Startup", "Authing", "JwksUri" }), AppSettings.app(new string[] { "Startup", "Authing", "Issuer" }), new TimeSpan(TimeSpan.TicksPerDay)));
+ })
+ .AddScheme(nameof(ApiResponseHandler), o => { });
+
+ }
+ }
+}
From 41fa6122597bb3eb0d2b473adb1bb3f47d1aa4d6 Mon Sep 17 00:00:00 2001
From: Nine
Date: Tue, 31 Jan 2023 16:40:28 +0800
Subject: [PATCH 007/190] =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=8C=96=E6=97=A5?=
=?UTF-8?q?=E5=BF=97,=E5=A2=9E=E5=8A=A0PostgreSql=E6=94=AF=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Log4net.config | 90 ++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/Blog.Core.Api/Log4net.config b/Blog.Core.Api/Log4net.config
index 3ce11b6a..61bd3739 100644
--- a/Blog.Core.Api/Log4net.config
+++ b/Blog.Core.Api/Log4net.config
@@ -251,6 +251,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -267,6 +354,9 @@
+
+
+
From d0e4ff7757aed635dd240426cc3160e5a68a65f5 Mon Sep 17 00:00:00 2001
From: Geralt_Zhang <40553940+HuiJiOnGit@users.noreply.github.com>
Date: Thu, 2 Feb 2023 20:42:46 +0800
Subject: [PATCH 008/190] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=85=AC=E5=85=B1?=
=?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=B1=9E=E6=80=A7=E9=85=8D=E7=BD=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
将`TargetFramework`属性迁移到`common.targets`作为方便管理
---
Blog.Core.Api/Blog.Core.Api.csproj | 4 +---
Blog.Core.Common/Blog.Core.Common.csproj | 4 +---
Blog.Core.EventBus/Blog.Core.EventBus.csproj | 4 +---
Blog.Core.Extensions/Blog.Core.Extensions.csproj | 4 +---
Blog.Core.FrameWork/Blog.Core.FrameWork.csproj | 4 +---
Blog.Core.Gateway/Blog.Core.Gateway.csproj | 4 +---
Blog.Core.IServices/Blog.Core.IServices.csproj | 4 +---
Blog.Core.Model/Blog.Core.Model.csproj | 4 +---
Blog.Core.Repository/Blog.Core.Repository.csproj | 4 +---
Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj | 4 +---
Blog.Core.Services/Blog.Core.Services.csproj | 4 +---
Blog.Core.Tasks/Blog.Core.Tasks.csproj | 4 +---
Blog.Core.Tests/Blog.Core.Tests.csproj | 3 +--
Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj | 4 ++--
build/common.targets | 5 +++++
15 files changed, 20 insertions(+), 40 deletions(-)
create mode 100644 build/common.targets
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 9016c427..fcaef62a 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -1,10 +1,8 @@
+
-
Exe
-
- net7.0
enable
Linux
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index b3d20137..30816b97 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.EventBus/Blog.Core.EventBus.csproj b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
index bb75b1b0..8c50f8e2 100644
--- a/Blog.Core.EventBus/Blog.Core.EventBus.csproj
+++ b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index 3323fd2b..437841b7 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj b/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj
index 4f60a46d..51022b3c 100644
--- a/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj
+++ b/Blog.Core.FrameWork/Blog.Core.FrameWork.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.Gateway/Blog.Core.Gateway.csproj b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
index 819eaa36..ca3a7f72 100644
--- a/Blog.Core.Gateway/Blog.Core.Gateway.csproj
+++ b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
..\Blog.Core.Gateway\Blog.Core.Gateway.xml
diff --git a/Blog.Core.IServices/Blog.Core.IServices.csproj b/Blog.Core.IServices/Blog.Core.IServices.csproj
index 8ccfcc2f..20e8e658 100644
--- a/Blog.Core.IServices/Blog.Core.IServices.csproj
+++ b/Blog.Core.IServices/Blog.Core.IServices.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.Model/Blog.Core.Model.csproj b/Blog.Core.Model/Blog.Core.Model.csproj
index 120f3222..3c2ee04a 100644
--- a/Blog.Core.Model/Blog.Core.Model.csproj
+++ b/Blog.Core.Model/Blog.Core.Model.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
..\Blog.Core.Api\Blog.Core.Model.xml
diff --git a/Blog.Core.Repository/Blog.Core.Repository.csproj b/Blog.Core.Repository/Blog.Core.Repository.csproj
index 3547007f..783014e0 100644
--- a/Blog.Core.Repository/Blog.Core.Repository.csproj
+++ b/Blog.Core.Repository/Blog.Core.Repository.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
index d98cfafb..cd71cf26 100644
--- a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
+++ b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.Services/Blog.Core.Services.csproj b/Blog.Core.Services/Blog.Core.Services.csproj
index fbfa7bbc..04437f0c 100644
--- a/Blog.Core.Services/Blog.Core.Services.csproj
+++ b/Blog.Core.Services/Blog.Core.Services.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
..\Blog.Core.Api\bin\Debug\
diff --git a/Blog.Core.Tasks/Blog.Core.Tasks.csproj b/Blog.Core.Tasks/Blog.Core.Tasks.csproj
index 968fb795..408f379c 100644
--- a/Blog.Core.Tasks/Blog.Core.Tasks.csproj
+++ b/Blog.Core.Tasks/Blog.Core.Tasks.csproj
@@ -1,8 +1,6 @@
-
- net7.0
-
+
diff --git a/Blog.Core.Tests/Blog.Core.Tests.csproj b/Blog.Core.Tests/Blog.Core.Tests.csproj
index fd488226..98eff6fc 100644
--- a/Blog.Core.Tests/Blog.Core.Tests.csproj
+++ b/Blog.Core.Tests/Blog.Core.Tests.csproj
@@ -1,8 +1,7 @@
+
- net7.0
-
false
false
diff --git a/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj b/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj
index 23fd3e3d..6bdeb841 100644
--- a/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj
+++ b/Ocelot.Provider.Nacos/Ocelot.Provider.Nacos.csproj
@@ -1,7 +1,7 @@
-
+
+
- net7.0
softlgl
softlgl
https://github.com/softlgl/Ocelot.Provider.Nacos
diff --git a/build/common.targets b/build/common.targets
new file mode 100644
index 00000000..bfd5899f
--- /dev/null
+++ b/build/common.targets
@@ -0,0 +1,5 @@
+
+
+ net7.0
+
+
\ No newline at end of file
From 21307c64e6ec9f0b2ab78878db3005bfb1c59f3c Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 3 Feb 2023 14:56:10 +0800
Subject: [PATCH 009/190] Update PermissionController.cs
---
.../Controllers/PermissionController.cs | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Controllers/PermissionController.cs b/Blog.Core.Api/Controllers/PermissionController.cs
index edb9dd8c..d3000766 100644
--- a/Blog.Core.Api/Controllers/PermissionController.cs
+++ b/Blog.Core.Api/Controllers/PermissionController.cs
@@ -649,14 +649,15 @@ public async Task> BatchPost([FromBody] List pe
}
///
- /// 菜单同步
+ /// 系统接口菜单同步接口
///
+ ///
/// 接口module的控制器名称
/// 菜单permission的父id
/// 是否执行迁移到数据
///
[HttpGet]
- public async Task>> MigratePermission(string controllerName = "", int pid = 0, bool isAction = false)
+ public async Task>> MigratePermission(string action = "", string controllerName = "", int pid = 0, bool isAction = false)
{
var data = new MessageModel>();
if (controllerName.IsNullOrEmpty())
@@ -677,6 +678,7 @@ public async Task>> MigratePermission(string contr
}
var url = $"{jsonFileDomain}/swagger/V2/swagger.json";
+
var response = await client.GetAsync(url);
var body = await response.Content.ReadAsStringAsync();
@@ -688,6 +690,13 @@ public async Task>> MigratePermission(string contr
foreach (JProperty jProperty in pathsJObj.Properties())
{
var apiPath = jProperty.Name.ToLower();
+ if (action.IsNotEmptyOrNull())
+ {
+ if (!apiPath.Contains(action.ToLower()))
+ {
+ continue;
+ }
+ }
string httpmethod = "";
if (jProperty.Value.ToString().ToLower().Contains("get"))
{
@@ -708,6 +717,12 @@ public async Task>> MigratePermission(string contr
var summary = jProperty.Value.SelectToken($"{httpmethod}.summary").ObjToString();
+ var subIx = summary.IndexOf("(Auth");
+ if (subIx > 0)
+ {
+ summary = summary.Substring(0, subIx - 1);
+ }
+
permissions.Add(new Permission()
{
Code = " ",
From 9e888246cc25a16da57d04f847c1d1621f122f7b Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 3 Feb 2023 17:08:02 +0800
Subject: [PATCH 010/190] Update appsettings.json
---
Blog.Core.Api/appsettings.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index d639a62e..ea678174 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -190,7 +190,7 @@
"ApiName": "blog.core.api" // 资源服务器
},
"Authing": {
- "Enabled": true,
+ "Enabled": false,
"Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
"Audience": "63d51c4205c2849803be5178",
"JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
From bc03131ae0dcc810588662a0ac31ac5a7b04515a Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 5 Feb 2023 09:10:24 +0800
Subject: [PATCH 011/190] Update Blog.Core.xml
---
Blog.Core.Api/Blog.Core.xml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index b48d95ee..3321d53a 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -454,10 +454,11 @@
-
+
- 菜单同步
+ 系统接口菜单同步接口
+
接口module的控制器名称
菜单permission的父id
是否执行迁移到数据
From 569e968c82a8a6c087d6ec59e54d7df6a166e91a Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 5 Feb 2023 17:25:46 +0800
Subject: [PATCH 012/190] feat: add ExpressionExtensions.cs
---
.../Extensions/ExpressionExtensions.cs | 339 ++++++++++++++++++
Blog.Core.Common/Helper/DynamicLinqFactory.cs | 327 +----------------
2 files changed, 340 insertions(+), 326 deletions(-)
create mode 100644 Blog.Core.Common/Extensions/ExpressionExtensions.cs
diff --git a/Blog.Core.Common/Extensions/ExpressionExtensions.cs b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
new file mode 100644
index 00000000..4e1b066d
--- /dev/null
+++ b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
@@ -0,0 +1,339 @@
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Net.Http.Headers;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Helper
+{
+ ///
+ /// Linq扩展
+ ///
+ public static class ExpressionExtensions
+ {
+ #region Nacos NamingService
+
+ private static readonly HttpClient httpclient = new HttpClient();
+
+ private static string GetServiceUrl(Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl)
+ {
+ try
+ {
+ var instance = serv.SelectOneHealthyInstance(ServiceName, Group).GetAwaiter().GetResult();
+ var host = $"{instance.Ip}:{instance.Port}";
+ if (instance.Metadata.ContainsKey("endpoint")) host = instance.Metadata["endpoint"];
+
+
+ var baseUrl = instance.Metadata.TryGetValue("secure", out _)
+ ? $"https://{host}"
+ : $"http://{host}";
+
+ if (string.IsNullOrWhiteSpace(baseUrl))
+ {
+ return "";
+ }
+
+ return $"{baseUrl}{apiurl}";
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaoceGet(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters = null)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+ if (Parameters != null && Parameters.Any())
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (var pitem in Parameters)
+ {
+ sb.Append($"{pitem.Key}={pitem.Value}&");
+ }
+
+ url = $"{url}?{sb.ToString().Trim('&')}";
+ }
+
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.GetAsync(url);
+ return await result.Content.ReadAsStringAsync();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaocePostForm(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+
+ var content = (Parameters != null && Parameters.Any()) ? new FormUrlEncodedContent(Parameters) : null;
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.PostAsync(url, content);
+ return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaocePostJson(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, string jSonData)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.PostAsync(url, new StringContent(jSonData, Encoding.UTF8, "application/json"));
+ return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
+
+ //httpClient.BaseAddress = new Uri("https://www.testapi.com");
+ //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ //httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaocePostFile(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+
+ var content = new MultipartFormDataContent();
+ foreach (var pitem in Parameters)
+ {
+ content.Add(new ByteArrayContent(pitem.Value), "files", pitem.Key);
+ }
+
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.PostAsync(url, content);
+ return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
+ }
+ catch (Exception e)
+ {
+ //InfluxdbHelper.GetInstance().AddLog("Cof_NaocePostFile.Err", ee);
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ #endregion
+
+ #region HttpContext
+
+ ///
+ /// 返回请求上下文
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static async Task Cof_SendResponse(this HttpContext context, System.Net.HttpStatusCode code, string message, string ContentType = "text/html;charset=utf-8")
+ {
+ context.Response.StatusCode = (int)code;
+ context.Response.ContentType = ContentType;
+ await context.Response.WriteAsync(message);
+ }
+
+ #endregion
+
+ #region ICaching
+
+ ///
+ /// 从缓存里取数据,如果不存在则执行查询方法,
+ ///
+ /// 类型
+ /// ICaching
+ /// 键值
+ /// 查询方法
+ /// 有效期 单位分钟/param>
+ ///
+ public static T Cof_GetICaching(this ICaching cache, string key, Func GetFun, int timeSpanMin) where T : class
+ {
+ var obj = cache.Get(key);
+ obj = GetFun();
+ if (obj == null)
+ {
+ obj = GetFun();
+ cache.Set(key, obj, timeSpanMin);
+ }
+
+ return obj as T;
+ }
+
+ ///
+ /// 异步从缓存里取数据,如果不存在则执行查询方法
+ ///
+ /// 类型
+ /// ICaching
+ /// 键值
+ /// 查询方法
+ /// 有效期 单位分钟/param>
+ ///
+ public static async Task Cof_AsyncGetICaching(this ICaching cache, string key, Func> GetFun, int timeSpanMin) where T : class
+ {
+ var obj = cache.Get(key);
+ if (obj == null)
+ {
+ obj = await GetFun();
+ cache.Set(key, obj, timeSpanMin);
+ }
+
+ return obj as T;
+ }
+
+ #endregion
+
+ #region 常用扩展方法
+
+ public static bool Cof_CheckAvailable(this IEnumerable Tlist)
+ {
+ return Tlist != null && Tlist.Count() > 0;
+ }
+
+ ///
+ /// 调用内部方法
+ ///
+ public static Expression Call(this Expression instance, string methodName, params Expression[] arguments)
+ {
+ if (instance.Type == typeof(string))
+ return Expression.Call(instance, instance.Type.GetMethod(methodName, new Type[] { typeof(string) }), arguments); //修复string contains 出现的问题 Ambiguous match found.
+ else
+ return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments);
+ }
+
+ ///
+ /// 获取内部成员
+ ///
+ public static Expression Property(this Expression expression, string propertyName)
+ {
+ // Todo:左边条件如果是dynamic,
+ // 则Expression.Property无法获取子内容
+ // 报错在这里,由于expression内的对象为Object,所以无法解析到
+ // var x = (expression as IQueryable).ElementType;
+ var exp = Expression.Property(expression, propertyName);
+ if (exp.Type.IsGenericType && exp.Type.GetGenericTypeDefinition() == typeof(Nullable<>))
+ {
+ return Expression.Convert(exp, exp.Type.GetGenericArguments()[0]);
+ }
+
+ return exp;
+ }
+
+ ///
+ /// 转Lambda
+ ///
+ public static Expression ToLambda(this Expression body,
+ params ParameterExpression[] parameters)
+ {
+ return Expression.Lambda(body, parameters);
+ }
+
+ #endregion
+
+ #region 常用运算符 [ > , >= , == , < , <= , != , || , && ]
+
+ ///
+ /// &&
+ ///
+ public static Expression AndAlso(this Expression left, Expression right)
+ {
+ return Expression.AndAlso(left, right);
+ }
+
+ ///
+ /// ||
+ ///
+ public static Expression OrElse(this Expression left, Expression right)
+ {
+ return Expression.OrElse(left, right);
+ }
+
+ ///
+ /// Contains
+ ///
+ public static Expression Contains(this Expression left, Expression right)
+ {
+ return left.Call("Contains", right);
+ }
+
+ ///
+ /// >
+ ///
+ public static Expression GreaterThan(this Expression left, Expression right)
+ {
+ return Expression.GreaterThan(left, right);
+ }
+
+ ///
+ /// >=
+ ///
+ public static Expression GreaterThanOrEqual(this Expression left, Expression right)
+ {
+ return Expression.GreaterThanOrEqual(left, right);
+ }
+
+ ///
+ /// <
+ ///
+ public static Expression LessThan(this Expression left, Expression right)
+ {
+ return Expression.LessThan(left, right);
+ }
+
+ ///
+ /// <=
+ ///
+ public static Expression LessThanOrEqual(this Expression left, Expression right)
+ {
+ return Expression.LessThanOrEqual(left, right);
+ }
+
+ ///
+ /// ==
+ ///
+ public static Expression Equal(this Expression left, Expression right)
+ {
+ return Expression.Equal(left, right);
+ }
+
+ ///
+ /// !=
+ ///
+ public static Expression NotEqual(this Expression left, Expression right)
+ {
+ return Expression.NotEqual(left, right);
+ }
+
+ #endregion
+ }
+
+}
diff --git a/Blog.Core.Common/Helper/DynamicLinqFactory.cs b/Blog.Core.Common/Helper/DynamicLinqFactory.cs
index a12c6bbb..43fdd7e3 100644
--- a/Blog.Core.Common/Helper/DynamicLinqFactory.cs
+++ b/Blog.Core.Common/Helper/DynamicLinqFactory.cs
@@ -528,332 +528,7 @@ public enum OperationSymbol
#endregion
- ///
- /// Linq扩展
- ///
- public static class ExpressionExtensions
- {
- #region Nacos NamingService
-
- private static readonly HttpClient httpclient = new HttpClient();
-
- private static string GetServiceUrl(Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl)
- {
- try
- {
- var instance = serv.SelectOneHealthyInstance(ServiceName, Group).GetAwaiter().GetResult();
- var host = $"{instance.Ip}:{instance.Port}";
- if (instance.Metadata.ContainsKey("endpoint")) host = instance.Metadata["endpoint"];
-
-
- var baseUrl = instance.Metadata.TryGetValue("secure", out _)
- ? $"https://{host}"
- : $"http://{host}";
-
- if (string.IsNullOrWhiteSpace(baseUrl))
- {
- return "";
- }
-
- return $"{baseUrl}{apiurl}";
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaoceGet(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters = null)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
- if (Parameters != null && Parameters.Any())
- {
- StringBuilder sb = new StringBuilder();
- foreach (var pitem in Parameters)
- {
- sb.Append($"{pitem.Key}={pitem.Value}&");
- }
-
- url = $"{url}?{sb.ToString().Trim('&')}";
- }
-
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.GetAsync(url);
- return await result.Content.ReadAsStringAsync();
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaocePostForm(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
-
- var content = (Parameters != null && Parameters.Any()) ? new FormUrlEncodedContent(Parameters) : null;
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.PostAsync(url, content);
- return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaocePostJson(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, string jSonData)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.PostAsync(url, new StringContent(jSonData, Encoding.UTF8, "application/json"));
- return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
-
- //httpClient.BaseAddress = new Uri("https://www.testapi.com");
- //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- //httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaocePostFile(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
-
- var content = new MultipartFormDataContent();
- foreach (var pitem in Parameters)
- {
- content.Add(new ByteArrayContent(pitem.Value), "files", pitem.Key);
- }
-
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.PostAsync(url, content);
- return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
- }
- catch (Exception e)
- {
- //InfluxdbHelper.GetInstance().AddLog("Cof_NaocePostFile.Err", ee);
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- #endregion
-
- #region HttpContext
-
- ///
- /// 返回请求上下文
- ///
- ///
- ///
- ///
- ///
- ///
- public static async Task Cof_SendResponse(this HttpContext context, System.Net.HttpStatusCode code, string message, string ContentType = "text/html;charset=utf-8")
- {
- context.Response.StatusCode = (int)code;
- context.Response.ContentType = ContentType;
- await context.Response.WriteAsync(message);
- }
-
- #endregion
-
- #region ICaching
-
- ///
- /// 从缓存里取数据,如果不存在则执行查询方法,
- ///
- /// 类型
- /// ICaching
- /// 键值
- /// 查询方法
- /// 有效期 单位分钟/param>
- ///
- public static T Cof_GetICaching(this ICaching cache, string key, Func GetFun, int timeSpanMin) where T : class
- {
- var obj = cache.Get(key);
- obj = GetFun();
- if (obj == null)
- {
- obj = GetFun();
- cache.Set(key, obj, timeSpanMin);
- }
-
- return obj as T;
- }
-
- ///
- /// 异步从缓存里取数据,如果不存在则执行查询方法
- ///
- /// 类型
- /// ICaching
- /// 键值
- /// 查询方法
- /// 有效期 单位分钟/param>
- ///
- public static async Task Cof_AsyncGetICaching(this ICaching cache, string key, Func> GetFun, int timeSpanMin) where T : class
- {
- var obj = cache.Get(key);
- if (obj == null)
- {
- obj = await GetFun();
- cache.Set(key, obj, timeSpanMin);
- }
-
- return obj as T;
- }
-
- #endregion
-
- #region 常用扩展方法
-
- public static bool Cof_CheckAvailable(this IEnumerable Tlist)
- {
- return Tlist != null && Tlist.Count() > 0;
- }
-
- ///
- /// 调用内部方法
- ///
- public static Expression Call(this Expression instance, string methodName, params Expression[] arguments)
- {
- if (instance.Type == typeof(string))
- return Expression.Call(instance, instance.Type.GetMethod(methodName, new Type[] { typeof(string) }), arguments); //修复string contains 出现的问题 Ambiguous match found.
- else
- return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments);
- }
-
- ///
- /// 获取内部成员
- ///
- public static Expression Property(this Expression expression, string propertyName)
- {
- // Todo:左边条件如果是dynamic,
- // 则Expression.Property无法获取子内容
- // 报错在这里,由于expression内的对象为Object,所以无法解析到
- // var x = (expression as IQueryable).ElementType;
- var exp = Expression.Property(expression, propertyName);
- if (exp.Type.IsGenericType && exp.Type.GetGenericTypeDefinition() == typeof(Nullable<>))
- {
- return Expression.Convert(exp, exp.Type.GetGenericArguments()[0]);
- }
-
- return exp;
- }
-
- ///
- /// 转Lambda
- ///
- public static Expression ToLambda(this Expression body,
- params ParameterExpression[] parameters)
- {
- return Expression.Lambda(body, parameters);
- }
-
- #endregion
-
- #region 常用运算符 [ > , >= , == , < , <= , != , || , && ]
-
- ///
- /// &&
- ///
- public static Expression AndAlso(this Expression left, Expression right)
- {
- return Expression.AndAlso(left, right);
- }
-
- ///
- /// ||
- ///
- public static Expression OrElse(this Expression left, Expression right)
- {
- return Expression.OrElse(left, right);
- }
-
- ///
- /// Contains
- ///
- public static Expression Contains(this Expression left, Expression right)
- {
- return left.Call("Contains", right);
- }
-
- ///
- /// >
- ///
- public static Expression GreaterThan(this Expression left, Expression right)
- {
- return Expression.GreaterThan(left, right);
- }
-
- ///
- /// >=
- ///
- public static Expression GreaterThanOrEqual(this Expression left, Expression right)
- {
- return Expression.GreaterThanOrEqual(left, right);
- }
-
- ///
- /// <
- ///
- public static Expression LessThan(this Expression left, Expression right)
- {
- return Expression.LessThan(left, right);
- }
-
- ///
- /// <=
- ///
- public static Expression LessThanOrEqual(this Expression left, Expression right)
- {
- return Expression.LessThanOrEqual(left, right);
- }
-
- ///
- /// ==
- ///
- public static Expression Equal(this Expression left, Expression right)
- {
- return Expression.Equal(left, right);
- }
-
- ///
- /// !=
- ///
- public static Expression NotEqual(this Expression left, Expression right)
- {
- return Expression.NotEqual(left, right);
- }
-
- #endregion
- }
-
+
///
/// Queryable扩展
///
From d0b3cfe8054cb64b63a184f1cfb036fe9b3fee14 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 5 Feb 2023 18:40:35 +0800
Subject: [PATCH 013/190] feat: add ExpressionExtensions_Nacos.cs
---
.../Extensions/ExpressionExtensions.cs | 134 ----------------
.../Extensions/ExpressionExtensions_Nacos.cs | 148 ++++++++++++++++++
2 files changed, 148 insertions(+), 134 deletions(-)
create mode 100644 Blog.Core.Common/Extensions/ExpressionExtensions_Nacos.cs
diff --git a/Blog.Core.Common/Extensions/ExpressionExtensions.cs b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
index 4e1b066d..7f9e69e5 100644
--- a/Blog.Core.Common/Extensions/ExpressionExtensions.cs
+++ b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
@@ -3,9 +3,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
-using System.Net.Http.Headers;
-using System.Net.Http;
-using System.Text;
using System.Threading.Tasks;
namespace Blog.Core.Common.Helper
@@ -15,137 +12,6 @@ namespace Blog.Core.Common.Helper
///
public static class ExpressionExtensions
{
- #region Nacos NamingService
-
- private static readonly HttpClient httpclient = new HttpClient();
-
- private static string GetServiceUrl(Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl)
- {
- try
- {
- var instance = serv.SelectOneHealthyInstance(ServiceName, Group).GetAwaiter().GetResult();
- var host = $"{instance.Ip}:{instance.Port}";
- if (instance.Metadata.ContainsKey("endpoint")) host = instance.Metadata["endpoint"];
-
-
- var baseUrl = instance.Metadata.TryGetValue("secure", out _)
- ? $"https://{host}"
- : $"http://{host}";
-
- if (string.IsNullOrWhiteSpace(baseUrl))
- {
- return "";
- }
-
- return $"{baseUrl}{apiurl}";
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaoceGet(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters = null)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
- if (Parameters != null && Parameters.Any())
- {
- StringBuilder sb = new StringBuilder();
- foreach (var pitem in Parameters)
- {
- sb.Append($"{pitem.Key}={pitem.Value}&");
- }
-
- url = $"{url}?{sb.ToString().Trim('&')}";
- }
-
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.GetAsync(url);
- return await result.Content.ReadAsStringAsync();
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaocePostForm(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
-
- var content = (Parameters != null && Parameters.Any()) ? new FormUrlEncodedContent(Parameters) : null;
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.PostAsync(url, content);
- return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaocePostJson(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, string jSonData)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.PostAsync(url, new StringContent(jSonData, Encoding.UTF8, "application/json"));
- return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
-
- //httpClient.BaseAddress = new Uri("https://www.testapi.com");
- //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- //httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- public static async Task Cof_NaocePostFile(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
- {
- try
- {
- var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
- if (string.IsNullOrEmpty(url)) return "";
-
- var content = new MultipartFormDataContent();
- foreach (var pitem in Parameters)
- {
- content.Add(new ByteArrayContent(pitem.Value), "files", pitem.Key);
- }
-
- httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
- var result = await httpclient.PostAsync(url, content);
- return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
- }
- catch (Exception e)
- {
- //InfluxdbHelper.GetInstance().AddLog("Cof_NaocePostFile.Err", ee);
- Console.WriteLine(e.Message);
- }
-
- return "";
- }
-
- #endregion
-
#region HttpContext
///
diff --git a/Blog.Core.Common/Extensions/ExpressionExtensions_Nacos.cs b/Blog.Core.Common/Extensions/ExpressionExtensions_Nacos.cs
new file mode 100644
index 00000000..c187ee6a
--- /dev/null
+++ b/Blog.Core.Common/Extensions/ExpressionExtensions_Nacos.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Helper
+{
+ ///
+ /// Linq扩展
+ ///
+ public static class ExpressionExtensions_Nacos
+ {
+ #region Nacos NamingService
+
+ private static readonly HttpClient httpclient = new HttpClient();
+
+ private static string GetServiceUrl(Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl)
+ {
+ try
+ {
+ var instance = serv.SelectOneHealthyInstance(ServiceName, Group).GetAwaiter().GetResult();
+ var host = $"{instance.Ip}:{instance.Port}";
+ if (instance.Metadata.ContainsKey("endpoint")) host = instance.Metadata["endpoint"];
+
+
+ var baseUrl = instance.Metadata.TryGetValue("secure", out _)
+ ? $"https://{host}"
+ : $"http://{host}";
+
+ if (string.IsNullOrWhiteSpace(baseUrl))
+ {
+ return "";
+ }
+
+ return $"{baseUrl}{apiurl}";
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaoceGet(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters = null)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+ if (Parameters != null && Parameters.Any())
+ {
+ StringBuilder sb = new StringBuilder();
+ foreach (var pitem in Parameters)
+ {
+ sb.Append($"{pitem.Key}={pitem.Value}&");
+ }
+
+ url = $"{url}?{sb.ToString().Trim('&')}";
+ }
+
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.GetAsync(url);
+ return await result.Content.ReadAsStringAsync();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaocePostForm(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+
+ var content = (Parameters != null && Parameters.Any()) ? new FormUrlEncodedContent(Parameters) : null;
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.PostAsync(url, content);
+ return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaocePostJson(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, string jSonData)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.PostAsync(url, new StringContent(jSonData, Encoding.UTF8, "application/json"));
+ return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
+
+ //httpClient.BaseAddress = new Uri("https://www.testapi.com");
+ //httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ //httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ public static async Task Cof_NaocePostFile(this Nacos.V2.INacosNamingService serv, string ServiceName, string Group, string apiurl, Dictionary Parameters)
+ {
+ try
+ {
+ var url = GetServiceUrl(serv, ServiceName, Group, apiurl);
+ if (string.IsNullOrEmpty(url)) return "";
+
+ var content = new MultipartFormDataContent();
+ foreach (var pitem in Parameters)
+ {
+ content.Add(new ByteArrayContent(pitem.Value), "files", pitem.Key);
+ }
+
+ httpclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
+ var result = await httpclient.PostAsync(url, content);
+ return await result.Content.ReadAsStringAsync(); //.GetAwaiter().GetResult();
+ }
+ catch (Exception e)
+ {
+ //InfluxdbHelper.GetInstance().AddLog("Cof_NaocePostFile.Err", ee);
+ Console.WriteLine(e.Message);
+ }
+
+ return "";
+ }
+
+ #endregion
+ }
+
+}
From 316adaa3671dc0384591e26a148e61cf39e494fb Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 5 Feb 2023 21:50:46 +0800
Subject: [PATCH 014/190] feat: add SerilogServer_Es.cs
---
.../LogHelper/Seri/SerilogServer.cs | 17 +---
.../LogHelper/Seri/SerilogServer_Es.cs | 89 +++++++++++++++++++
2 files changed, 91 insertions(+), 15 deletions(-)
create mode 100644 Blog.Core.Common/LogHelper/Seri/SerilogServer_Es.cs
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
index 98affb9e..cb5ec0ff 100644
--- a/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer.cs
@@ -1,6 +1,4 @@
using Blog.Core.Common.Helper;
-using Blog.Core.Serilog.Es;
-using Blog.Core.Serilog.Es.Formatters;
using Serilog;
using Serilog.Events;
using System;
@@ -19,23 +17,12 @@ public class SerilogServer
public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "", bool isJudgeJsonFormat = false)
{
Log.Logger = new LoggerConfiguration()
- // TCPSink 集成Serilog 使用tcp的方式向elk 输出log日志 LogstashJsonFormatter 这个是按照自定义格式化输出内容
- .WriteTo.TCPSink(new LogstashJsonFormatter())
.MinimumLevel.Debug()
.MinimumLevel.Override("Microsoft", LogEventLevel.Error)
//.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
.WriteTo.File(Path.Combine("Log", defaultFolder, $"{filename}.log"),
- rollingInterval: RollingInterval.Infinite,
- outputTemplate: "{Message}{NewLine}{Exception}")
-
- // 将日志托送到远程ES
- // docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d --name ES01 elasticsearch:7.2.0
- //.Enrich.FromLogContext()
- //.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://x.xxx.xx.xx:9200/"))
- //{
- // AutoRegisterTemplate = true,
- //})
-
+ rollingInterval: RollingInterval.Infinite,
+ outputTemplate: "{Message}{NewLine}{Exception}")
.CreateLogger();
var now = DateTime.Now;
diff --git a/Blog.Core.Common/LogHelper/Seri/SerilogServer_Es.cs b/Blog.Core.Common/LogHelper/Seri/SerilogServer_Es.cs
new file mode 100644
index 00000000..048d5597
--- /dev/null
+++ b/Blog.Core.Common/LogHelper/Seri/SerilogServer_Es.cs
@@ -0,0 +1,89 @@
+using Blog.Core.Common.Helper;
+using Blog.Core.Serilog.Es;
+using Blog.Core.Serilog.Es.Formatters;
+using Serilog;
+using Serilog.Events;
+using System;
+using System.IO;
+
+namespace Blog.Core.Common.LogHelper
+{
+ public class SerilogServer_Es
+ {
+ ///
+ /// 记录日常日志
+ ///
+ ///
+ ///
+ ///
+ public static void WriteLog(string filename, string[] dataParas, bool IsHeader = true, string defaultFolder = "", bool isJudgeJsonFormat = false)
+ {
+ Log.Logger = new LoggerConfiguration()
+ // TCPSink 集成Serilog 使用tcp的方式向elk 输出log日志 LogstashJsonFormatter 这个是按照自定义格式化输出内容
+ .WriteTo.TCPSink(new LogstashJsonFormatter())
+ .MinimumLevel.Debug()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Error)
+ //.WriteTo.File(Path.Combine($"log/Serilog/{filename}/", ".log"), rollingInterval: RollingInterval.Day, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level}] {Message}{NewLine}{Exception}")
+ .WriteTo.File(Path.Combine("Log", defaultFolder, $"{filename}.log"),
+ rollingInterval: RollingInterval.Infinite,
+ outputTemplate: "{Message}{NewLine}{Exception}")
+
+ // 将日志托送到远程ES
+ // docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d --name ES01 elasticsearch:7.2.0
+ //.Enrich.FromLogContext()
+ //.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://x.xxx.xx.xx:9200/"))
+ //{
+ // AutoRegisterTemplate = true,
+ //})
+
+ .CreateLogger();
+
+ var now = DateTime.Now;
+ string logContent = String.Join("\r\n", dataParas);
+ var isJsonFormat = true;
+ if (isJudgeJsonFormat)
+ {
+ var judCont = logContent.Substring(0, logContent.LastIndexOf(","));
+ isJsonFormat = JsonHelper.IsJson(judCont);
+ }
+
+ if (isJsonFormat)
+ {
+ if (IsHeader)
+ {
+ logContent = (
+ "--------------------------------\r\n" +
+ DateTime.Now + "|\r\n" +
+ String.Join("\r\n", dataParas) + "\r\n"
+ );
+ }
+ // 展示elk支持输出4种日志级别
+ Log.Information(logContent);
+ //Log.Warning(logContent);
+ //Log.Error(logContent);
+ //Log.Debug(logContent);
+ }
+ else
+ {
+ Console.WriteLine("【JSON格式异常:】"+logContent + now.ObjToString());
+ }
+ Log.CloseAndFlush();
+ }
+ ///
+ /// 记录异常日志
+ ///
+ ///
+ ///
+ ///
+ public static void WriteErrorLog(string filename, string message, Exception ex)
+ {
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Debug()
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Error)
+ .WriteTo.File(Path.Combine($"log/Error/{filename}/", ".txt"), rollingInterval: RollingInterval.Day)
+ .CreateLogger();
+ Log.Error(ex, message);
+ Log.CloseAndFlush();
+ }
+ }
+}
From 04905f07150a84eda6185d591182570c29eadb60 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 5 Feb 2023 22:36:15 +0800
Subject: [PATCH 015/190] feat:JobSetup_HostedService
---
Blog.Core.Api/Program.cs | 1 +
.../HostedService/Job1TimedService.cs | 2 +-
.../HostedService/Job2TimedService.cs | 2 +-
.../JobSetup_HostedService.cs | 20 +++++++++++++++++++
4 files changed, 23 insertions(+), 2 deletions(-)
rename {Blog.Core.Tasks => Blog.Core.Extensions}/HostedService/Job1TimedService.cs (98%)
rename {Blog.Core.Tasks => Blog.Core.Extensions}/HostedService/Job2TimedService.cs (97%)
create mode 100644 Blog.Core.Extensions/ServiceExtensions/JobSetup_HostedService.cs
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index 7a9a25c0..8ab4b93d 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -70,6 +70,7 @@
builder.Services.AddMiniProfilerSetup();
builder.Services.AddSwaggerSetup();
builder.Services.AddJobSetup();
+//builder.Services.AddJobSetup_HostedService();
builder.Services.AddHttpContextSetup();
builder.Services.AddAppTableConfigSetup(builder.Environment);
builder.Services.AddHttpApi();
diff --git a/Blog.Core.Tasks/HostedService/Job1TimedService.cs b/Blog.Core.Extensions/HostedService/Job1TimedService.cs
similarity index 98%
rename from Blog.Core.Tasks/HostedService/Job1TimedService.cs
rename to Blog.Core.Extensions/HostedService/Job1TimedService.cs
index 9777affc..bd515194 100644
--- a/Blog.Core.Tasks/HostedService/Job1TimedService.cs
+++ b/Blog.Core.Extensions/HostedService/Job1TimedService.cs
@@ -5,7 +5,7 @@
using System.Threading;
using System.Threading.Tasks;
-namespace Blog.Core.Tasks
+namespace Blog.Core.Extensions
{
public class Job1TimedService : IHostedService, IDisposable
{
diff --git a/Blog.Core.Tasks/HostedService/Job2TimedService.cs b/Blog.Core.Extensions/HostedService/Job2TimedService.cs
similarity index 97%
rename from Blog.Core.Tasks/HostedService/Job2TimedService.cs
rename to Blog.Core.Extensions/HostedService/Job2TimedService.cs
index ee7f2c5c..a1d0d88a 100644
--- a/Blog.Core.Tasks/HostedService/Job2TimedService.cs
+++ b/Blog.Core.Extensions/HostedService/Job2TimedService.cs
@@ -4,7 +4,7 @@
using System.Threading;
using System.Threading.Tasks;
-namespace Blog.Core.Tasks
+namespace Blog.Core.Extensions
{
public class Job2TimedService : IHostedService, IDisposable
{
diff --git a/Blog.Core.Extensions/ServiceExtensions/JobSetup_HostedService.cs b/Blog.Core.Extensions/ServiceExtensions/JobSetup_HostedService.cs
new file mode 100644
index 00000000..ccf5eb4d
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/JobSetup_HostedService.cs
@@ -0,0 +1,20 @@
+using Microsoft.Extensions.DependencyInjection;
+using System;
+
+namespace Blog.Core.Extensions
+{
+ ///
+ /// 任务调度 启动服务
+ ///
+ public static class JobSetup_HostedService
+ {
+ public static void AddJobSetup_HostedService(this IServiceCollection services)
+ {
+ if (services == null) throw new ArgumentNullException(nameof(services));
+
+ services.AddHostedService();
+ services.AddHostedService();
+
+ }
+ }
+}
From a21e2055edbedc0bce480b5fa3c2a6c197ac55cf Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Mon, 6 Feb 2023 22:11:56 +0800
Subject: [PATCH 016/190] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20=E5=8D=87=E7=B4=9A?=
=?UTF-8?q?SqlSugar=20->=205.1.3.49?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Model/Blog.Core.Model.csproj | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/Blog.Core.Model/Blog.Core.Model.csproj b/Blog.Core.Model/Blog.Core.Model.csproj
index de7e6467..67bb5ad7 100644
--- a/Blog.Core.Model/Blog.Core.Model.csproj
+++ b/Blog.Core.Model/Blog.Core.Model.csproj
@@ -16,9 +16,13 @@
-
+
+
+
+
+
From 60653a383ddd3a9f1ba80acb0d6b550742ff6366 Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Tue, 7 Feb 2023 00:00:05 +0800
Subject: [PATCH 017/190] =?UTF-8?q?=E2=9C=A8=E3=80=80=E5=A2=9E=E5=8A=A0?=
=?UTF-8?q?=E7=A7=8D=E5=AD=90=E6=95=B0=E6=8D=AE=E6=8E=A5=E5=8F=A3=E3=80=81?=
=?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=B8=B8=E7=94=A8=E6=96=B9=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Common/App.cs | 19 +++++
Blog.Core.Common/Core/InternalApp.cs | 15 ++++
.../Extensions/AssemblysExtensions.cs | 24 ++++++
.../Extensions/GenericTypeExtensions.cs | 28 +++++-
Blog.Core.Common/Helper/UtilConvert.cs | 12 +++
Blog.Core.Common/Seed/DBSeed.cs | 85 +++++++++++++++++--
Blog.Core.Common/Seed/IEntitySeedData.cs | 36 ++++++++
7 files changed, 211 insertions(+), 8 deletions(-)
create mode 100644 Blog.Core.Common/App.cs
create mode 100644 Blog.Core.Common/Core/InternalApp.cs
create mode 100644 Blog.Core.Common/Extensions/AssemblysExtensions.cs
create mode 100644 Blog.Core.Common/Seed/IEntitySeedData.cs
diff --git a/Blog.Core.Common/App.cs b/Blog.Core.Common/App.cs
new file mode 100644
index 00000000..008aea5d
--- /dev/null
+++ b/Blog.Core.Common/App.cs
@@ -0,0 +1,19 @@
+using Blog.Core.Common.Core;
+using Blog.Core.Common.HttpContextUser;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using System;
+
+namespace Blog.Core.Common;
+
+public class App
+{
+ public static IServiceProvider RootServices => InternalApp.RootServices ;
+
+ ///
+ /// 获取请求上下文
+ ///
+ public static HttpContext HttpContext => RootServices?.GetService()?.HttpContext;
+
+ public static IUser User => HttpContext == null ? null : RootServices?.GetService();
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Core/InternalApp.cs b/Blog.Core.Common/Core/InternalApp.cs
new file mode 100644
index 00000000..b1f94f9d
--- /dev/null
+++ b/Blog.Core.Common/Core/InternalApp.cs
@@ -0,0 +1,15 @@
+using Microsoft.Extensions.Hosting;
+using System;
+
+namespace Blog.Core.Common.Core;
+
+public static class InternalApp
+{
+ /// 根服务
+ public static IServiceProvider RootServices;
+
+ public static void ConfigureApplication(this IHost app)
+ {
+ RootServices = app.Services;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Extensions/AssemblysExtensions.cs b/Blog.Core.Common/Extensions/AssemblysExtensions.cs
new file mode 100644
index 00000000..06fa943b
--- /dev/null
+++ b/Blog.Core.Common/Extensions/AssemblysExtensions.cs
@@ -0,0 +1,24 @@
+using Microsoft.Extensions.DependencyModel;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.Loader;
+
+namespace Blog.Core.Common.Extensions;
+
+public static class AssemblysExtensions
+{
+ public static List GetAllAssemblies()
+ {
+ var list = new List();
+ var deps = DependencyContext.Default;
+ var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package" && lib.Name.StartsWith("Baiqian"));
+ foreach (var lib in libs)
+ {
+ var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
+ list.Add(assembly);
+ }
+
+ return list;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Extensions/GenericTypeExtensions.cs b/Blog.Core.Common/Extensions/GenericTypeExtensions.cs
index 368b6676..c0b6150f 100644
--- a/Blog.Core.Common/Extensions/GenericTypeExtensions.cs
+++ b/Blog.Core.Common/Extensions/GenericTypeExtensions.cs
@@ -26,5 +26,31 @@ public static string GetGenericTypeName(this object @object)
{
return @object.GetType().GetGenericTypeName();
}
+
+ ///
+ /// 判断类型是否实现某个泛型
+ ///
+ /// 类型
+ /// 泛型类型
+ /// bool
+ public static bool HasImplementedRawGeneric(this Type type, Type generic)
+ {
+ // 检查接口类型
+ var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
+ if (isTheRawGenericType) return true;
+
+ // 检查类型
+ while (type != null && type != typeof(object))
+ {
+ isTheRawGenericType = IsTheRawGenericType(type);
+ if (isTheRawGenericType) return true;
+ type = type.BaseType;
+ }
+
+ return false;
+
+ // 判断逻辑
+ bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type);
+ }
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Helper/UtilConvert.cs b/Blog.Core.Common/Helper/UtilConvert.cs
index 282989e3..ea3b7c05 100644
--- a/Blog.Core.Common/Helper/UtilConvert.cs
+++ b/Blog.Core.Common/Helper/UtilConvert.cs
@@ -43,6 +43,18 @@ public static int ObjToInt(this object thisValue, int errorValue)
return errorValue;
}
+ public static long ObjToLong(this object thisValue)
+ {
+ long reval = 0;
+ if (thisValue == null) return 0;
+ if (thisValue != DBNull.Value && long.TryParse(thisValue.ToString(), out reval))
+ {
+ return reval;
+ }
+
+ return reval;
+ }
+
///
///
///
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 9afdc30d..adb185f2 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -1,4 +1,5 @@
using Blog.Core.Common.DB;
+using Blog.Core.Common.Extensions;
using Blog.Core.Common.Helper;
using Blog.Core.Model.Models;
using Magicodes.ExporterAndImporter.Excel;
@@ -96,7 +97,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
var modelTypes = referencedAssemblies
.SelectMany(a => a.DefinedTypes)
.Select(type => type.AsType())
- .Where(x => x.IsClass && x.Namespace != null && x.Namespace.Equals("Blog.Core.Model.Models")).ToList();
+ .Where(x => x.IsClass && x.Namespace is "Blog.Core.Model.Models").ToList();
modelTypes.ForEach(t =>
{
// 这里只支持添加表,不支持删除
@@ -110,8 +111,6 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
ConsoleHelper.WriteSuccessLine($"Tables created successfully!");
Console.WriteLine();
-
-
if (AppSettings.app(new string[] { "AppSettings", "SeedDBDataEnabled" }).ObjToBool())
{
JsonSerializerSettings setting = new JsonSerializerSettings();
@@ -135,6 +134,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
var importer = new ExcelImporter();
#region BlogArticle
+
if (!await myContext.Db.Queryable().AnyAsync())
{
myContext.GetEntityDB().InsertRange(JsonHelper.ParseFormByJson>(FileHelper.ReadFile(string.Format(SeedDataFolder, "BlogArticle"), Encoding.UTF8)));
@@ -144,15 +144,14 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:BlogArticle already exists...");
}
+
#endregion
#region Modules
+
if (!await myContext.Db.Queryable().AnyAsync())
{
-
-
-
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Modules"), Encoding.UTF8), setting);
myContext.GetEntityDB().InsertRange(data);
@@ -162,10 +161,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:Modules already exists...");
}
+
#endregion
#region Permission
+
if (!await myContext.Db.Queryable().AnyAsync())
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Permission"), Encoding.UTF8), setting);
@@ -177,10 +178,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:Permission already exists...");
}
+
#endregion
#region Role
+
if (!await myContext.Db.Queryable().AnyAsync())
{
//var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Role"), Encoding.UTF8), setting);
@@ -195,10 +198,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:Role already exists...");
}
+
#endregion
#region RoleModulePermission
+
if (!await myContext.Db.Queryable().AnyAsync())
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "RoleModulePermission"), Encoding.UTF8), setting);
@@ -210,10 +215,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:RoleModulePermission already exists...");
}
+
#endregion
#region Topic
+
if (!await myContext.Db.Queryable().AnyAsync())
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Topic"), Encoding.UTF8), setting);
@@ -225,10 +232,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:Topic already exists...");
}
+
#endregion
#region TopicDetail
+
if (!await myContext.Db.Queryable().AnyAsync())
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "TopicDetail"), Encoding.UTF8), setting);
@@ -240,10 +249,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:TopicDetail already exists...");
}
+
#endregion
#region UserRole
+
if (!await myContext.Db.Queryable().AnyAsync())
{
//var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "UserRole"), Encoding.UTF8), setting);
@@ -258,10 +269,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:UserRole already exists...");
}
+
#endregion
#region sysUserInfo
+
if (!await myContext.Db.Queryable().AnyAsync())
{
//var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "sysUserInfo"), Encoding.UTF8), setting);
@@ -276,10 +289,12 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:sysUserInfo already exists...");
}
+
#endregion
#region TasksQz
+
if (!await myContext.Db.Queryable().AnyAsync())
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "TasksQz"), Encoding.UTF8), setting);
@@ -291,9 +306,11 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:TasksQz already exists...");
}
+
#endregion
#region Department
+
if (!await myContext.Db.Queryable().AnyAsync())
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Department"), Encoding.UTF8), setting);
@@ -305,13 +322,16 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:Department already exists...");
}
+
#endregion
+ //种子初始化
+ await SeedDataAsync(myContext);
+
ConsoleHelper.WriteSuccessLine($"Done seeding database!");
}
Console.WriteLine();
-
}
catch (Exception ex)
{
@@ -321,5 +341,56 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
"3、其他错误:" + ex.Message);
}
}
+
+ ///
+ /// 种子初始化数据
+ ///
+ ///
+ ///
+ private static async Task SeedDataAsync(MyContext myContext)
+ {
+ // 获取所有种子配置-初始化数据
+ var seedDataTypes = AssemblysExtensions.GetAllAssemblies().SelectMany(s => s.DefinedTypes)
+ .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass &&
+ u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(IEntitySeedData<>))));
+ if (!seedDataTypes.Any()) return;
+ foreach (var seedType in seedDataTypes)
+ {
+ dynamic instance = Activator.CreateInstance(seedType);
+ //初始化数据
+ {
+ var seedData = instance.InitSeedData();
+ if (seedData != null && Enumerable.Any(seedData))
+ {
+ var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
+ var entity = myContext.Db.EntityMaintenance.GetEntityInfo(entityType);
+
+ if (!await myContext.Db.Queryable(entity.DbTableName, "").AnyAsync())
+ {
+ await myContext.Db.Insertable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
+ Console.WriteLine($"Table:{entity.DbTableName} init success!");
+ }
+ }
+ }
+
+ //种子数据
+ {
+ var seedData = instance.SeedData();
+ if (seedData != null && Enumerable.Any(seedData))
+ {
+ var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
+ var entity = myContext.Db.EntityMaintenance.GetEntityInfo(entityType);
+
+ await myContext.Db.Storageable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
+ Console.WriteLine($"Table:{entity.DbTableName} seedData success!");
+ }
+ }
+
+ //自定义处理
+ {
+ await instance.CustomizeSeedData(myContext.Db);
+ }
+ }
+ }
}
}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/IEntitySeedData.cs b/Blog.Core.Common/Seed/IEntitySeedData.cs
new file mode 100644
index 00000000..3e2f4859
--- /dev/null
+++ b/Blog.Core.Common/Seed/IEntitySeedData.cs
@@ -0,0 +1,36 @@
+using SqlSugar;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Seed;
+
+///
+/// 种子数据 接口
+///
+///
+public interface IEntitySeedData
+ where T : class, new()
+{
+ ///
+ /// 初始化种子数据
+ /// 只要表不存在数据,程序启动就会自动初始化
+ ///
+ ///
+ IEnumerable InitSeedData();
+
+ ///
+ /// 种子数据
+ /// 存在不操作、不存在Insert
+ /// 适合系统内置数据,项目开发后续增加内置数据
+ ///
+ ///
+ IEnumerable SeedData();
+
+ ///
+ /// 自定义操作
+ /// 以上满不足了,可以自己编写
+ ///
+ ///
+ ///
+ Task CustomizeSeedData(ISqlSugarClient db);
+}
\ No newline at end of file
From 151e7fc0ab97989c9545e2b1d406d254993edcfc Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Tue, 7 Feb 2023 00:27:55 +0800
Subject: [PATCH 018/190] =?UTF-8?q?=E2=9C=A8=F0=9F=8E=A8=20=E5=A4=9A?=
=?UTF-8?q?=E7=A7=9F=E6=88=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1.兼容使用多租户多种方案
2.增加系统租户表、用户增加租户id、新增一张业务表用于租户测试数据
3.TenantByIdController 租户使用
---
Blog.Core.Api/Blog.Core.Api.csproj | 6 +-
Blog.Core.Api/Blog.Core.Model.xml | 172 ++++++++++++++++++
Blog.Core.Api/Blog.Core.xml | 17 ++
Blog.Core.Api/Controllers/LoginController.cs | 37 ++--
.../Tenant/TenantByIdController.cs | 49 +++++
Blog.Core.Api/Program.cs | 3 +-
.../BlogCore.Data.excel/SysUserInfo.xlsx | Bin 11177 -> 11197 bytes
Blog.Core.Common/Blog.Core.Common.csproj | 4 +
Blog.Core.Common/DB/Aop/SqlsugarAop.cs | 86 +++++++++
Blog.Core.Common/DB/RepositorySetting.cs | 43 +++++
.../Extensions/AssemblysExtensions.cs | 2 +-
.../HttpContextUser/AspNetUser.cs | 6 +-
Blog.Core.Common/HttpContextUser/IUser.cs | 3 +-
.../Seed/SeedData/BusinessDataSeedData.cs | 79 ++++++++
.../Seed/SeedData/TenantSeedData.cs | 44 +++++
.../Seed/SeedData/UserInfoSeedData.cs | 42 +++++
Blog.Core.EventBus/Blog.Core.EventBus.csproj | 2 +-
.../Blog.Core.Extensions.csproj | 2 +-
.../Middlewares/RequRespLogMiddleware.cs | 1 -
.../ServiceExtensions/SqlsugarSetup.cs | 17 +-
Blog.Core.IServices/BASE/IBaseServices.cs | 1 +
Blog.Core.Model/Blog.Core.Model.csproj | 2 +-
Blog.Core.Model/CustomEnums/TenantTypeEnum.cs | 23 +++
Blog.Core.Model/Models/BusinessTable.cs | 27 +++
Blog.Core.Model/Models/RootTkey/BaseEntity.cs | 86 +++++++++
.../RootTkey/Interface/IDeleteFilter.cs | 9 +
.../RootTkey/Interface/ITenantEntity.cs | 15 ++
.../Models/RootTkey/RootEntityTkey.cs | 2 -
Blog.Core.Model/Models/SysTenant.cs | 67 +++++++
Blog.Core.Model/Models/sysUserInfo.cs | 10 +-
Blog.Core.Services/BASE/BaseServices.cs | 56 +++---
31 files changed, 854 insertions(+), 59 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs
create mode 100644 Blog.Core.Common/DB/Aop/SqlsugarAop.cs
create mode 100644 Blog.Core.Common/DB/RepositorySetting.cs
create mode 100644 Blog.Core.Common/Seed/SeedData/BusinessDataSeedData.cs
create mode 100644 Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
create mode 100644 Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
create mode 100644 Blog.Core.Model/CustomEnums/TenantTypeEnum.cs
create mode 100644 Blog.Core.Model/Models/BusinessTable.cs
create mode 100644 Blog.Core.Model/Models/RootTkey/BaseEntity.cs
create mode 100644 Blog.Core.Model/Models/RootTkey/Interface/IDeleteFilter.cs
create mode 100644 Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs
create mode 100644 Blog.Core.Model/Models/SysTenant.cs
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 38575a55..7e17937a 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -26,18 +26,22 @@
+
+
+
+
@@ -94,7 +98,7 @@
-
+
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 36975d11..f5fd195c 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -34,6 +34,21 @@
所有
+
+
+ 租户隔离方案
+
+
+
+
+ Id隔离
+
+
+
+
+ 库隔离
+
+
以下model 来自ids4项目,多库模式,为了调取ids4数据
@@ -301,6 +316,27 @@
逻辑删除
+
+
+ 业务数据
+ 多租户 (Id 隔离)
+
+
+
+
+ 无需手动赋值
+
+
+
+
+ 名称
+
+
+
+
+ 金额
+
+
部门表
@@ -822,6 +858,137 @@
修改时间
+
+
+ 雪花Id
+
+
+
+
+ 状态
+ 中立字段,某些表可使用某些表不使用
+
+
+
+
+ 中立字段,某些表可使用某些表不使用
+ 逻辑上的删除,非物理删除
+ 例如:单据删除并非直接删除
+
+
+
+
+ 中立字段
+ 是否内置数据
+
+
+
+
+ 创建ID
+
+
+
+
+ 创建者
+
+
+
+
+ 创建时间
+
+
+
+
+ 修改ID
+
+
+
+
+ 更新者
+
+
+
+
+ 修改日期
+
+
+
+
+ 数据版本
+
+
+
+
+ 软删除 过滤器
+
+
+
+
+ 租户模型接口
+
+
+
+
+ 租户Id
+
+
+
+
+ 系统租户表
+ 根据TenantType 分为两种方案:
+ 1.按租户字段区分
+ 2.按租户分库
+
+
+
+ 注意:
+ 使用租户Id方案,无需配置分库的连接
+
+
+
+
+ 名称
+
+
+
+
+ 租户类型
+
+
+
+
+ 数据库/租户标识 不可重复
+ 使用Id方案,可无需配置
+
+
+
+
+ 主机
+ 使用Id方案,可无需配置
+
+
+
+
+ 数据库类型
+ 使用Id方案,可无需配置
+
+
+
+
+ 数据库连接
+ 使用Id方案,可无需配置
+
+
+
+
+ 状态
+
+
+
+
+ 备注
+
+
用户信息表
@@ -887,6 +1054,11 @@
登录账号
+
+
+ 租户Id
+
+
任务计划表
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 3321d53a..8b5b79fd 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -1236,6 +1236,23 @@
+
+
+ 多租户测试
+
+
+
+
+ 获取租户下全部业务数据
+
+
+
+
+
+ 新增业务数据
+
+
+
自定义路由 /api/{version}/[controler]/[action]
diff --git a/Blog.Core.Api/Controllers/LoginController.cs b/Blog.Core.Api/Controllers/LoginController.cs
index 25818c13..87f5c0c9 100644
--- a/Blog.Core.Api/Controllers/LoginController.cs
+++ b/Blog.Core.Api/Controllers/LoginController.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.IdentityModel.Tokens.Jwt;
-using System.Linq;
-using System.Security.Claims;
-using System.Threading.Tasks;
-using Blog.Core.AuthHelper;
+using Blog.Core.AuthHelper;
using Blog.Core.AuthHelper.OverWrite;
using Blog.Core.Common.Helper;
using Blog.Core.IServices;
@@ -12,8 +6,9 @@
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
namespace Blog.Core.Controllers
@@ -52,6 +47,7 @@ public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServic
#region 获取token的第1种方法
+
///
/// 获取JWT的方法1
///
@@ -62,7 +58,6 @@ public LoginController(ISysUserInfoServices sysUserInfoServices, IUserRoleServic
[Route("Token")]
public async Task> GetJwtStr(string name, string pass)
{
-
string jwtStr = string.Empty;
bool suc = false;
//这里就是用户登陆以后,通过数据库去调取数据,分配权限的操作
@@ -70,7 +65,6 @@ public async Task> GetJwtStr(string name, string pass)
var user = await _sysUserInfoServices.GetUserRoleNameStr(name, MD5Helper.MD5Encrypt32(pass));
if (user != null)
{
-
TokenModelJwt tokenModel = new TokenModelJwt { Uid = 1, Role = user };
jwtStr = JwtHelper.IssueJwt(tokenModel);
@@ -119,6 +113,7 @@ public MessageModel GetJwtStrForNuxt(string name, string pass)
{
jwtStr = "login fail!!!";
}
+
var result = new
{
data = new { success = suc, token = jwtStr }
@@ -131,8 +126,8 @@ public MessageModel GetJwtStrForNuxt(string name, string pass)
response = jwtStr
};
}
- #endregion
+ #endregion
///
@@ -157,11 +152,14 @@ public async Task> GetJwtToken3(string name = "
{
var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(name, pass);
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
- var claims = new List {
+ var claims = new List
+ {
new Claim(ClaimTypes.Name, name),
new Claim(JwtRegisteredClaimNames.Jti, user.FirstOrDefault().Id.ToString()),
+ new Claim("TenantId", user.FirstOrDefault().TenantId.ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
- new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
+ new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
+ };
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
@@ -218,11 +216,13 @@ public async Task> RefreshToken(string token =
{
var userRoles = await _sysUserInfoServices.GetUserRoleNameStr(user.LoginName, user.LoginPWD);
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
- var claims = new List {
- new Claim(ClaimTypes.Name, user.LoginName),
- new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
- new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
- new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
+ var claims = new List
+ {
+ new Claim(ClaimTypes.Name, user.LoginName),
+ new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
+ new Claim(JwtRegisteredClaimNames.Iat, DateTime.Now.ToString()),
+ new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString())
+ };
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
//用户标识
@@ -233,6 +233,7 @@ public async Task> RefreshToken(string token =
return Success(refreshToken, "获取成功");
}
}
+
return Failed("认证失败!");
}
diff --git a/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs b/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs
new file mode 100644
index 00000000..a0271780
--- /dev/null
+++ b/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs
@@ -0,0 +1,49 @@
+using Blog.Core.Common.HttpContextUser;
+using Blog.Core.Controllers;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Api.Controllers.Tenant;
+
+///
+/// 多租户测试
+///
+[Produces("application/json")]
+[Route("api/Tenant/ById")]
+[Authorize]
+public class TenantByIdController : BaseApiController
+{
+ private readonly IBaseServices _services;
+ private readonly IUser _user;
+
+ public TenantByIdController(IUser user, IBaseServices services)
+ {
+ _user = user;
+ _services = services;
+ }
+
+ ///
+ /// 获取租户下全部业务数据
+ ///
+ ///
+ [HttpGet]
+ public async Task>> GetAll()
+ {
+ var data = await _services.Query();
+ return Success(data);
+ }
+
+ ///
+ /// 新增业务数据
+ ///
+ ///
+ [HttpPost]
+ public async Task Post([FromBody] BusinessTable data)
+ {
+ await _services.Db.Insertable(data).ExecuteReturnSnowflakeIdAsync();
+ return Success();
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index 8ab4b93d..21bb55c0 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -4,6 +4,7 @@
using Autofac.Extensions.DependencyInjection;
using Blog.Core;
using Blog.Core.Common;
+using Blog.Core.Common.Core;
using Blog.Core.Common.LogHelper;
using Blog.Core.Common.Seed;
using Blog.Core.Extensions;
@@ -13,7 +14,6 @@
using Blog.Core.Hubs;
using Blog.Core.IServices;
using Blog.Core.Tasks;
-using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
@@ -132,6 +132,7 @@
// 3、配置中间件
var app = builder.Build();
+app.ConfigureApplication();
if (app.Environment.IsDevelopment())
{
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.excel/SysUserInfo.xlsx b/Blog.Core.Api/wwwroot/BlogCore.Data.excel/SysUserInfo.xlsx
index 51c0e125ec7a2b31b7d3e932bee4a0cde662b4d0..6a1e4ca6b01b92e1ab3095a7090a48ed41119a21 100644
GIT binary patch
delta 4254
zcmZ9PcTf{*v&MsT1OkMjbV89XMF|2*=+a9lqJZ>XgiwTtL8>4<^p1cS2{rU8geKB!
zM0yF)0|L@T;Ck+zIp==g{3V;aVpwD&a#8&_Dprn@P^Y&S)1<9e8GrYw9}3m2*N9{?
zi;LqVvpfMTvUaGRcvYj0*|~-?Km)mV7)$xkDLl)=?Zqd+3^a63kHyNFM5yr%<7e>A
z15d^kLl>k&MT~K=8!L=YmUV^0d?lj$E95-g)IwIIngQUb5eBM+FZ;#`+lfecW@BlU
z;AoQ%c4$_E6fwz9#fhO_<>Cgk*yEJc)I@Uz#=2)NYidyPs>n|3ZWDF_XflRQS<&f8mXurGhUp_X^F;%1WmjmYa8y-QBTH
zy}gGiY2Un;f5&9GIm&E6`(pwXw-LCSxo=5}id34xF9qDts0IaE|1d?~
zD6Tm~tEW=$kuJCLcyqv9rc?i|cl(RkVI%jRk6M~35eLO5eulf$Vt6AHjoq&Fv7RUA
zH5m6T@}z)ks@q2kBW(`-Y}8UhHo!O^dJdfU$0zYUEG5!b8PZSU^R&{wgV^5B@DF{L
zY`NM$zx+Jb)zx`H>oMw6^-(5~|5yHj(bSZKk>c`4@5!g}QE-v&%EkpQsilu*46;{B}GVudef&G+7H
zFB;eRt`mh=luo)UkzvDzsSsYhdoOxs1kJnzg5`V`Rl@^Q21G^SHajwh2LsMBS_N{Y
zL$S#$pU1P^{IQp(b^&SMjdyR#a!Z*is39D_J2AMnx(H5mVl2rGY0yX=`<04$@>cWs
z4Z8QtD$LQ?B7t^Q37kp7YO+SR$T|31v17WMHZ!OfdKEI}v4hu9h^`X&zHemsUfiPy
z@7F!j!lz-Qo!Qi;BU;B&vkOY3J~E(LVtnzgN)LWzR+b7AY!HtJ4y$}U_-p5OxCYd9
z>@ei2#Pu1c@NsWt7%9^1uruS?BwT~^%VEAFwqQ6>R|2RsHojbg(C4*BP{+JM90MyY
z5)6M#hX?{S_u>{slBOHvmvgbUE0Fl`BT=HoCMT_3%!-J)BN1eC*JR*(PxpMoU
zIuCJrRn?uj2^onETin3#QrdNXUbpBELXd_Euo{$wnXi6NUntP70pGj3KM2Rh(4K3v
z8~CR2CUMuNY^t3UMKnQOD@atg!=|Q_N(Az|qR3j<1=KBM_F~Vspb^^uZ|5~px5Ph*Z*zKNQ8C`s}MU}_?JlP@bSF;6a>XKZ<
z4L0$_)n)X3&Sa|~g}ojXzLtIr(T_ghSobRSsZ#v;e@>)t?)D
zbrqSl=sgc*hz0z_#7M>C$rQhV4*%hnb!ehM&Y_3pvjG>sQc|r}LWW5#rnxLN
zAY;M!vkl*Xu|iRb=9eHS+(i82yY!Axz-UA&Inh6kd{0S~b>%>#7En|jM}B;)UHg&n
z5++{Lwwzyv)FsqZD`(vZ^#7h{f-JDVP-=OGEQIuz^r|aq==G8^duYK8CxFS{R-SxS
z7kH=L`VnSJEGxE%wy7B5{_<;u+=IyYXi!^!ntfBzoXTeEmUwSg>qPO$;HrA;YT0P^
zYrTO2ai(+;4RYA>{0*4eZMqJb!^d8Y#lrTmj!NTV2SgNJ*h!v+HaB;Ry>T@wX_a;Z
zsi*F#7kLIdZG$bOBI0N~I~$}uqixtjoQMtc+bNa6Xcx64Uf5k@kF?!Ke2zLII00L|
zEd>}G{W^YMYf5l)KO)E^xebBaWS>(8E1~WAtojNJo#G2^Ey}V^%Fc(
zJ4^O!eAerxHPt>%<5we1a>(eBab2})+79zvFX6ay{i8sT@#oVpIuxN-K2HAG2K8v6NPv$awl7sQInV$yXVL1!6K^Br}Ae~U)ldR>09AT
zChr6$peNRLBS6gnExS(5_5`+sE~>XwCdZfF_`J>UFunDuXCgpP;75f
z)?AWF17{T1(Kd7z5m@^j&Xs9FRSiS_p8RARPv)iAV}IWHee(o}ZDUlULKg6Vtn^3$
zfH^7vfbRdC3fw=~(+U2!Pr;aXC9SJ7|42FI(Ufc+`irL)u3Zxf&Ta6Y8rnC3`lpC7|*)-i~xXuC5sfK9y_+GhJfwH_9lJc~fyqA!n1eQZvkeRki{te!XM
z+h|8i%o~0tUS)cb*Y}l`K82QZ$1(@UEf|Rvq6FWr-h;5S)G<l~louj^Hm8cfxR
z<4>V_{YWbVNwgqR$l5aEzg>e*CX7j!cxXI{_jW$9!eJ;eXsL3~WtFHPXh_(Z+wj+?
zHh;AFWENucpf=I|O?vd?k7k3nSGk#U-axW<@pOJsftepu1dYB#3#Z@!T-z0)bdRa!
zBe^mIm+oUBG`kT}+!A~9VU~3nA0pM1CDTUJ1>;ST6oJr*k=f1!%xX(U|HtmZ)YP>E
z<}Ay~a~4W9Tq9$@q?g0#TZQf=vyy9(tPa?w23P%u8@7SZ7eB5gO(<+LdeY_|UDmi-
z(4Fo+=4wYx*RZd)I-hga)x^*?7ua$c;6p_^qmJEhbLyL3ZS8DF-JHvsp+EvE<_E4r
z`mrEVrOo(NUfKZfojN+c0Pp4Yv%j`{ipRKnRsV{XQR`Dqqp;0rbErKtr*$|-K8aRi
z7Oqbqtl)seS{S#+?4MSTmiG@g4+198_9M`l>j*-7g{Wz_+Xu!kcPPI`rEk8NhGb?=!tr+^OO;AA
z`Ye~NTzc|&^6pQ8RM~edDJ6dq9u0j8M)7frBM0xiQ|gj-nvh;0fscdEif&P|RTz)n
zo=QCuzelu`-6N}gE@8ee7SC$^t0Hv>Z8RgDJN`H${&SRGkf>XzwML2D8%N#X0d>>C
z(yEHqH%j2dHFR`7uI{cGYhpc1a(jk@ex}o1(BpA(Mr^qDyK)ST9EZwN{et|usw%Xi
zIkK6-gPXk4J4u8G9T6d=%};Ec<0pH?(IfoRA)ITihd~h^^WpN@y1~JY1|($fx6Q$Z
z^+AY5S*`?~`<95G8H5G%qsQOr;0%GifX+-}hFe&z31Tn_2%mu?f?j85I>30PMTNP|
zZpDsDjptT@dq-ExOe<&SvX`9lhdf7B{;Ly4u|U~HyBV%%)ZFKf3%`woRH{OL8gZjCa1DfrjG?Gv9-zXG42^Lfq-RKS+?tc
zb?0VMJ~_$V;gTpXsdQrHa^+F;BqiE20KW3SqALdR%Cs4vdF*+Tr|KdSw?|5lF3O$l
z?hh8tfHp-<{quq}MmYjf384c~+?w1%BHeiE#ap7`n6bp`F(6tJFsrxa>^;zcYY>+;IuHz
z{2X`VH`(8Qh!kL?OG?HJpa7t%Nhz?Jyw^yn6TZGYzeNH7>|>4jrAUz1)zrSeLf!WQ
z%ln?PrnX7qUnHxyU7k2EVh+}&^Weyn1(f?sBkP|eqq-#?X)a`fMJ2{#05BZj;Zj`<$N)ovk-hFvC#OPXa3Y8eWv
z`ZD$*v)3f4vhB!UQL`d%Jh%o^WSqDuavE8`Tg5>V?m&dTqUYYSOzi3)$@_UlA3qcY
z`y_>bK6USh;FCR+d<)RVpuck$+sWzB`}^Kfm4)Ft8a+KwC0|6q8xFj9G$0zp)Vny2
zf!@5ZW%Yi)_q2iO#jw^)FgRB1o5)J$p^4-Vi0(9VsW8l>)UlE2lS|sdI~UJ3tQ`X46}`-1=g
delta 4220
zcmZWsbyO2<-yR?_T0$izDH|P94kRQb2GSwjATbc7VM-~2)aVVVQ3FOx2?zosq+~Ec
zBoq*7Bt+`-dEWCr&-uRZ{_8&HzJCAwuKQfkZeDI)GfRQkpa=*VCj|iXC;$Kk000o=
zB_0TW?CA)Hdx`~ldtpq6eP&e{JIsG5ScJ-5kkHmT76LS06U+=z0@pF_mf}IELtL9J
zJ|D8Cq*85aS8)8c8hIoG^>m_IN)@>F@gm{m2$c=b_)z3BSmlX*ET9qnE+bw<=w(8-
zh5GleGl-sTK4GFoPnNDKUqj&?DEqrGKMS3wGRXZwQb5Xm$T*Y+1O@~3{Jx~Ju`Xuo
zraRK&%1czD@6d5O2pdn(P7>H(Kn^R{4FmKt9EPZi-{@}YB1Mf&oukdR>*om{2KuDV$lh46G_@OJ&UVzOCrI%Ddwdc$@s
zDv9ESf8Tnrs11$Vi~>4G$IsahywbZ?Q()6VQWGB+4J+k#4_ew3oQY$W=^sf}kq`vZTtNNOtH&kb0^y3k+
z*~+QXFJ26|G7%ctcRK%*E48oZ+rV>#`eYa3=L_wqER*T}BNJhoRq$6igI0!L?9{-=
zam4Tl()9h=%*e8_ws-4v3?X0br5lpkM|!rK&)?4Pkax_(xembL3uF^5G4>{mOmQ^1
zl`@X`d;}8J&6Y3AE?@UP*Vyl6^u2D2@Vc!e@p@P+1Ajli|$>2)WPU1*gTSzYfeo+eJ5
zG1FdZT>Ig(inneY=@Otu9X4h4AMvf)_cBfaq`=X7svY381L7p{2EuQU80
zHE`S)t{)s&XF3*7vF5vS7)bIHzs{;O0Z)=OrKPm7Ma&ZFJ$(6t^znjvD*BNNp)dA5
zXXBmDyBCT%_oI(s@KNPg6s0My;-7)?2Di8nxDowqyYEva%_ILn!mLDpmgHXM6TLnO=w?B?%L!k;HUB#Yjg#y!}V(5njzpaW9NXx&iYAL-`A|J07S
z<2*~^u=(sKW9i<3PKnBFPt-VG7r$770MTnE#ou4aKF#T7#;FN-$Pd*$f%@N<9x)@2
z9IVQ&4gBokUpv)oJ}^_7DVXgd-xd(E8S|JqDL49SjjhnxNNUt1)QV2ya+E1ZW|tce
zIrOWhfQ8J_I$GDr$6hy@lqqBy6<|G)S?Rt0HeMJTkG2Z!gOy;RB8XgmESFe087j@(dKTowJ
z66h&stt4(Qi=D(de>*%`+t?_Ux6z+FoZIOvY8noL-psv3N94}inaS#%C&j
z9C8f{_;GsVb2oSa2Nox)-vpN+ptbSLar!KNypwUK@+s>*YUr%>9$TjMpeLvyYjB4S
z@5ZgV^u#p&IzoyNu6`^Iy3N`r-ve~V@NCe#C-Ree%{CJS-v{#-0df=70i(=ufIK)q
z>9Y_V4F*8t;NZY
z>2a_ZZ$yj+O$aZ`;odLHmoj7R*dp{$-s&1&(sS&r&_=VDda<-^_Z<97r9Mn4S29nN
zwMbn>NiDGmO1;t}P@xcTZz|M($L^M$bX}e9=j%_SC$O(5m{MgACNJ?Dz}(Q~$Pate
z$F?|_GxWe&vIwT}I_vjTY!-Wj$FKAyV#7=<_CEHlW{iFnt0R&p3R^RLM;5$LQye5L
z#9S-L4DY?uEAS|KxJfp8cvtsBHEn0fux#P7PtnX2qHOGtD5UBo<=ouP@|GOG`t2DV
zZqqv3z`GRIEEP}w|K@HI&K7+%DzI@FxsKUMoyrQ$&@By8{#C}Ymnw1r^P
zZ=MpGU?`7y$!+(dmy1?l3EYSP)DK)$qe5tVy*bk-0|26c007;80*e2WU@sT{zv4-c
z+1;c$*&AQT4wM<$bF@ntbQ8C9sF!~Nsgfy3wyB>q$7DcI5M`EBXun|VQ^=U4S|(2Q
ztv={e!DWg0f!jf`^9=%AVTvS#`saB=7S4Yj`_^o~+
zgLft|hLXj&kA9unI}Om!ROY3Y*6;BAXulU1YYlYo{*vLdpb!9O`9kiX2wi+iUGFSv
z3e-~;OS?J9q$xy(xN7jEz7fvn8H6jA9J^s@Wb`hD^fqc^smFGVQMP-!rTs<+&d0ZD
zvJ9~Fs`ks=!vN(UCCUs?(bh=8Vd?FAr9Bz7_SgAS$3`^@frQkQFsU-q7IU
zkwcUmqW$8gYqx>LMy!-tuX38CZ^l-wWSAAKZv=~Tp?{b!sAIGgn;riFPq;H^mzpZ8
zsJI!TS&dnT7_C8+YtK1gRrH^7!0g+$K}DM5gp(t$6Z;P6kXqoXxSNkOPpv{yrm$S1
zerAQK(y^N7`E%odC0YBxb%qQG~udVI%AN@-7pFEDt&l{Wi732T`C%ob@SBvd~@B=e0
zm!svJyA>`%2QMi83P->&1tpc-KZQUQnE>KIq?rzT5>z&nG
zvwZjXwRP844w!(atJ&Ne>`O}4IbO#-Oy(QHD@a7-WrD}4Tb8%R512^M$56O!#18&j
zv0SIwwLWjN_;<_U6WR58QF{*QD`5n=%*;qtlo7|&~Z<*a+!ET
zwDo{^E8VyN>m*yyD8iOWlf7;7>37L1P48<18T*NGWy#t$=1;E&!#MHAbP6wAJh392
z9>UzgqWB!Kp+^D@`82$)u-sCS4e2*A^T2|Akuk8h3P=k^YPXB)zcxLgWcZq)%DZW;Ws*RbL@l><8N3WA&dE#
z^}*GlB-gb9Y_Vmwzi8`6^OA=?_t5=EoN2Ry(U4tx#$E|p#m&}&B<2T=O4GAGHi=4`
zGFEve`cgay(~tDNue3Jeo-wy|aK!kLGH;Sz2_rSeRDaj5KippYT2yrIrjJ+9&x)E4
zKU~x?e4XfD5siv9q-N}n;AG+oVpQY&MHK{zi+k}20joLL+TE)7uthmMg3Fi~pOT8F
zZ%E>K`e*Jx`v4oTigQ4&k#dg`x0?$kXa~ee(hqr1w8qJi)qq+y>GD39XBW<
zQG6(yd7ZT>jf3)d#KKoK@&T`Q=%DxO03M51wQC9nAKk_aikfBgYZ>!!y%~GvQ>0>4
z*-qrof!7c>lmNyGSI2>ZzoHx9I1Z9Xr|&Ay>2I!CCU&-yp!YB769%)52PCG0CIq+d
zSnU?cw;bE*_jT;lcW^rOoZX4AUAUW2T4Kc2y8J9hO&Rpl0aWo>hmolEp+OFMGA%i8
z_N&?&s6>JJA)VTjdyuuO8zKbvkrO7cU?4_yS_8~sYPj!}nBL9e?oN{7=G8TEnY_Pu
z)ppB(4ERrFN3sa&lMEuA1VuUiZ88ABjXy5=?>R?S2x^cxAom0X1pcp={)^gW`@8!8
z?W{
+
+
+
+
diff --git a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
new file mode 100644
index 00000000..3646625d
--- /dev/null
+++ b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
@@ -0,0 +1,86 @@
+using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model.Models.RootTkey.Interface;
+using SqlSugar;
+using System;
+
+namespace Blog.Core.Common.DB.Aop;
+
+public static class SqlSugarAop
+{
+ public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
+ {
+ if (entityInfo.EntityValue is BaseEntity root)
+ {
+ if (root.Id == 0)
+ {
+ root.Id = SnowFlakeSingle.Instance.NextId();
+ }
+ }
+
+ if (entityInfo.EntityValue is BaseEntity baseEntity)
+ {
+ // 新增操作
+ if (entityInfo.OperationType == DataFilterType.InsertByObject)
+ {
+ if (baseEntity.CreateTime == DateTime.MinValue)
+ {
+ baseEntity.CreateTime = DateTime.Now;
+ }
+ }
+
+ if (entityInfo.OperationType == DataFilterType.UpdateByObject)
+ {
+ baseEntity.ModifyTime = DateTime.Now;
+ }
+
+
+ if (App.User?.ID > 0)
+ {
+ if (baseEntity is ITenantEntity tenant && App.User.TenantId > 0)
+ {
+ if (tenant.TenantId == 0)
+ {
+ tenant.TenantId = App.User.TenantId;
+ }
+ }
+
+ switch (entityInfo.OperationType)
+ {
+ case DataFilterType.UpdateByObject:
+ baseEntity.ModifyId = App.User.ID;
+ baseEntity.ModifyBy = App.User.Name;
+ break;
+ case DataFilterType.InsertByObject:
+ if (baseEntity.CreateBy.IsNullOrEmpty() || baseEntity.CreateId is null or <= 0)
+ {
+ baseEntity.CreateId = App.User.ID;
+ baseEntity.CreateBy = App.User.Name;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ private static string GetWholeSql(SugarParameter[] paramArr, string sql)
+ {
+ foreach (var param in paramArr)
+ {
+ sql = sql.Replace(param.ParameterName, $@"'{param.Value.ObjToString()}'");
+ }
+
+ return sql;
+ }
+
+ private static string GetParas(SugarParameter[] pars)
+ {
+ string key = "【SQL参数】:";
+ foreach (var param in pars)
+ {
+ key += $"{param.ParameterName}:{param.Value}\n";
+ }
+
+ return key;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/RepositorySetting.cs b/Blog.Core.Common/DB/RepositorySetting.cs
new file mode 100644
index 00000000..c80ec7f8
--- /dev/null
+++ b/Blog.Core.Common/DB/RepositorySetting.cs
@@ -0,0 +1,43 @@
+using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model.Models.RootTkey.Interface;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Blog.Core.Common.DB;
+
+public class RepositorySetting
+{
+ private static readonly Lazy> AllEntitys = new(() =>
+ {
+ return typeof(BaseEntity).Assembly
+ .GetTypes()
+ .Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(BaseEntity)))
+ .Where(it => it.FullName != null && it.FullName.StartsWith("Ivytalk.FoodSafety.Model.Models"));
+ });
+
+ public static IEnumerable Entitys => AllEntitys.Value;
+
+ ///
+ /// 配置实体软删除过滤器
+ /// 统一过滤 软删除 无需自己写条件
+ ///
+ public static void SetDeletedEntityFilter(SqlSugarScopeProvider db)
+ {
+ db.QueryFilter.AddTableFilter(it => it.IsDeleted == false);
+ }
+
+ ///
+ /// 配置租户
+ ///
+ public static void SetTenantEntityFilter(SqlSugarScopeProvider db)
+ {
+ if (App.User is not { ID: > 0, TenantId: > 0 })
+ {
+ return;
+ }
+
+ db.QueryFilter.AddTableFilter(it => it.TenantId == App.User.TenantId || it.TenantId == 0);
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Extensions/AssemblysExtensions.cs b/Blog.Core.Common/Extensions/AssemblysExtensions.cs
index 06fa943b..5e5d4349 100644
--- a/Blog.Core.Common/Extensions/AssemblysExtensions.cs
+++ b/Blog.Core.Common/Extensions/AssemblysExtensions.cs
@@ -12,7 +12,7 @@ public static List GetAllAssemblies()
{
var list = new List();
var deps = DependencyContext.Default;
- var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package" && lib.Name.StartsWith("Baiqian"));
+ var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package" );
foreach (var lib in libs)
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
diff --git a/Blog.Core.Common/HttpContextUser/AspNetUser.cs b/Blog.Core.Common/HttpContextUser/AspNetUser.cs
index e4e27d87..b37e4a24 100644
--- a/Blog.Core.Common/HttpContextUser/AspNetUser.cs
+++ b/Blog.Core.Common/HttpContextUser/AspNetUser.cs
@@ -5,6 +5,7 @@
using Blog.Core.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
+using SqlSugar.Extensions;
namespace Blog.Core.Common.HttpContextUser
{
@@ -40,6 +41,7 @@ private string GetName()
}
public int ID => GetClaimValueByType("jti").FirstOrDefault().ObjToInt();
+ public long TenantId => GetClaimValueByType("TenantId").FirstOrDefault().ObjToLong();
public bool IsAuthenticated()
{
@@ -87,11 +89,9 @@ public IEnumerable GetClaimsIdentity()
public List GetClaimValueByType(string ClaimType)
{
-
return (from item in GetClaimsIdentity()
where item.Type == ClaimType
select item.Value).ToList();
-
}
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/HttpContextUser/IUser.cs b/Blog.Core.Common/HttpContextUser/IUser.cs
index beef3b7d..3849bd38 100644
--- a/Blog.Core.Common/HttpContextUser/IUser.cs
+++ b/Blog.Core.Common/HttpContextUser/IUser.cs
@@ -8,6 +8,7 @@ public interface IUser
{
string Name { get; }
int ID { get; }
+ long TenantId { get; }
bool IsAuthenticated();
IEnumerable GetClaimsIdentity();
List GetClaimValueByType(string ClaimType);
@@ -17,4 +18,4 @@ public interface IUser
MessageModel MessageModel { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/BusinessDataSeedData.cs b/Blog.Core.Common/Seed/SeedData/BusinessDataSeedData.cs
new file mode 100644
index 00000000..361cd725
--- /dev/null
+++ b/Blog.Core.Common/Seed/SeedData/BusinessDataSeedData.cs
@@ -0,0 +1,79 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Blog.Core.Model.Models;
+using SqlSugar;
+
+namespace Blog.Core.Common.Seed.SeedData;
+
+///
+/// 初始化 业务数据
+///
+public class BusinessDataSeedData : IEntitySeedData
+{
+ public IEnumerable InitSeedData()
+ {
+ return new[]
+ {
+ new BusinessTable()
+ {
+ Id = 1,
+ TenantId = 1000001,
+ Name = "张三的数据01",
+ Amount = 150,
+ IsDeleted = true,
+ },
+ new BusinessTable()
+ {
+ Id = 2,
+ TenantId = 1000001,
+ Name = "张三的数据02",
+ Amount = 200,
+ },
+ new BusinessTable()
+ {
+ Id = 3,
+ TenantId = 1000001,
+ Name = "张三的数据03",
+ Amount = 250,
+ },
+ new BusinessTable()
+ {
+ Id = 4,
+ TenantId = 1000002,
+ Name = "李四的数据01",
+ Amount = 300,
+ },
+ new BusinessTable()
+ {
+ Id = 5,
+ TenantId = 1000002,
+ Name = "李四的数据02",
+ Amount = 500,
+ },
+ new BusinessTable()
+ {
+ Id = 6,
+ TenantId = 0,
+ Name = "公共数据01",
+ Amount = 16600,
+ },
+ new BusinessTable()
+ {
+ Id = 7,
+ TenantId = 0,
+ Name = "公共数据02",
+ Amount = 19800,
+ },
+ };
+ }
+
+ public IEnumerable SeedData()
+ {
+ return default;
+ }
+
+ public Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs b/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
new file mode 100644
index 00000000..89945547
--- /dev/null
+++ b/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Blog.Core.Model.CustomEnums;
+using Blog.Core.Model.Models;
+using SqlSugar;
+
+namespace Blog.Core.Common.Seed.SeedData;
+
+///
+/// 租户 种子数据
+///
+public class TenantSeedData : IEntitySeedData
+{
+ public IEnumerable InitSeedData()
+ {
+ return new[]
+ {
+ new SysTenant()
+ {
+ Id = 1000001,
+ ConfigId = "Tenant_1",
+ Name = "张三",
+ TenantType = TenantTypeEnum.Id
+ },
+ new SysTenant()
+ {
+ Id = 1000002,
+ ConfigId = "Tenant_2",
+ Name = "李四",
+ TenantType = TenantTypeEnum.Id
+ },
+ };
+ }
+
+ public IEnumerable SeedData()
+ {
+ return default;
+ }
+
+ public Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs b/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
new file mode 100644
index 00000000..c00eb798
--- /dev/null
+++ b/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Blog.Core.Model.Models;
+using SqlSugar;
+
+namespace Blog.Core.Common.Seed.SeedData;
+
+public class UserInfoSeedData : IEntitySeedData
+{
+ public IEnumerable InitSeedData()
+ {
+ return default;
+ }
+
+ public IEnumerable SeedData()
+ {
+ return new[]
+ {
+ new SysUserInfo()
+ {
+ Id = 10001,
+ LoginName = "zhangsan",
+ LoginPWD = "E10ADC3949BA59ABBE56E057F20F883E",
+ Name = "张三",
+ TenantId = 1000001, //租户Id
+ },
+ new SysUserInfo()
+ {
+ Id = 10002,
+ LoginName = "lisi",
+ LoginPWD = "E10ADC3949BA59ABBE56E057F20F883E",
+ Name = "李四",
+ TenantId = 1000002, //租户Id
+ },
+ };
+ }
+
+ public Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.EventBus/Blog.Core.EventBus.csproj b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
index 070c0a48..09d4e6a2 100644
--- a/Blog.Core.EventBus/Blog.Core.EventBus.csproj
+++ b/Blog.Core.EventBus/Blog.Core.EventBus.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index 50969b05..451d24f1 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -21,7 +21,7 @@
-
+
diff --git a/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs b/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs
index 6ff8d044..4c61ed3b 100644
--- a/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/RequRespLogMiddleware.cs
@@ -7,7 +7,6 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
-using Ubiety.Dns.Core.Common;
namespace Blog.Core.Extensions.Middlewares
{
diff --git a/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs b/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
index b3eb4bdc..3ecf224a 100644
--- a/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
@@ -9,6 +9,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Blog.Core.Common.DB.Aop;
namespace Blog.Core.Extensions
{
@@ -101,7 +102,21 @@ public static void AddSqlsugarSetup(this IServiceCollection services)
}
);
});
- return new SqlSugarScope(listConfig);
+ return new SqlSugarScope(listConfig, db =>
+ {
+ listConfig.ForEach(config =>
+ {
+ var dbProvider = db.GetConnectionScope((string)config.ConfigId);
+
+ // 数据审计
+ dbProvider.Aop.DataExecuting = SqlSugarAop.DataExecuting;
+
+ // 配置实体假删除过滤器
+ RepositorySetting.SetDeletedEntityFilter(dbProvider);
+ // 配置实体数据权限
+ RepositorySetting.SetTenantEntityFilter(dbProvider);
+ });
+ });
});
}
diff --git a/Blog.Core.IServices/BASE/IBaseServices.cs b/Blog.Core.IServices/BASE/IBaseServices.cs
index 27daae98..7856f8bf 100644
--- a/Blog.Core.IServices/BASE/IBaseServices.cs
+++ b/Blog.Core.IServices/BASE/IBaseServices.cs
@@ -10,6 +10,7 @@ namespace Blog.Core.IServices.BASE
{
public interface IBaseServices where TEntity : class
{
+ ISqlSugarClient Db { get; }
Task QueryById(object objId);
Task QueryById(object objId, bool blnUseCache = false);
diff --git a/Blog.Core.Model/Blog.Core.Model.csproj b/Blog.Core.Model/Blog.Core.Model.csproj
index 67bb5ad7..e66c5c5b 100644
--- a/Blog.Core.Model/Blog.Core.Model.csproj
+++ b/Blog.Core.Model/Blog.Core.Model.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/Blog.Core.Model/CustomEnums/TenantTypeEnum.cs b/Blog.Core.Model/CustomEnums/TenantTypeEnum.cs
new file mode 100644
index 00000000..a445414b
--- /dev/null
+++ b/Blog.Core.Model/CustomEnums/TenantTypeEnum.cs
@@ -0,0 +1,23 @@
+using System.ComponentModel;
+
+namespace Blog.Core.Model.CustomEnums;
+
+///
+/// 租户隔离方案
+///
+public enum TenantTypeEnum
+{
+ None = 0,
+
+ ///
+ /// Id隔离
+ ///
+ [Description("Id隔离")]
+ Id = 1,
+
+ ///
+ /// 库隔离
+ ///
+ [Description("库隔离")]
+ Db = 2,
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/BusinessTable.cs b/Blog.Core.Model/Models/BusinessTable.cs
new file mode 100644
index 00000000..01a18716
--- /dev/null
+++ b/Blog.Core.Model/Models/BusinessTable.cs
@@ -0,0 +1,27 @@
+using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model.Models.RootTkey.Interface;
+
+namespace Blog.Core.Model.Models;
+
+///
+/// 业务数据
+/// 多租户 (Id 隔离)
+///
+public class BusinessTable : BaseEntity, ITenantEntity
+{
+ ///
+ /// 无需手动赋值
+ ///
+ public long TenantId { get; set; }
+
+
+ ///
+ /// 名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 金额
+ ///
+ public decimal Amount { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/RootTkey/BaseEntity.cs b/Blog.Core.Model/Models/RootTkey/BaseEntity.cs
new file mode 100644
index 00000000..efbde8fd
--- /dev/null
+++ b/Blog.Core.Model/Models/RootTkey/BaseEntity.cs
@@ -0,0 +1,86 @@
+using Blog.Core.Model.Models.RootTkey.Interface;
+using SqlSugar;
+using System;
+
+namespace Blog.Core.Model.Models.RootTkey;
+
+public class BaseEntity : IDeleteFilter
+{
+ ///
+ /// 雪花Id
+ ///
+ [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = false)]
+ public long Id { get; set; }
+
+ #region 数据状态管理
+
+ ///
+ /// 状态
+ /// 中立字段,某些表可使用某些表不使用
+ ///
+ public bool Enabled { get; set; } = true;
+
+ ///
+ /// 中立字段,某些表可使用某些表不使用
+ /// 逻辑上的删除,非物理删除
+ /// 例如:单据删除并非直接删除
+ ///
+ public bool IsDeleted { get; set; }
+
+ ///
+ /// 中立字段
+ /// 是否内置数据
+ ///
+ public bool IsInternal { get; set; }
+
+ #endregion
+
+ #region 创建
+
+ ///
+ /// 创建ID
+ ///
+ [SugarColumn(IsNullable = true, IsOnlyIgnoreUpdate = true)]
+ public long? CreateId { get; set; }
+
+ ///
+ /// 创建者
+ ///
+ [SugarColumn(IsNullable = true, IsOnlyIgnoreUpdate = true)]
+ public string CreateBy { get; set; }
+
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(IsOnlyIgnoreUpdate = true)]
+ public DateTime CreateTime { get; set; } = DateTime.Now;
+
+ #endregion
+
+ #region 修改
+
+ ///
+ /// 修改ID
+ ///
+ [SugarColumn(IsNullable = true)]
+ public long? ModifyId { get; set; }
+
+ ///
+ /// 更新者
+ ///
+ [SugarColumn(IsNullable = true)]
+ public string ModifyBy { get; set; }
+
+ ///
+ /// 修改日期
+ ///
+ public DateTime? ModifyTime { get; set; } = DateTime.Now;
+
+ ///
+ /// 数据版本
+ ///
+ [SugarColumn(DefaultValue = "0", IsEnableUpdateVersionValidation = true)] //标识版本字段
+ public long Version { get; set; }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/RootTkey/Interface/IDeleteFilter.cs b/Blog.Core.Model/Models/RootTkey/Interface/IDeleteFilter.cs
new file mode 100644
index 00000000..57d421e9
--- /dev/null
+++ b/Blog.Core.Model/Models/RootTkey/Interface/IDeleteFilter.cs
@@ -0,0 +1,9 @@
+namespace Blog.Core.Model.Models.RootTkey.Interface;
+
+///
+/// 软删除 过滤器
+///
+public interface IDeleteFilter
+{
+ public bool IsDeleted { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs b/Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs
new file mode 100644
index 00000000..350312b8
--- /dev/null
+++ b/Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs
@@ -0,0 +1,15 @@
+using SqlSugar;
+
+namespace Blog.Core.Model.Models.RootTkey.Interface;
+
+///
+/// 租户模型接口
+///
+public interface ITenantEntity
+{
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(DefaultValue = "0")]
+ public long TenantId { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/RootTkey/RootEntityTkey.cs b/Blog.Core.Model/Models/RootTkey/RootEntityTkey.cs
index afecdec9..20bdda0d 100644
--- a/Blog.Core.Model/Models/RootTkey/RootEntityTkey.cs
+++ b/Blog.Core.Model/Models/RootTkey/RootEntityTkey.cs
@@ -11,7 +11,5 @@ public class RootEntityTkey where Tkey : IEquatable
///
[SugarColumn(IsNullable = false, IsPrimaryKey = true)]
public Tkey Id { get; set; }
-
-
}
}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/SysTenant.cs b/Blog.Core.Model/Models/SysTenant.cs
new file mode 100644
index 00000000..7e6f195d
--- /dev/null
+++ b/Blog.Core.Model/Models/SysTenant.cs
@@ -0,0 +1,67 @@
+using Blog.Core.Model.CustomEnums;
+using SqlSugar;
+
+namespace Blog.Core.Model.Models;
+
+///
+/// 系统租户表
+/// 根据TenantType 分为两种方案:
+/// 1.按租户字段区分
+/// 2.按租户分库
+///
+///
+///
+/// 注意:
+/// 使用租户Id方案,无需配置分库的连接
+///
+public class SysTenant : RootEntityTkey
+{
+ ///
+ /// 名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 租户类型
+ ///
+ public TenantTypeEnum TenantType { get; set; }
+
+ ///
+ /// 数据库/租户标识 不可重复
+ /// 使用Id方案,可无需配置
+ ///
+ [SugarColumn(Length = 64)]
+ public string ConfigId { get; set; }
+
+ ///
+ /// 主机
+ /// 使用Id方案,可无需配置
+ ///
+ [SugarColumn(IsNullable = true)]
+ public string Host { get; set; }
+
+ ///
+ /// 数据库类型
+ /// 使用Id方案,可无需配置
+ ///
+ [SugarColumn(IsNullable = true)]
+ public SqlSugar.DbType? DbType { get; set; }
+
+ ///
+ /// 数据库连接
+ /// 使用Id方案,可无需配置
+ ///
+ [SugarColumn(IsNullable = true)]
+ public string Connection { get; set; }
+
+ ///
+ /// 状态
+ ///
+ public bool Status { get; set; } = true;
+
+ ///
+ /// 备注
+ ///
+ [SugarColumn(IsNullable = true)]
+ public string Remark { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/sysUserInfo.cs b/Blog.Core.Model/Models/sysUserInfo.cs
index c60e4bce..366b2291 100644
--- a/Blog.Core.Model/Models/sysUserInfo.cs
+++ b/Blog.Core.Model/Models/sysUserInfo.cs
@@ -8,7 +8,7 @@ namespace Blog.Core.Model.Models
/// 用户信息表
///
//[SugarTable("SysUserInfo")]
- [SugarTable("SysUserInfo", "用户表")]//('数据库表名','数据库表备注')
+ [SugarTable("SysUserInfo", "用户表")] //('数据库表名','数据库表备注')
public class SysUserInfo : SysUserInfoRoot
{
public SysUserInfo()
@@ -120,6 +120,14 @@ public SysUserInfo(string loginName, string loginPWD)
[SugarColumn(IsNullable = true)]
public bool IsDeleted { get; set; }
+ ///
+ /// 租户Id
+ ///
+ [SugarColumn(IsNullable = false,DefaultValue = "0")]
+ public long TenantId { get; set; }
+
+ [Navigate(NavigateType.OneToOne, nameof(TenantId))]
+ public SysTenant Tenant { get; set; }
[SugarColumn(IsIgnore = true)]
public List RoleNames { get; set; }
diff --git a/Blog.Core.Services/BASE/BaseServices.cs b/Blog.Core.Services/BASE/BaseServices.cs
index ec685be2..f8105165 100644
--- a/Blog.Core.Services/BASE/BaseServices.cs
+++ b/Blog.Core.Services/BASE/BaseServices.cs
@@ -17,13 +17,17 @@ public BaseServices(IBaseRepository BaseDal = null)
{
this.BaseDal = BaseDal;
}
+
//public IBaseRepository baseDal = new BaseRepository();
- public IBaseRepository BaseDal { get; set; }//通过在子类的构造函数中注入,这里是基类,不用构造函数
+ public IBaseRepository BaseDal { get; set; } //通过在子类的构造函数中注入,这里是基类,不用构造函数
+
+ public ISqlSugarClient Db => BaseDal.Db;
public async Task QueryById(object objId)
{
return await BaseDal.QueryById(objId);
}
+
///
/// 功能描述:根据ID查询一条数据
/// 作 者:AZLinli.Blog.Core
@@ -76,21 +80,23 @@ public async Task Update(TEntity entity)
{
return await BaseDal.Update(entity);
}
+
public async Task Update(TEntity entity, string where)
{
return await BaseDal.Update(entity, where);
}
+
public async Task Update(object operateAnonymousObjects)
{
return await BaseDal.Update(operateAnonymousObjects);
}
public async Task Update(
- TEntity entity,
- List lstColumns = null,
- List lstIgnoreColumns = null,
- string where = ""
- )
+ TEntity entity,
+ List lstColumns = null,
+ List lstIgnoreColumns = null,
+ string where = ""
+ )
{
return await BaseDal.Update(entity, lstColumns, lstIgnoreColumns, where);
}
@@ -127,7 +133,6 @@ public async Task DeleteByIds(object[] ids)
}
-
///
/// 功能描述:查询所有数据
/// 作 者:AZLinli.Blog.Core
@@ -181,7 +186,7 @@ public async Task> Query(Expression查询实体条件
/// 排序条件
///
- public async Task> Query(Expression> expression, Expression> whereExpression,string orderByFileds)
+ public async Task> Query(Expression> expression, Expression> whereExpression, string orderByFileds)
{
return await BaseDal.Query(expression, whereExpression, orderByFileds);
}
@@ -224,7 +229,6 @@ public async Task> Query(string where, string orderByFileds)
public async Task> QuerySql(string sql, SugarParameter[] parameters = null)
{
return await BaseDal.QuerySql(sql, parameters);
-
}
///
@@ -236,8 +240,8 @@ public async Task> QuerySql(string sql, SugarParameter[] parameter
public async Task QueryTable(string sql, SugarParameter[] parameters = null)
{
return await BaseDal.QueryTable(sql, parameters);
-
}
+
///
/// 功能描述:查询前N条数据
/// 作 者:AZLinli.Blog.Core
@@ -283,10 +287,10 @@ public async Task> Query(
string orderByFileds)
{
return await BaseDal.Query(
- whereExpression,
- pageIndex,
- pageSize,
- orderByFileds);
+ whereExpression,
+ pageIndex,
+ pageSize,
+ orderByFileds);
}
///
@@ -299,34 +303,34 @@ public async Task> Query(
/// 排序字段,如name asc,age desc
/// 数据列表
public async Task> Query(
- string where,
- int pageIndex,
- int pageSize,
- string orderByFileds)
+ string where,
+ int pageIndex,
+ int pageSize,
+ string orderByFileds)
{
return await BaseDal.Query(
- where,
- pageIndex,
- pageSize,
- orderByFileds);
+ where,
+ pageIndex,
+ pageSize,
+ orderByFileds);
}
public async Task> QueryPage(Expression> whereExpression,
- int pageIndex = 1, int pageSize = 20, string orderByFileds = null)
+ int pageIndex = 1, int pageSize = 20, string orderByFileds = null)
{
return await BaseDal.QueryPage(whereExpression,
- pageIndex, pageSize, orderByFileds);
+ pageIndex, pageSize, orderByFileds);
}
public async Task> QueryMuch(Expression> joinExpression, Expression> selectExpression, Expression> whereLambda = null) where T : class, new()
{
return await BaseDal.QueryMuch(joinExpression, selectExpression, whereLambda);
}
+
public async Task> QueryPage(PaginationModel pagination)
{
var express = DynamicLinqFactory.CreateLambda(pagination.Conditions);
return await QueryPage(express, pagination.PageIndex, pagination.PageSize, pagination.OrderByFileds);
}
}
-
-}
+}
\ No newline at end of file
From 657e67d164b64996d2ee2ca790f81c3800304b8f Mon Sep 17 00:00:00 2001
From: HuiJiOnGit <40553940+HuiJiOnGit@users.noreply.github.com>
Date: Tue, 7 Feb 2023 08:30:39 +0800
Subject: [PATCH 019/190] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=9C=A8docke?=
=?UTF-8?q?r=E4=B8=AD=E6=97=A0=E6=B3=95=E8=BF=98=E5=8E=9F=E7=9A=84?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.sln | 1 +
Dockerfile | 1 +
2 files changed, 2 insertions(+)
diff --git a/Blog.Core.sln b/Blog.Core.sln
index c8f61505..c8989b24 100644
--- a/Blog.Core.sln
+++ b/Blog.Core.sln
@@ -30,6 +30,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionItems", "SolutionIt
Blog.Core.Publish.Docker.sh = Blog.Core.Publish.Docker.sh
Blog.Core.Publish.Linux.sh = Blog.Core.Publish.Linux.sh
codecov.yml = codecov.yml
+ build\common.targets = build\common.targets
CreateYourProject.bat = CreateYourProject.bat
DockerBuild.bat = DockerBuild.bat
Dockerfile = Dockerfile
diff --git a/Dockerfile b/Dockerfile
index 69a3d132..c80e6896 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -24,6 +24,7 @@ COPY ["Blog.Core.Services/Blog.Core.Services.csproj", "Blog.Core.Services/"]
COPY ["Blog.Core.IServices/Blog.Core.IServices.csproj", "Blog.Core.IServices/"]
COPY ["Blog.Core.Repository/Blog.Core.Repository.csproj", "Blog.Core.Repository/"]
COPY ["Blog.Core.Tasks/Blog.Core.Tasks.csproj", "Blog.Core.Tasks/"]
+COPY ["build", "build/"]
RUN dotnet restore "Blog.Core.Api/Blog.Core.Api.csproj"
COPY . .
WORKDIR "/src/Blog.Core.Api"
From 822e2ebd1fe6e4d848ad91f2556158410f8411bd Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 7 Feb 2023 10:39:00 +0800
Subject: [PATCH 020/190] Update DBSeed.cs
---
Blog.Core.Common/Seed/DBSeed.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 9afdc30d..9b2c911f 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -291,7 +291,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:TasksQz already exists...");
}
- #endregion
+ #endregion TasksQz
#region Department
if (!await myContext.Db.Queryable().AnyAsync())
From 552d94beb8d8fe6d1aa6fc002894d19f2444208c Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 11 Feb 2023 23:39:44 +0800
Subject: [PATCH 021/190] Update DBSeed.cs
---
Blog.Core.Common/Seed/DBSeed.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 9b2c911f..da313e3c 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -291,7 +291,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
Console.WriteLine("Table:TasksQz already exists...");
}
- #endregion TasksQz
+ #endregion
#region Department
if (!await myContext.Db.Queryable().AnyAsync())
@@ -322,4 +322,4 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
}
}
}
-}
\ No newline at end of file
+}
From 0228aed85fdd62946bb7bb0f64c1983f5cf0c538 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 12 Feb 2023 00:06:39 +0800
Subject: [PATCH 022/190] Update RepositorySetting.cs
---
Blog.Core.Common/DB/RepositorySetting.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Common/DB/RepositorySetting.cs b/Blog.Core.Common/DB/RepositorySetting.cs
index c80ec7f8..4f2e67d2 100644
--- a/Blog.Core.Common/DB/RepositorySetting.cs
+++ b/Blog.Core.Common/DB/RepositorySetting.cs
@@ -14,7 +14,7 @@ public class RepositorySetting
return typeof(BaseEntity).Assembly
.GetTypes()
.Where(t => t.IsClass && !t.IsAbstract && t.IsSubclassOf(typeof(BaseEntity)))
- .Where(it => it.FullName != null && it.FullName.StartsWith("Ivytalk.FoodSafety.Model.Models"));
+ .Where(it => it.FullName != null && it.FullName.StartsWith("Blog.Core.Model.Models"));
});
public static IEnumerable Entitys => AllEntitys.Value;
From d09de26d6ea095c626bdfa623a23d91d1902aae8 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Sun, 12 Feb 2023 22:00:04 +0800
Subject: [PATCH 023/190] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E4=B8=BB=E5=88=86?=
=?UTF-8?q?=E6=94=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 137 ++++++
Blog.Core.Api/Blog.Core.xml | 160 +++++++
Blog.Core.Api/Controllers/TrojanController.cs | 451 ++++++++++++++++++
Blog.Core.Api/Controllers/WeChatController.cs | 12 +
Blog.Core.Api/Dockerfile | 2 +-
Blog.Core.IServices/BASE/IBaseServices.cs | 1 +
Blog.Core.IServices/ITrojanUsersServices.cs | 14 +
Blog.Core.Model/Models/TrojanCusServers.cs | 26 +
Blog.Core.Model/Models/TrojanDetails.cs | 63 +++
Blog.Core.Model/Models/TrojanServers.cs | 31 ++
Blog.Core.Model/Models/TrojanUrlServers.cs | 26 +
Blog.Core.Model/Models/TrojanUsers.cs | 39 ++
.../ViewModels/TrojanLimitFlowDto.cs | 23 +
Blog.Core.Model/ViewModels/TrojanServerDto.cs | 14 +
.../ViewModels/TrojanServerSpliceDto.cs | 28 ++
.../ViewModels/TrojanUseDetailDto.cs | 35 ++
Blog.Core.Repository/BASE/BaseRepository.cs | 13 +
Blog.Core.Repository/BASE/IBaseRepository.cs | 6 +
Blog.Core.Services/BASE/BaseServices.cs | 9 +
Blog.Core.Services/TrojanUsersServices.cs | 18 +
Blog.Core.Tasks/Blog.Core.Tasks.csproj | 1 +
.../HostedService/Job1TimedService.cs | 60 +++
.../HostedService/Job2TimedService.cs | 47 ++
.../QuartzNet/Jobs/Job_Trojan_Quartz.cs | 79 +++
.../QuartzNet/Jobs/Job_URL_Quartz.cs | 51 ++
25 files changed, 1345 insertions(+), 1 deletion(-)
create mode 100644 Blog.Core.Api/Controllers/TrojanController.cs
create mode 100644 Blog.Core.IServices/ITrojanUsersServices.cs
create mode 100644 Blog.Core.Model/Models/TrojanCusServers.cs
create mode 100644 Blog.Core.Model/Models/TrojanDetails.cs
create mode 100644 Blog.Core.Model/Models/TrojanServers.cs
create mode 100644 Blog.Core.Model/Models/TrojanUrlServers.cs
create mode 100644 Blog.Core.Model/Models/TrojanUsers.cs
create mode 100644 Blog.Core.Model/ViewModels/TrojanLimitFlowDto.cs
create mode 100644 Blog.Core.Model/ViewModels/TrojanServerDto.cs
create mode 100644 Blog.Core.Model/ViewModels/TrojanServerSpliceDto.cs
create mode 100644 Blog.Core.Model/ViewModels/TrojanUseDetailDto.cs
create mode 100644 Blog.Core.Services/TrojanUsersServices.cs
create mode 100644 Blog.Core.Tasks/HostedService/Job1TimedService.cs
create mode 100644 Blog.Core.Tasks/HostedService/Job2TimedService.cs
create mode 100644 Blog.Core.Tasks/QuartzNet/Jobs/Job_Trojan_Quartz.cs
create mode 100644 Blog.Core.Tasks/QuartzNet/Jobs/Job_URL_Quartz.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 36975d11..ea9857bc 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -982,6 +982,76 @@
Tibug 博文
+
+
+ users自定义服务器
+
+
+
+
+ 用户流量每月汇总表
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Trojan服务器
+
+
+
+
+ users自定义URL服务器
+
+
+
+
+ Trojan用户
+
+
+
+
+ 历史流量记录
+
+
用户跟角色关联表
@@ -2407,6 +2477,73 @@
+
+
+ 限制流量dto
+ 作者:胡丁文
+ 时间:2020-4-27 16:57:07
+
+
+
+
+ 用户
+
+
+
+
+ 流量(-1为无限,单位为最小单位byte)
+
+
+
+
+ Trojan服务器拼接服务器和订阅地址
+
+
+
+
+ 普通订阅连接
+
+
+
+
+ clash订阅连接
+
+
+
+
+ 备用clash订阅连接
+
+
+
+
+ Trojan用户流量统计分组
+
+
+
+
+ 用户ID
+
+
+
+
+ 月度
+
+
+
+
+ 上传流量
+
+
+
+
+ 下载流量
+
+
+
+
+ 下载流量
+
+
微信接口消息DTO
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 3321d53a..a14a9006 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -650,6 +650,159 @@
+
+
+ 获取Trojan用户
+
+
+
+
+
+
+
+
+ 获取Trojan用户-下拉列表用
+
+
+
+
+
+ 添加Trojan用户
+
+
+
+
+
+
+ 更新Trojan用户
+
+
+
+
+
+
+ 删除用户
+
+
+
+
+
+
+ 重置流量
+
+
+
+
+
+
+ 限制流量
+
+
+
+
+
+
+ 重置链接密码
+
+
+
+
+
+
+ 获取Trojan服务器
+
+
+
+
+
+ 获取拼接后的Trojan服务器
+
+ passwordshow
+
+
+
+
+ 删除Trojan服务器
+
+
+
+
+
+
+ 更新Trojan服务器
+
+
+
+
+
+
+ 添加Trojan服务器
+
+
+
+
+
+
+ 获取Cus服务器
+
+
+
+
+
+ 删除Cus服务器
+
+
+
+
+
+
+ 更新Cus服务器
+
+
+
+
+
+
+ 添加Cus服务器
+
+
+
+
+
+
+ 获取Url服务器
+
+
+
+
+
+ 删除Url服务器
+
+
+
+
+
+
+ 更新Url服务器
+
+
+
+
+
+
+ 添加Url服务器
+
+
+
+
+
+
+ 获取订阅数据
+
+ 链接密码
+ 是否使用base64加密
+
+
用户管理
@@ -1062,6 +1215,13 @@
卡片消息对象
+
+
+ 推送卡片消息接口
+
+ 卡片消息对象
+
+
推送文本消息
diff --git a/Blog.Core.Api/Controllers/TrojanController.cs b/Blog.Core.Api/Controllers/TrojanController.cs
new file mode 100644
index 00000000..8ec64c8a
--- /dev/null
+++ b/Blog.Core.Api/Controllers/TrojanController.cs
@@ -0,0 +1,451 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Blog.Core.Common;
+using Blog.Core.Common.Extensions;
+using Blog.Core.Common.Helper;
+using Blog.Core.Common.HttpContextUser;
+using Blog.Core.IServices;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Blog.Core.Model.ViewModels;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Controllers
+{
+ [Route("api/[controller]/[action]")]
+ [ApiController]
+ [Authorize(Permissions.Name)]
+ public class TrojanController : ControllerBase
+ {
+ private ITrojanUsersServices _trojanUsersServices;
+ public IBaseServices _baseServicesServers;
+ public IBaseServices _baseServicesDetails;
+ public IBaseServices _baseServicesCusServers;
+ public IBaseServices _baseServicesUrlServers;
+ private IUser _user;
+ public TrojanController(ITrojanUsersServices trojanUsersServices,IUser user
+ , IBaseServices baseServicesServers
+ , IBaseServices baseServicesDetails
+ , IBaseServices baseServicesCusServers
+ , IBaseServices baseServicesUrlServers)
+ {
+ _baseServicesDetails = baseServicesDetails;
+ _baseServicesServers = baseServicesServers;
+ _trojanUsersServices = trojanUsersServices;
+ _baseServicesCusServers = baseServicesCusServers;
+ _baseServicesUrlServers = baseServicesUrlServers;
+ _user = user;
+ }
+ ///
+ /// 获取Trojan用户
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task>> GetUser([FromQuery]PaginationModel pagination, [FromQuery] string name, [FromQuery] bool isuse)
+ {
+ var whereFind = LinqHelper.True();
+ if (!string.IsNullOrEmpty(name))
+ whereFind = whereFind.And(t=>t.username.Contains(name));
+ if (isuse)
+ whereFind = whereFind.And(t => t.upload > 0 || t.download > 0);
+ var data = await _trojanUsersServices.QueryPage(whereFind, pagination.PageIndex, pagination.PageSize);
+ if (data.data.Count > 0)
+ {
+ var ids = data.data.Select(t => t.id).ToList();
+ var where = LinqHelper.True();
+ where = where.And(t => ids.Contains(t.userId));//.And(t => t.calDate < DateTime.Now).And(t => t.calDate > DateTime.Now.AddMonths(-12));
+ var userDetails = await _baseServicesDetails.Query(where);
+ foreach (var trojanUser in data.data)
+ {
+ var ls = from t in userDetails
+ where t.userId == trojanUser.id
+ group t by new { moth = t.calDate.ToString("yyyy-MM"), id = t.userId } into g
+ orderby g.Key.moth descending
+ select new TrojanUseDetailDto { userId = g.Key.id, moth = g.Key.moth, up = g.Sum(t => Convert.ToDecimal(t.upload)), down = g.Sum(t => Convert.ToDecimal(t.download)) };
+ var lsData = ls.ToList();
+ trojanUser.useList = lsData;
+ }
+ }
+ return MessageModel>.Success("获取成功", data);
+ }
+
+ ///
+ /// 获取Trojan用户-下拉列表用
+ ///
+ ///
+ [HttpGet]
+ public async Task> GetAllTrojanUser()
+ {
+ var data = await _trojanUsersServices.QueryTable("select id,username from users");
+ return MessageModel.Success("获取成功", data);
+ }
+ ///
+ /// 添加Trojan用户
+ ///
+ ///
+ ///
+ [HttpPost]
+ public async Task> AddUser([FromBody]TrojanUsers user)
+ {
+ var find = await _trojanUsersServices.Query(t => t.username == user.username);
+ if(find!=null && find.Count>0) return MessageModel
diff --git a/Blog.Core.Tasks/HostedService/Job1TimedService.cs b/Blog.Core.Tasks/HostedService/Job1TimedService.cs
new file mode 100644
index 00000000..9777affc
--- /dev/null
+++ b/Blog.Core.Tasks/HostedService/Job1TimedService.cs
@@ -0,0 +1,60 @@
+using Blog.Core.Common;
+using Blog.Core.IServices;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Tasks
+{
+ public class Job1TimedService : IHostedService, IDisposable
+ {
+ private Timer _timer;
+ private readonly IBlogArticleServices _blogArticleServices;
+
+ // 这里可以注入
+ public Job1TimedService(IBlogArticleServices blogArticleServices)
+ {
+ _blogArticleServices = blogArticleServices;
+ }
+
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ Console.WriteLine("Job 1 is starting.");
+
+ _timer = new Timer(DoWork, null, TimeSpan.Zero,
+ TimeSpan.FromSeconds(60 * 60));//一个小时
+
+ return Task.CompletedTask;
+ }
+
+ private void DoWork(object state)
+ {
+ try
+ {
+ var model = _blogArticleServices.GetBlogDetails(1).Result;
+ Console.WriteLine($"Job 1 启动成功,获取id=1的博客title为:{model?.btitle}");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error:{ex.Message}");
+ }
+
+ ConsoleHelper.WriteSuccessLine($"Job 1: {DateTime.Now}");
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ Console.WriteLine("Job 1 is stopping.");
+
+ _timer?.Change(Timeout.Infinite, 0);
+
+ return Task.CompletedTask;
+ }
+
+ public void Dispose()
+ {
+ _timer?.Dispose();
+ }
+ }
+}
diff --git a/Blog.Core.Tasks/HostedService/Job2TimedService.cs b/Blog.Core.Tasks/HostedService/Job2TimedService.cs
new file mode 100644
index 00000000..ee7f2c5c
--- /dev/null
+++ b/Blog.Core.Tasks/HostedService/Job2TimedService.cs
@@ -0,0 +1,47 @@
+using Blog.Core.Common;
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Tasks
+{
+ public class Job2TimedService : IHostedService, IDisposable
+ {
+ private Timer _timer;
+
+ // 这里可以注入
+ public Job2TimedService()
+ {
+ }
+
+ public Task StartAsync(CancellationToken cancellationToken)
+ {
+ Console.WriteLine("Job 2 is starting.");
+
+ _timer = new Timer(DoWork, null, TimeSpan.Zero,
+ TimeSpan.FromSeconds(60 * 60 * 2));//两个小时
+
+ return Task.CompletedTask;
+ }
+
+ private void DoWork(object state)
+ {
+ ConsoleHelper.WriteWarningLine($"Job 2: {DateTime.Now}");
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ Console.WriteLine("Job 2 is stopping.");
+
+ _timer?.Change(Timeout.Infinite, 0);
+
+ return Task.CompletedTask;
+ }
+
+ public void Dispose()
+ {
+ _timer?.Dispose();
+ }
+ }
+}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Trojan_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Trojan_Quartz.cs
new file mode 100644
index 00000000..f9640749
--- /dev/null
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Trojan_Quartz.cs
@@ -0,0 +1,79 @@
+using Blog.Core.Repository.UnitOfWorks;
+using Blog.Core.IServices;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model.Models;
+using Microsoft.Extensions.Logging;
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+///
+/// 这里要注意下,命名空间和程序集是一样的,不然反射不到(任务类要去JobSetup添加注入)
+///
+namespace Blog.Core.Tasks
+{
+ public class Job_Trojan_Quartz : JobBase, IJob
+ {
+ private readonly IUnitOfWorkManage _unitOfWorkManage;
+ public IBaseServices_DetailServices;
+ private readonly ITrojanUsersServices _TrojanUsers;
+ private readonly ILogger _logger;
+
+ public Job_Trojan_Quartz(IUnitOfWorkManage unitOfWorkManage, IBaseServices iusers_DetailServices, ITrojanUsersServices trojanUsers, ITasksQzServices tasksQzServices, ILogger logger)
+ {
+ _tasksQzServices = tasksQzServices;
+ _unitOfWorkManage = unitOfWorkManage;
+ _DetailServices = iusers_DetailServices;
+ _TrojanUsers = trojanUsers;
+ _logger = logger;
+ }
+ public async Task Execute(IJobExecutionContext context)
+ {
+ //var param = context.MergedJobDataMap;
+ // 可以直接获取 JobDetail 的值
+ var jobKey = context.JobDetail.Key;
+ var jobId = jobKey.Name;
+ var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
+
+ }
+ public async Task Run(IJobExecutionContext context, int jobid)
+ {
+ if (jobid > 0)
+ {
+ try
+ {
+ //获取每月用户的数据
+ _unitOfWorkManage.BeginTran();
+ var now = DateTime.Now.AddMonths(-1);
+
+ var list = await _TrojanUsers.Query();
+ List ls = new List();
+ foreach (var us in list)
+ {
+ TrojanDetails u = new TrojanDetails();
+ u.calDate = now;
+ u.userId = us.id;
+ u.download = us.download;
+ u.upload = us.upload;
+ //清零
+ us.download = 0;
+ us.upload = 0;
+ ls.Add(u);
+ }
+ await _TrojanUsers.Update(list);
+ await _DetailServices.Add(ls);
+ _unitOfWorkManage.CommitTran();
+ }
+ catch (Exception)
+ {
+ _unitOfWorkManage.RollbackTran();
+ throw;
+ }
+ }
+ }
+ }
+
+
+
+}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_URL_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_URL_Quartz.cs
new file mode 100644
index 00000000..666a8d41
--- /dev/null
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_URL_Quartz.cs
@@ -0,0 +1,51 @@
+using Blog.Core.Common.Helper;
+using Blog.Core.Repository.UnitOfWorks;
+using Blog.Core.IServices;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model.Models;
+using Microsoft.Extensions.Logging;
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+///
+/// 这里要注意下,命名空间和程序集是一样的,不然反射不到(任务类要去JobSetup添加注入)
+///
+namespace Blog.Core.Tasks
+{
+ public class Job_URL_Quartz : JobBase, IJob
+ {
+ private readonly ILogger _logger;
+
+ public Job_URL_Quartz(ITasksQzServices tasksQzServices, ILogger logger)
+ {
+ _tasksQzServices = tasksQzServices;
+ _logger = logger;
+ }
+ public async Task Execute(IJobExecutionContext context)
+ {
+ // 可以直接获取 JobDetail 的值
+ var jobKey = context.JobDetail.Key;
+ var jobId = jobKey.Name;
+ var executeLog = await ExecuteJob(context, async () => await Run(context, jobId.ObjToInt()));
+
+ }
+ public async Task Run(IJobExecutionContext context, int jobid)
+ {
+ if (jobid > 0)
+ {
+ JobDataMap data = context.JobDetail.JobDataMap;
+ string pars = data.GetString("JobParam");
+ if (!string.IsNullOrWhiteSpace(pars))
+ {
+ var log = await HttpHelper.GetAsync(pars);
+ _logger.LogInformation(log);
+ }
+ }
+ }
+ }
+
+
+
+}
From b36db59e1abdd2ebece8caf034ae6238a58885d7 Mon Sep 17 00:00:00 2001
From: HuiJiOnGit <40553940+HuiJiOnGit@users.noreply.github.com>
Date: Mon, 13 Feb 2023 13:47:18 +0800
Subject: [PATCH 024/190] =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=BA=94=E7=94=A8?=
=?UTF-8?q?=E4=B8=AD=E9=97=B4=E4=BB=B6=E5=90=AF=E5=8A=A8=E6=9C=8D=E5=8A=A1?=
=?UTF-8?q?=E5=88=B0`HostedService`=E4=B8=AD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Program.cs | 30 ++------
Blog.Core.Api/Startup.cs | 39 ++++------
.../HostedService/ConsulHostedService.cs | 71 +++++++++++++++++++
.../HostedService/EventBusHostedService.cs | 45 ++++++++++++
.../HostedService/QuartzJobHostedService.cs | 67 +++++++++++++++++
.../HostedService/SeedDataHostedService.cs | 55 ++++++++++++++
.../Middlewares/ConsulMiddleware.cs | 52 --------------
.../Middlewares/QuartzJobMiddleware.cs | 51 -------------
.../Middlewares/SeedDataMiddleware.cs | 33 ---------
.../ServiceExtensions/EventBusSetup.cs | 21 ++----
.../InitializationHostServiceSetup.cs | 24 +++++++
11 files changed, 287 insertions(+), 201 deletions(-)
create mode 100644 Blog.Core.Extensions/HostedService/ConsulHostedService.cs
create mode 100644 Blog.Core.Extensions/HostedService/EventBusHostedService.cs
create mode 100644 Blog.Core.Extensions/HostedService/QuartzJobHostedService.cs
create mode 100644 Blog.Core.Extensions/HostedService/SeedDataHostedService.cs
delete mode 100644 Blog.Core.Extensions/Middlewares/ConsulMiddleware.cs
delete mode 100644 Blog.Core.Extensions/Middlewares/QuartzJobMiddleware.cs
delete mode 100644 Blog.Core.Extensions/Middlewares/SeedDataMiddleware.cs
create mode 100644 Blog.Core.Extensions/ServiceExtensions/InitializationHostServiceSetup.cs
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index 8ab4b93d..d7619781 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -1,19 +1,17 @@
-
-// 以下为asp.net 6.0的写法,如果用5.0,请看Program.five.cs文件
+// 以下为asp.net 6.0的写法,如果用5.0,请看Program.five.cs文件
+using System.IdentityModel.Tokens.Jwt;
+using System.Reflection;
+using System.Text;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Blog.Core;
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
-using Blog.Core.Common.Seed;
using Blog.Core.Extensions;
using Blog.Core.Extensions.Apollo;
using Blog.Core.Extensions.Middlewares;
using Blog.Core.Filter;
using Blog.Core.Hubs;
-using Blog.Core.IServices;
-using Blog.Core.Tasks;
-using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
@@ -21,9 +19,6 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
-using System.IdentityModel.Tokens.Jwt;
-using System.Reflection;
-using System.Text;
var builder = WebApplication.CreateBuilder(args);
@@ -49,7 +44,6 @@
config.AddConfigurationApollo("appsettings.apollo.json");
});
-
// 2、配置服务
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
builder.Services.AddSingleton(new LogLock(builder.Environment.ContentRootPath));
@@ -79,7 +73,7 @@
builder.Services.AddKafkaSetup(builder.Configuration);
builder.Services.AddEventBusSetup();
builder.Services.AddNacosSetup(builder.Configuration);
-
+builder.Services.AddInitializationHostServiceSetup();
builder.Services.AddAuthorizationSetup();
if (Permissions.IsUseIds4 || Permissions.IsUseAuthing)
{
@@ -129,7 +123,6 @@
builder.Services.Replace(ServiceDescriptor.Transient());
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
-
// 3、配置中间件
var app = builder.Build();
@@ -182,16 +175,5 @@
endpoints.MapHub("/api2/chatHub");
});
-
-var scope = app.Services.GetRequiredService().CreateScope();
-var myContext = scope.ServiceProvider.GetRequiredService();
-var tasksQzServices = scope.ServiceProvider.GetRequiredService();
-var schedulerCenter = scope.ServiceProvider.GetRequiredService();
-var lifetime = scope.ServiceProvider.GetRequiredService();
-app.UseSeedDataMiddle(myContext, builder.Environment.WebRootPath);
-app.UseQuartzJobMiddleware(tasksQzServices, schedulerCenter);
-app.UseConsulMiddle(builder.Configuration, lifetime);
-app.ConfigureEventBus();
-
// 4、运行
-app.Run();
+app.Run();
\ No newline at end of file
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index b341819e..bc1630f1 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -1,34 +1,28 @@
-using Autofac;
+using System.IdentityModel.Tokens.Jwt;
+using System.Reflection;
+using System.Text;
+using Autofac;
using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
using Blog.Core.Common.Seed;
using Blog.Core.Extensions;
+using Blog.Core.Extensions.Middlewares;
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
using Blog.Core.Tasks;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
-using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
-using System.IdentityModel.Tokens.Jwt;
-using System.Reflection;
-using System.Text;
-using Blog.Core.Extensions.Middlewares;
namespace Blog.Core
{
public class Startup
{
-
private IServiceCollection _services;
public Startup(IConfiguration configuration, IWebHostEnvironment env)
@@ -75,7 +69,7 @@ public void ConfigureServices(IServiceCollection services)
services.AddEventBusSetup();
services.AddNacosSetup(Configuration);
-
+ services.AddInitializationHostServiceSetup();
// 授权+认证 (jwt or ids4)
services.AddAuthorizationSetup();
if (Permissions.IsUseIds4)
@@ -95,7 +89,7 @@ public void ConfigureServices(IServiceCollection services)
services.Configure(x => x.AllowSynchronousIO = true)
.Configure(x => x.AllowSynchronousIO = true);
-
+
services.AddDistributedMemoryCache();
services.AddSession();
services.AddHttpPollySetup();
@@ -134,7 +128,7 @@ public void ConfigureServices(IServiceCollection services)
services.Replace(ServiceDescriptor.Transient());
_services = services;
- //支持编码大全 例如:支持 System.Text.Encoding.GetEncoding("GB2312") System.Text.Encoding.GetEncoding("GB18030")
+ //支持编码大全 例如:支持 System.Text.Encoding.GetEncoding("GB2312") System.Text.Encoding.GetEncoding("GB18030")
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
@@ -150,11 +144,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyContex
{
// Ip限流,尽量放管道外层
app.UseIpLimitMiddle();
- // 记录请求与返回数据
+ // 记录请求与返回数据
app.UseRequestResponseLogMiddle();
// 用户访问记录(必须放到外层,不然如果遇到异常,会报错,因为不能返回流)
app.UseRecordAccessLogsMiddle();
- // signalr
+ // signalr
app.UseSignalRSendMiddle();
// 记录ip请求
app.UseIpLogMiddle();
@@ -214,7 +208,6 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyContex
// 开启异常中间件,要放到最后
//app.UseExceptionHandlerMidd();
-
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
@@ -225,15 +218,13 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, MyContex
});
// 生成种子数据
- app.UseSeedDataMiddle(myContext, Env.WebRootPath);
+ //app.UseSeedDataMiddle(myContext, Env.WebRootPath);
// 开启QuartzNetJob调度服务
- app.UseQuartzJobMiddleware(tasksQzServices, schedulerCenter);
+ //app.UseQuartzJobMiddleware(tasksQzServices, schedulerCenter);
// 服务注册
- app.UseConsulMiddle(Configuration, lifetime);
+ //app.UseConsulMiddle(Configuration, lifetime);
// 事件总线,订阅服务
- app.ConfigureEventBus();
-
+ //app.ConfigureEventBus();
}
-
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/HostedService/ConsulHostedService.cs b/Blog.Core.Extensions/HostedService/ConsulHostedService.cs
new file mode 100644
index 00000000..df866e6a
--- /dev/null
+++ b/Blog.Core.Extensions/HostedService/ConsulHostedService.cs
@@ -0,0 +1,71 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Consul;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace Blog.Core.Extensions.HostedService;
+
+public class ConsulHostedService : IHostedService
+{
+ private readonly IConfiguration _configuration;
+ private readonly IHostApplicationLifetime _hostApplicationLifetime;
+ private readonly ILogger _logger;
+
+ public ConsulHostedService(IConfiguration configuration, IHostApplicationLifetime hostApplicationLifetime, ILogger logger)
+ {
+ _configuration = configuration;
+ _hostApplicationLifetime = hostApplicationLifetime;
+ _logger = logger;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Start Consul Service!");
+ await DoWork();
+ }
+
+ public async Task DoWork()
+ {
+ if (_configuration["Middleware:Consul:Enabled"].ObjToBool())
+ {
+ var consulClient = new ConsulClient(c =>
+ {
+ //consul地址
+ c.Address = new Uri(_configuration["ConsulSetting:ConsulAddress"]);
+ });
+
+ var registration = new AgentServiceRegistration()
+ {
+ ID = Guid.NewGuid().ToString(),//服务实例唯一标识
+ Name = _configuration["ConsulSetting:ServiceName"],//服务名
+ Address = _configuration["ConsulSetting:ServiceIP"], //服务IP
+ Port = int.Parse(_configuration["ConsulSetting:ServicePort"]),//服务端口
+ Check = new AgentServiceCheck()
+ {
+ DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
+ Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
+ HTTP = $"http://{_configuration["ConsulSetting:ServiceIP"]}:{_configuration["ConsulSetting:ServicePort"]}{_configuration["ConsulSetting:ServiceHealthCheck"]}",//健康检查地址
+ Timeout = TimeSpan.FromSeconds(5)//超时时间
+ }
+ };
+
+ //服务注册
+ await consulClient.Agent.ServiceRegister(registration);
+
+ //应用程序终止时,取消注册
+ _hostApplicationLifetime.ApplicationStopping.Register(async () =>
+ {
+ await consulClient.Agent.ServiceDeregister(registration.ID);
+ });
+ }
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Stop Consul Service!");
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/HostedService/EventBusHostedService.cs b/Blog.Core.Extensions/HostedService/EventBusHostedService.cs
new file mode 100644
index 00000000..7f18ed19
--- /dev/null
+++ b/Blog.Core.Extensions/HostedService/EventBusHostedService.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Blog.Core.Common;
+using Blog.Core.EventBus;
+using Blog.Core.EventBus.EventHandling;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace Blog.Core.Extensions.HostedService;
+
+public class EventBusHostedService : IHostedService
+{
+ private readonly IServiceProvider _serviceProvider;
+ private readonly ILogger _logger;
+
+ public EventBusHostedService(IServiceProvider serviceProvider, ILogger logger)
+ {
+ _serviceProvider = serviceProvider;
+ _logger = logger;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Start EventBus Service!");
+ await DoWork();
+ }
+
+ private Task DoWork()
+ {
+ if (AppSettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
+ {
+ var eventBus = _serviceProvider.GetRequiredService();
+ eventBus.Subscribe();
+ }
+ return Task.CompletedTask;
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Stop EventBus Service!");
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/HostedService/QuartzJobHostedService.cs b/Blog.Core.Extensions/HostedService/QuartzJobHostedService.cs
new file mode 100644
index 00000000..d8f4d602
--- /dev/null
+++ b/Blog.Core.Extensions/HostedService/QuartzJobHostedService.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Blog.Core.Common;
+using Blog.Core.IServices;
+using Blog.Core.Tasks;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace Blog.Core.Extensions.HostedService;
+
+public class QuartzJobHostedService : IHostedService
+{
+ private readonly ITasksQzServices _tasksQzServices;
+ private readonly ISchedulerCenter _schedulerCenter;
+ private readonly ILogger _logger;
+
+ public QuartzJobHostedService(ITasksQzServices tasksQzServices, ISchedulerCenter schedulerCenter, ILogger logger)
+ {
+ _tasksQzServices = tasksQzServices;
+ _schedulerCenter = schedulerCenter;
+ _logger = logger;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Start QuartzJob Service!");
+ await DoWork();
+ }
+
+ private async Task DoWork()
+ {
+ try
+ {
+ if (AppSettings.app("Middleware", "QuartzNetJob", "Enabled").ObjToBool())
+ {
+ var allQzServices = await _tasksQzServices.Query();
+ foreach (var item in allQzServices)
+ {
+ if (item.IsStart)
+ {
+ var result = await _schedulerCenter.AddScheduleJobAsync(item);
+ if (result.success)
+ {
+ Console.WriteLine($"QuartzNetJob{item.Name}启动成功!");
+ }
+ else
+ {
+ Console.WriteLine($"QuartzNetJob{item.Name}启动失败!错误信息:{result.msg}");
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ _logger.LogError(e, "An error was reported when starting the job service.");
+ throw;
+ }
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Stop QuartzJob Service!");
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs b/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs
new file mode 100644
index 00000000..beef5a75
--- /dev/null
+++ b/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Blog.Core.Common;
+using Blog.Core.Common.Seed;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
+
+namespace Blog.Core.Extensions;
+
+public sealed class SeedDataHostedService : IHostedService
+{
+ private readonly MyContext _myContext;
+ private readonly ILogger _logger;
+ private readonly string _webRootPath;
+
+ public SeedDataHostedService(
+ MyContext myContext,
+ IWebHostEnvironment webHostEnvironment,
+ ILogger logger)
+ {
+ _myContext = myContext;
+ _logger = logger;
+ _webRootPath = webHostEnvironment.WebRootPath;
+ }
+
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Start Initialization Db Seed Service!");
+ await DoWork();
+ }
+
+ private async Task DoWork()
+ {
+ try
+ {
+ if (AppSettings.app("AppSettings", "SeedDBEnabled").ObjToBool() || AppSettings.app("AppSettings", "SeedDBDataEnabled").ObjToBool())
+ {
+ await DBSeed.SeedAsync(_myContext, _webRootPath);
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error occured seeding the Database.");
+ throw;
+ }
+ }
+
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ _logger.LogInformation("Stop Initialization Db Seed Service!");
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/Middlewares/ConsulMiddleware.cs b/Blog.Core.Extensions/Middlewares/ConsulMiddleware.cs
deleted file mode 100644
index c1aae8cc..00000000
--- a/Blog.Core.Extensions/Middlewares/ConsulMiddleware.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using Consul;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.Hosting;
-
-namespace Blog.Core.Extensions.Middlewares
-{
- ///
- /// Consul 注册服务
- ///
- public static class ConsulMiddleware
- {
- public static IApplicationBuilder UseConsulMiddle(this IApplicationBuilder app, IConfiguration configuration, IHostApplicationLifetime lifetime)
- {
- if (configuration["Middleware:Consul:Enabled"].ObjToBool())
- {
- var consulClient = new ConsulClient(c =>
- {
- //consul地址
- c.Address = new Uri(configuration["ConsulSetting:ConsulAddress"]);
- });
-
- var registration = new AgentServiceRegistration()
- {
- ID = Guid.NewGuid().ToString(),//服务实例唯一标识
- Name = configuration["ConsulSetting:ServiceName"],//服务名
- Address = configuration["ConsulSetting:ServiceIP"], //服务IP
- Port = int.Parse(configuration["ConsulSetting:ServicePort"]),//服务端口
- Check = new AgentServiceCheck()
- {
- DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务启动多久后注册
- Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔
- HTTP = $"http://{configuration["ConsulSetting:ServiceIP"]}:{configuration["ConsulSetting:ServicePort"]}{configuration["ConsulSetting:ServiceHealthCheck"]}",//健康检查地址
- Timeout = TimeSpan.FromSeconds(5)//超时时间
- }
- };
-
- //服务注册
- consulClient.Agent.ServiceRegister(registration).Wait();
-
- //应用程序终止时,取消注册
- lifetime.ApplicationStopping.Register(() =>
- {
- consulClient.Agent.ServiceDeregister(registration.ID).Wait();
- });
-
- }
- return app;
- }
- }
-}
diff --git a/Blog.Core.Extensions/Middlewares/QuartzJobMiddleware.cs b/Blog.Core.Extensions/Middlewares/QuartzJobMiddleware.cs
deleted file mode 100644
index 69c52de3..00000000
--- a/Blog.Core.Extensions/Middlewares/QuartzJobMiddleware.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using Blog.Core.Common;
-using Blog.Core.IServices;
-using Blog.Core.Tasks;
-using log4net;
-using Microsoft.AspNetCore.Builder;
-
-namespace Blog.Core.Extensions.Middlewares
-{
- ///
- /// Quartz 启动服务
- ///
- public static class QuartzJobMiddleware
- {
- private static readonly ILog Log = LogManager.GetLogger(typeof(QuartzJobMiddleware));
- public static void UseQuartzJobMiddleware(this IApplicationBuilder app, ITasksQzServices tasksQzServices, ISchedulerCenter schedulerCenter)
- {
- if (app == null) throw new ArgumentNullException(nameof(app));
-
- try
- {
- if (AppSettings.app("Middleware", "QuartzNetJob", "Enabled").ObjToBool())
- {
-
- var allQzServices = tasksQzServices.Query().Result;
- foreach (var item in allQzServices)
- {
- if (item.IsStart)
- {
- var result = schedulerCenter.AddScheduleJobAsync(item).Result;
- if (result.success)
- {
- Console.WriteLine($"QuartzNetJob{item.Name}启动成功!");
- }
- else
- {
- Console.WriteLine($"QuartzNetJob{item.Name}启动失败!错误信息:{result.msg}");
- }
- }
- }
-
- }
- }
- catch (Exception e)
- {
- Log.Error($"An error was reported when starting the job service.\n{e.Message}");
- throw;
- }
- }
- }
-}
diff --git a/Blog.Core.Extensions/Middlewares/SeedDataMiddleware.cs b/Blog.Core.Extensions/Middlewares/SeedDataMiddleware.cs
deleted file mode 100644
index ad944bfd..00000000
--- a/Blog.Core.Extensions/Middlewares/SeedDataMiddleware.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using Blog.Core.Common;
-using Blog.Core.Common.Seed;
-using log4net;
-using Microsoft.AspNetCore.Builder;
-
-namespace Blog.Core.Extensions.Middlewares
-{
- ///
- /// 生成种子数据中间件服务
- ///
- public static class SeedDataMiddleware
- {
- private static readonly ILog Log = LogManager.GetLogger(typeof(SeedDataMiddleware));
- public static void UseSeedDataMiddle(this IApplicationBuilder app, MyContext myContext, string webRootPath)
- {
- if (app == null) throw new ArgumentNullException(nameof(app));
-
- try
- {
- if (AppSettings.app("AppSettings", "SeedDBEnabled").ObjToBool() || AppSettings.app("AppSettings", "SeedDBDataEnabled").ObjToBool())
- {
- DBSeed.SeedAsync(myContext, webRootPath).Wait();
- }
- }
- catch (Exception e)
- {
- Log.Error($"Error occured seeding the Database.\n{e.Message}");
- throw;
- }
- }
- }
-}
diff --git a/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs b/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
index 1aae5ed5..4ae98830 100644
--- a/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/EventBusSetup.cs
@@ -1,11 +1,9 @@
-using Autofac;
+using System;
+using Autofac;
using Blog.Core.Common;
using Blog.Core.EventBus;
-using Blog.Core.EventBus.EventHandling;
-using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using System;
namespace Blog.Core.Extensions
{
@@ -43,23 +41,12 @@ public static void AddEventBusSetup(this IServiceCollection services)
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount);
});
}
- if(AppSettings.app(new string[] { "Kafka", "Enabled" }).ObjToBool())
+ if (AppSettings.app(new string[] { "Kafka", "Enabled" }).ObjToBool())
{
services.AddHostedService();
services.AddSingleton();
}
}
}
-
-
- public static void ConfigureEventBus(this IApplicationBuilder app)
- {
- if (AppSettings.app(new string[] { "EventBus", "Enabled" }).ObjToBool())
- {
- var eventBus = app.ApplicationServices.GetRequiredService();
-
- eventBus.Subscribe();
- }
- }
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/ServiceExtensions/InitializationHostServiceSetup.cs b/Blog.Core.Extensions/ServiceExtensions/InitializationHostServiceSetup.cs
new file mode 100644
index 00000000..fea6a5ad
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/InitializationHostServiceSetup.cs
@@ -0,0 +1,24 @@
+using System;
+using Blog.Core.Extensions.HostedService;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Blog.Core.Extensions;
+
+public static class InitializationHostServiceSetup
+{
+ ///
+ /// 应用初始化服务注入
+ ///
+ ///
+ public static void AddInitializationHostServiceSetup(this IServiceCollection services)
+ {
+ if (services is null)
+ {
+ ArgumentNullException.ThrowIfNull(nameof(services));
+ }
+ services.AddHostedService();
+ services.AddHostedService();
+ services.AddHostedService();
+ services.AddHostedService();
+ }
+}
\ No newline at end of file
From 71e0f4a7fe99520614a43c6c536ffcc5a24db132 Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Mon, 13 Feb 2023 19:23:16 +0800
Subject: [PATCH 025/190] =?UTF-8?q?=E2=9C=A8=20=E5=AE=8C=E5=96=84=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E5=8A=A8=E6=80=81=E8=A1=A8=E8=BE=BE=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1.支持一对多导航属性
2.支持混合查询
测试代码看 DynamicLambdaTest
每次修改,都会验证通过测试
---
Blog.Core.Api/Blog.Core.Model.xml | 10 ++
.../Extensions/ExpressionExtensions.cs | 13 ++-
Blog.Core.Common/Helper/DynamicLinqFactory.cs | 100 +++++++++++++++---
.../Helper/GenericTypeExtensions.cs | 56 ++++++++++
Blog.Core.Model/Models/BlogArticle.cs | 14 ++-
Blog.Core.Model/Models/BlogArticleComment.cs | 19 ++++
Blog.Core.Model/Models/sysUserInfo.cs | 2 +-
.../Common_Test/DynamicLambdaTest.cs | 54 +++++++++-
.../DependencyInjection/DI_Test.cs | 35 +++---
9 files changed, 259 insertions(+), 44 deletions(-)
create mode 100644 Blog.Core.Common/Helper/GenericTypeExtensions.cs
create mode 100644 Blog.Core.Model/Models/BlogArticleComment.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 36975d11..f2b73257 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -301,6 +301,16 @@
逻辑删除
+
+
+ 评论
+
+
+
+
+ 博客文章 评论
+
+
部门表
diff --git a/Blog.Core.Common/Extensions/ExpressionExtensions.cs b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
index 7f9e69e5..4058b95a 100644
--- a/Blog.Core.Common/Extensions/ExpressionExtensions.cs
+++ b/Blog.Core.Common/Extensions/ExpressionExtensions.cs
@@ -151,6 +151,16 @@ public static Expression Contains(this Expression left, Expression right)
return left.Call("Contains", right);
}
+ public static Expression StartContains(this Expression left, Expression right)
+ {
+ return left.Call("StartsWith", right);
+ }
+
+ public static Expression EndContains(this Expression left, Expression right)
+ {
+ return left.Call("EndsWith", right);
+ }
+
///
/// >
///
@@ -201,5 +211,4 @@ public static Expression NotEqual(this Expression left, Expression right)
#endregion
}
-
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Helper/DynamicLinqFactory.cs b/Blog.Core.Common/Helper/DynamicLinqFactory.cs
index 43fdd7e3..7d45bbd2 100644
--- a/Blog.Core.Common/Helper/DynamicLinqFactory.cs
+++ b/Blog.Core.Common/Helper/DynamicLinqFactory.cs
@@ -1,15 +1,11 @@
-using Microsoft.AspNetCore.Http;
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
-using System.Net.Http;
-using System.Net.Http.Headers;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
namespace Blog.Core.Common.Helper
{
@@ -20,10 +16,10 @@ namespace Blog.Core.Common.Helper
///
public static class DynamicLinqFactory
{
- private static readonly Dictionary _operatingSystems = new();
+ private static readonly Dictionary _operatingSystems = new Dictionary();
public static Dictionary OperatingSystems => GetOperationSymbol();
- private static readonly Dictionary _linkSymbols = new();
+ private static readonly Dictionary _linkSymbols = new Dictionary();
public static Dictionary LinkSymbols => GetLinkSymbol();
///
@@ -70,11 +66,16 @@ public static Expression ExpressionStudio(Expression left, DynamicLinqHelper Dyn
var properties = DynamicLinq.Left.Split('.');
- // 从1开始,是不想用自定义种子,外层种子已经定义好了
- // 暂时也不会有多个自定义种子,先这样
- for (var i = 0; i < properties.Length; i++)
+ int index = 0;
+ foreach (var t in properties)
{
- mainExpression = mainExpression.Property(properties[i]);
+ if (mainExpression.Type.HasImplementedRawGeneric(typeof(IEnumerable<>)))
+ {
+ return ExpressionStudioEnumerable(left, mainExpression, DynamicLinq.Clone(), properties.Skip(index).ToArray());
+ }
+
+ mainExpression = mainExpression.Property(t);
+ index++;
}
left = left == null
@@ -85,6 +86,32 @@ public static Expression ExpressionStudio(Expression left, DynamicLinqHelper Dyn
return left;
}
+ public static Expression ExpressionStudioEnumerable(Expression left, Expression property, DynamicLinqHelper dynamicLinq, string[] properties)
+ {
+ var realType = property.Type.GenericTypeArguments[0];
+
+ var parameter = Expression.Parameter(realType, "z");
+ Expression mainExpression = property;
+ if (!properties.Any())
+ {
+ throw new ApplicationException("条件表达式错误,属性为集合时,需要明确具体属性");
+ }
+
+ dynamicLinq.Left = string.Join(".", properties);
+ mainExpression = ExpressionStudio(null, dynamicLinq, parameter);
+
+ var lambda = Expression.Lambda(mainExpression, parameter);
+
+ mainExpression = Expression.Call(typeof(Enumerable), "Any", new[] { realType }, property, lambda);
+
+ left = left == null
+ ? mainExpression
+ : ChangeLinkSymbol(dynamicLinq.LinkSymbol, left, mainExpression);
+
+ return left;
+ }
+
+
///
/// 将字符串装换成动态帮助类(内含递归)
///
@@ -132,6 +159,7 @@ public static List SplitOperationSymbol(string str)
{
var outList = new List();
var tokens = Regex.Matches(FormatString(str), _pattern, RegexOptions.Compiled)
+ .Cast()
.Select(m => m.Groups[1].Value.Trim())
.ToList();
@@ -139,7 +167,7 @@ public static List SplitOperationSymbol(string str)
int lastOperatingSymbolIndex = -1;
for (int i = tokens.Count - 1; i >= 0; i--)
{
- var token = tokens[i];
+ var token = tokens[i].ToLower();
if (OperatingSystems.ContainsKey(token))
{
@@ -189,6 +217,7 @@ public static List SplitOperationSymbol(string str)
}
}
+ outList.Reverse();
return outList;
}
@@ -259,7 +288,7 @@ public static Dictionary GetOperationSymbol()
{
foreach (var name in attr.Name.Split(';'))
{
- _operatingSystems.Add(name, (OperationSymbol)item.GetValue(null));
+ _operatingSystems.Add(name.ToLower(), (OperationSymbol)item.GetValue(null));
}
}
}
@@ -353,7 +382,14 @@ public static string FormatString(string str)
public static readonly string _pattern = @"\s*(" + string.Join("|", new string[]
{
// operators and punctuation that are longer than one char: longest first
- string.Join("|", new[] { "||", "&&", "==", "!=", "<=", ">=", "like", "contains" }.Select(Regex.Escape)),
+ string.Join("|", new[]
+ {
+ "||", "&&", "==", "!=", "<=", ">=",
+ "in",
+ "like", "contains", "%=",
+ "startslike", "startscontains", "%>",
+ "endlike", "endcontains", "%<",
+ }.Select(Regex.Escape)),
@"""(?:\\.|[^""])*""", // string
@"\d+(?:\.\d+)?", // number with optional decimal part
@"\w+", // word
@@ -365,7 +401,7 @@ public static string FormatString(string str)
///
public static OperationSymbol ChangeOperationSymbol(string str)
{
- switch (str)
+ switch (str.ToLower())
{
case "<":
return OperationSymbol.LessThan;
@@ -382,7 +418,16 @@ public static OperationSymbol ChangeOperationSymbol(string str)
return OperationSymbol.NotEqual;
case "contains":
case "like":
+ case "%=":
return OperationSymbol.Contains;
+ case "startslike":
+ case "startscontains":
+ case "%>":
+ return OperationSymbol.StartsContains;
+ case "endlike":
+ case "endcontains":
+ case "%<":
+ return OperationSymbol.EndContains;
}
throw new Exception("OperationSymbol IS NULL");
@@ -451,6 +496,10 @@ public static Expression ChangeOperationSymbol(OperationSymbol symbol, Expressio
return key.NotEqual(Expression.Constant(newTypeRight));
case OperationSymbol.Contains:
return key.Contains(Expression.Constant(newTypeRight));
+ case OperationSymbol.StartsContains:
+ return key.StartContains(Expression.Constant(newTypeRight));
+ case OperationSymbol.EndContains:
+ return key.EndContains(Expression.Constant(newTypeRight));
case OperationSymbol.In:
var contains = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
.Single(x => x.Name == "Contains" && x.GetParameters().Length == 2)
@@ -480,6 +529,17 @@ public class DynamicLinqHelper
[Display(Name = "连接符")]
public LinkSymbol LinkSymbol { get; set; }
+
+ public DynamicLinqHelper Clone()
+ {
+ return new DynamicLinqHelper()
+ {
+ Left = this.Left,
+ Right = this.Right,
+ OperationSymbol = this.OperationSymbol,
+ LinkSymbol = this.LinkSymbol,
+ };
+ }
}
///
@@ -504,9 +564,15 @@ public enum OperationSymbol
[Display(Name = "in")]
In,
- [Display(Name = "like;contains")]
+ [Display(Name = "like;contains;%=")]
Contains,
+ [Display(Name = "StartsLike;StartsContains;%>")]
+ StartsContains,
+
+ [Display(Name = "EndLike;EndContains;%<")]
+ EndContains,
+
[Display(Name = ">")]
GreaterThan,
@@ -528,7 +594,7 @@ public enum OperationSymbol
#endregion
-
+
///
/// Queryable扩展
///
diff --git a/Blog.Core.Common/Helper/GenericTypeExtensions.cs b/Blog.Core.Common/Helper/GenericTypeExtensions.cs
new file mode 100644
index 00000000..aa095e2a
--- /dev/null
+++ b/Blog.Core.Common/Helper/GenericTypeExtensions.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Linq;
+
+namespace Blog.Core.Common.Helper
+{
+ public static class GenericTypeExtensions
+ {
+ ///
+ /// 判断类型是否实现某个泛型
+ ///
+ /// 类型
+ /// 泛型类型
+ /// bool
+ public static bool HasImplementedRawGeneric(this Type type, Type generic)
+ {
+ // 检查接口类型
+ var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
+ if (isTheRawGenericType) return true;
+
+ // 检查类型
+ while (type != null && type != typeof(object))
+ {
+ isTheRawGenericType = IsTheRawGenericType(type);
+ if (isTheRawGenericType) return true;
+ type = type.BaseType;
+ }
+
+ return false;
+
+ // 判断逻辑
+ bool IsTheRawGenericType(Type t) => generic == (t.IsGenericType ? t.GetGenericTypeDefinition() : t);
+ }
+
+ public static string GetGenericTypeName(this Type type)
+ {
+ var typeName = string.Empty;
+
+ if (type.IsGenericType)
+ {
+ var genericTypes = string.Join(",", type.GetGenericArguments().Select(t => t.Name).ToArray());
+ typeName = $"{type.Name.Remove(type.Name.IndexOf('`'))}<{genericTypes}>";
+ }
+ else
+ {
+ typeName = type.Name;
+ }
+
+ return typeName;
+ }
+
+ public static string GetGenericTypeName(this object @object)
+ {
+ return @object.GetType().GetGenericTypeName();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/BlogArticle.cs b/Blog.Core.Model/Models/BlogArticle.cs
index 52176190..66f05bdf 100644
--- a/Blog.Core.Model/Models/BlogArticle.cs
+++ b/Blog.Core.Model/Models/BlogArticle.cs
@@ -1,5 +1,6 @@
using SqlSugar;
using System;
+using System.Collections.Generic;
namespace Blog.Core.Model.Models
{
@@ -14,12 +15,16 @@ public class BlogArticle
/// 这里之所以没用RootEntity,是想保持和之前的数据库一致,主键是bID,不是Id
[SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
public int bID { get; set; }
+
///
/// 创建人
///
[SugarColumn(Length = 600, IsNullable = true)]
public string bsubmitter { get; set; }
+ [Navigate(NavigateType.OneToOne, nameof(bsubmitter))]
+ public SysUserInfo User { get; set; }
+
///
/// 标题blog
///
@@ -57,6 +62,7 @@ public class BlogArticle
/// 创建时间
///
public System.DateTime bCreateTime { get; set; }
+
///
/// 备注
///
@@ -69,5 +75,11 @@ public class BlogArticle
[SugarColumn(IsNullable = true)]
public bool? IsDeleted { get; set; }
+
+ ///
+ /// 评论
+ ///
+ [Navigate(NavigateType.OneToMany, nameof(BlogArticleComment.bID))]
+ public List Comments { get; set; }
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/BlogArticleComment.cs b/Blog.Core.Model/Models/BlogArticleComment.cs
new file mode 100644
index 00000000..08010863
--- /dev/null
+++ b/Blog.Core.Model/Models/BlogArticleComment.cs
@@ -0,0 +1,19 @@
+using SqlSugar;
+
+namespace Blog.Core.Model.Models;
+
+///
+/// 博客文章 评论
+///
+public class BlogArticleComment : RootEntityTkey
+{
+ public int bID { get; set; }
+
+ public string Comment { get; set; }
+
+
+ public string UserId { get; set; }
+
+ [Navigate(NavigateType.OneToOne, nameof(UserId))]
+ public SysUserInfo User { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/sysUserInfo.cs b/Blog.Core.Model/Models/sysUserInfo.cs
index c60e4bce..455f6e9e 100644
--- a/Blog.Core.Model/Models/sysUserInfo.cs
+++ b/Blog.Core.Model/Models/sysUserInfo.cs
@@ -8,7 +8,7 @@ namespace Blog.Core.Model.Models
/// 用户信息表
///
//[SugarTable("SysUserInfo")]
- [SugarTable("SysUserInfo", "用户表")]//('数据库表名','数据库表备注')
+ [SugarTable("SysUserInfo", "用户表")] //('数据库表名','数据库表备注')
public class SysUserInfo : SysUserInfoRoot
{
public SysUserInfo()
diff --git a/Blog.Core.Tests/Common_Test/DynamicLambdaTest.cs b/Blog.Core.Tests/Common_Test/DynamicLambdaTest.cs
index 99757e4f..8f6ad096 100644
--- a/Blog.Core.Tests/Common_Test/DynamicLambdaTest.cs
+++ b/Blog.Core.Tests/Common_Test/DynamicLambdaTest.cs
@@ -3,6 +3,7 @@
using Blog.Core.Common.Helper;
using Blog.Core.IRepository.Base;
using Blog.Core.Model.Models;
+using SqlSugar;
using Xunit;
using Xunit.Abstractions;
@@ -21,13 +22,42 @@ public DynamicLambdaTest(ITestOutputHelper testOutputHelper)
var container = dI_Test.DICollections();
_baseRepository = container.Resolve>();
-
+ _baseRepository.Db.Aop.OnLogExecuting = (sql, p) =>
+ {
+ _testOutputHelper.WriteLine("");
+ _testOutputHelper.WriteLine("==================FullSql=====================", "", new string[] { sql.GetType().ToString(), GetParas(p), "【SQL语句】:" + sql });
+ _testOutputHelper.WriteLine("【SQL语句】:" + sql);
+ _testOutputHelper.WriteLine(GetParas(p));
+ _testOutputHelper.WriteLine("==============================================");
+ _testOutputHelper.WriteLine("");
+ };
//DbContext.Init(BaseDBConfig.ConnectionString,(DbType)BaseDBConfig.DbType);
+
+ Init();
+ }
+
+ private static string GetParas(SugarParameter[] pars)
+ {
+ string key = "【SQL参数】:";
+ foreach (var param in pars)
+ {
+ key += $"{param.ParameterName}:{param.Value}\n";
+ }
+
+ return key;
+ }
+
+ private void Init()
+ {
+ _baseRepository.Db.CodeFirst.InitTables();
+ _baseRepository.Db.CodeFirst.InitTables();
}
[Fact]
public async void Get_Blogs_DynamicTest()
{
+ //方便前端自定义条件查询
+ //语法更舒服
var data = await _baseRepository.Query();
_testOutputHelper.WriteLine(data.ToJson());
@@ -39,12 +69,26 @@ public async void Get_Blogs_DynamicTest()
await TestConditions("btitle like \"测试数据\" && bId>0");
await TestConditions("btitle like \"测试!@#$%^&*()_+|}{\":<>?LP\"数据\" && bId>0");
await TestConditions("btitle like \"测试!@+)(*()_&%^&^$^%$IUYWIQOJVLXKZM>?Z<>??LP\"数据\" && bId>0");
-
- //比如文章下 过滤创建人
- //await TestConditions("btitle.user.name like \"老张\"");
-
await TestConditions("IsDeleted == false");
await TestConditions("IsDeleted == true");
+
+ //导航属性
+
+ //一对一
+
+ //查询 老张的文章
+ await TestConditions("User.RealName like \"老张\"");
+ //查询 2019年后的老张文章
+ await TestConditions("User.RealName like \"老张\" && bUpdateTime>=\"2019-01-01 01:01:01\"");
+
+ //一对多
+
+ //查询 评论中有"写的不错"的文章
+ await TestConditions("Comments.Comment like \"写的不错\"");
+ //查询 2019后的 评论中有"写的不错"的文章
+ await TestConditions("Comments.Comment like \"写的不错\" && bUpdateTime>=\"2019-01-01 01:01:01\"");
+ //查询 有老张评论的文章
+ await TestConditions("Comments.User.LoginName like \"老张\"");
}
private async Task TestConditions(string conditions)
diff --git a/Blog.Core.Tests/DependencyInjection/DI_Test.cs b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
index 6fad1f45..ff2c74cd 100644
--- a/Blog.Core.Tests/DependencyInjection/DI_Test.cs
+++ b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
@@ -74,13 +74,13 @@ public IContainer DICollections()
var permission = new List();
var permissionRequirement = new PermissionRequirement(
- "/api/denied",
- permission,
- ClaimTypes.Role,
- AppSettings.app(new string[] { "Audience", "Issuer" }),
- AppSettings.app(new string[] { "Audience", "Audience" }),
- signingCredentials,//签名凭据
- expiration: TimeSpan.FromSeconds(60 * 60)//接口的过期时间
+ "/api/denied",
+ permission,
+ ClaimTypes.Role,
+ AppSettings.app(new string[] { "Audience", "Issuer" }),
+ AppSettings.app(new string[] { "Audience", "Audience" }),
+ signingCredentials, //签名凭据
+ expiration: TimeSpan.FromSeconds(60 * 60) //接口的过期时间
);
services.AddSingleton(permissionRequirement);
@@ -88,17 +88,16 @@ public IContainer DICollections()
services.AddAuthorization(options =>
{
options.AddPolicy(Permissions.Name,
- policy => policy.Requirements.Add(permissionRequirement));
+ policy => policy.Requirements.Add(permissionRequirement));
});
services.AddScoped(o =>
{
return new SqlSugar.SqlSugarScope(new SqlSugar.ConnectionConfig()
{
- ConnectionString = GetMainConnectionDb().Connection,//必填, 数据库连接字符串
- DbType = (SqlSugar.DbType)GetMainConnectionDb().DbType,//必填, 数据库类型
- IsAutoCloseConnection = true,//默认false, 时候知道关闭数据库连接, 设置为true无需使用using或者Close操作
- InitKeyType = SqlSugar.InitKeyType.SystemTable//默认SystemTable, 字段信息读取, 如:该属性是不是主键,标识列等等信息
+ ConnectionString = GetMainConnectionDb().Connection, //必填, 数据库连接字符串
+ DbType = (SqlSugar.DbType)GetMainConnectionDb().DbType, //必填, 数据库类型
+ IsAutoCloseConnection = true, //默认false, 时候知道关闭数据库连接, 设置为true无需使用using或者Close操作
});
});
@@ -121,19 +120,19 @@ public IContainer DICollections()
builder.RegisterAssemblyTypes(typeof(Startup).Assembly)
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
.PropertiesAutowired();
-
+
var servicesDllFile = Path.Combine(basePath, "Blog.Core.Services.dll");
var assemblysServices = Assembly.LoadFrom(servicesDllFile);
builder.RegisterAssemblyTypes(assemblysServices)
- .AsImplementedInterfaces()
- .InstancePerLifetimeScope()
- .PropertiesAutowired()
- .EnableInterfaceInterceptors();
+ .AsImplementedInterfaces()
+ .InstancePerLifetimeScope()
+ .PropertiesAutowired()
+ .EnableInterfaceInterceptors();
var repositoryDllFile = Path.Combine(basePath, "Blog.Core.Repository.dll");
var assemblysRepository = Assembly.LoadFrom(repositoryDllFile);
builder.RegisterAssemblyTypes(assemblysRepository)
- .PropertiesAutowired().AsImplementedInterfaces();
+ .PropertiesAutowired().AsImplementedInterfaces();
services.Replace(ServiceDescriptor.Transient());
From 1cc3ef25fa1afcb74e159ec18dd65da7ce2a7770 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Tue, 14 Feb 2023 22:14:41 +0800
Subject: [PATCH 026/190] Update DynamicLinqFactory.cs
---
.../Extensions/GenericTypeExtensions.cs | 38 +++++++++----------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/Blog.Core.Common/Extensions/GenericTypeExtensions.cs b/Blog.Core.Common/Extensions/GenericTypeExtensions.cs
index c0b6150f..6c067773 100644
--- a/Blog.Core.Common/Extensions/GenericTypeExtensions.cs
+++ b/Blog.Core.Common/Extensions/GenericTypeExtensions.cs
@@ -33,24 +33,24 @@ public static string GetGenericTypeName(this object @object)
/// 类型
/// 泛型类型
/// bool
- public static bool HasImplementedRawGeneric(this Type type, Type generic)
- {
- // 检查接口类型
- var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
- if (isTheRawGenericType) return true;
-
- // 检查类型
- while (type != null && type != typeof(object))
- {
- isTheRawGenericType = IsTheRawGenericType(type);
- if (isTheRawGenericType) return true;
- type = type.BaseType;
- }
-
- return false;
-
- // 判断逻辑
- bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type);
- }
+ // public static bool HasImplementedRawGeneric(this Type type, Type generic)
+ // {
+ // // 检查接口类型
+ // var isTheRawGenericType = type.GetInterfaces().Any(IsTheRawGenericType);
+ // if (isTheRawGenericType) return true;
+
+ // // 检查类型
+ // while (type != null && type != typeof(object))
+ // {
+ // isTheRawGenericType = IsTheRawGenericType(type);
+ // if (isTheRawGenericType) return true;
+ // type = type.BaseType;
+ // }
+
+ // return false;
+
+ // // 判断逻辑
+ // bool IsTheRawGenericType(Type type) => generic == (type.IsGenericType ? type.GetGenericTypeDefinition() : type);
+ // }
}
}
\ No newline at end of file
From 296201998d4997397c396b6fba1c544d2c9d9926 Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Sat, 18 Feb 2023 01:17:19 +0800
Subject: [PATCH 027/190] =?UTF-8?q?=E2=9C=A8=F0=9F=8E=A8=20=E5=A2=9E?=
=?UTF-8?q?=E5=8A=A0=E5=A4=9A=E7=A7=9F=E6=88=B7-=E5=88=86=E5=BA=93?=
=?UTF-8?q?=E6=96=B9=E6=A1=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1.自动初始化维护租户库
2.多租户库种子数据维护
分库方案 TenantByDbController
---
.gitignore | 1 +
Blog.Core.Api/Blog.Core.Model.xml | 81 +++++----
Blog.Core.Api/Blog.Core.xml | 13 +-
.../Tenant/TenantByDbController.cs | 38 +++++
.../Tenant/TenantByIdController.cs | 2 +-
Blog.Core.Common/Core/InternalApp.cs | 8 +-
Blog.Core.Common/DB/Aop/SqlsugarAop.cs | 2 +-
Blog.Core.Common/DB/BaseDBConfig.cs | 17 +-
Blog.Core.Common/DB/RepositorySetting.cs | 1 +
Blog.Core.Common/DB/TenantUtil.cs | 28 ++++
Blog.Core.Common/Seed/DBSeed.cs | 158 ++++++++++++++++--
.../Seed/SeedData/SubBusinessDataSeedData.cs | 70 ++++++++
.../Seed/SeedData/TenantSeedData.cs | 25 ++-
.../Seed/SeedData/UserInfoSeedData.cs | 40 ++++-
.../HostedService/SeedDataHostedService.cs | 3 +
Blog.Core.Model/Models/BusinessTable.cs | 2 +-
.../Models/SubLibraryBusinessTable.cs | 22 +++
Blog.Core.Model/Models/SysTenant.cs | 2 +-
.../Interface => Tenants}/ITenantEntity.cs | 2 +-
.../Tenants/MultiTenantAttribute.cs | 12 ++
.../TenantTypeEnum.cs | 2 +-
Blog.Core.Repository/BASE/BaseRepository.cs | 84 ++++++----
22 files changed, 520 insertions(+), 93 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs
create mode 100644 Blog.Core.Common/DB/TenantUtil.cs
create mode 100644 Blog.Core.Common/Seed/SeedData/SubBusinessDataSeedData.cs
create mode 100644 Blog.Core.Model/Models/SubLibraryBusinessTable.cs
rename Blog.Core.Model/{Models/RootTkey/Interface => Tenants}/ITenantEntity.cs (81%)
create mode 100644 Blog.Core.Model/Tenants/MultiTenantAttribute.cs
rename Blog.Core.Model/{CustomEnums => Tenants}/TenantTypeEnum.cs (89%)
diff --git a/.gitignore b/.gitignore
index de02add3..b7645c45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -355,3 +355,4 @@ Blog.Core/WMBlog.db
Blog.Core/Blog.Core*.xml
Blog.Core.Api/WMBlog.db
Blog.Core.Api/wwwroot/ui/
+*.db
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 3c1b8ef7..eb7eaab1 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -34,21 +34,6 @@
所有
-
-
- 租户隔离方案
-
-
-
-
- Id隔离
-
-
-
-
- 库隔离
-
-
以下model 来自ids4项目,多库模式,为了调取ids4数据
@@ -316,7 +301,16 @@
逻辑删除
-
+
+
+ 评论
+
+
+
+
+ 博客文章 评论
+
+
业务数据
@@ -336,16 +330,6 @@
金额
-
-
-
- 评论
-
-
-
-
- 博客文章 评论
-
@@ -933,14 +917,20 @@
软删除 过滤器
-
+
- 租户模型接口
+ 多租户-多库方案 业务表
+ 公共库无需标记[MultiTenant]特性
-
+
- 租户Id
+ 名称
+
+
+
+
+ 金额
@@ -1892,6 +1882,37 @@
返回数据集
+
+
+ 租户模型接口
+
+
+
+
+ 租户Id
+
+
+
+
+ 标识 多租户-分库 的业务表
+ 公共表无需区分 直接使用主库 各自业务在各自库中
+
+
+
+
+ 租户隔离方案
+
+
+
+
+ Id隔离
+
+
+
+
+ 库隔离
+
+
广告类
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 8b5b79fd..8effc9f8 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -1236,11 +1236,22 @@
-
+
多租户测试
+
+
+ 获取租户下全部业务数据
+
+
+
+
+
+ 多租户-Id方案 测试
+
+
获取租户下全部业务数据
diff --git a/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs b/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs
new file mode 100644
index 00000000..0d403adb
--- /dev/null
+++ b/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs
@@ -0,0 +1,38 @@
+using Blog.Core.Common.HttpContextUser;
+using Blog.Core.Controllers;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Api.Controllers.Tenant;
+
+///
+/// 多租户测试
+///
+[Produces("application/json")]
+[Route("api/Tenant/ByDb")]
+[Authorize]
+public class TenantByDbController : BaseApiController
+{
+ private readonly IBaseServices _services;
+ private readonly IUser _user;
+
+ public TenantByDbController(IUser user, IBaseServices services)
+ {
+ _user = user;
+ _services = services;
+ }
+
+ ///
+ /// 获取租户下全部业务数据
+ ///
+ ///
+ [HttpGet]
+ public async Task>> GetAll()
+ {
+ var data = await _services.Query();
+ return Success(data);
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs b/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs
index a0271780..b015bc6d 100644
--- a/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs
+++ b/Blog.Core.Api/Controllers/Tenant/TenantByIdController.cs
@@ -9,7 +9,7 @@
namespace Blog.Core.Api.Controllers.Tenant;
///
-/// 多租户测试
+/// 多租户-Id方案 测试
///
[Produces("application/json")]
[Route("api/Tenant/ById")]
diff --git a/Blog.Core.Common/Core/InternalApp.cs b/Blog.Core.Common/Core/InternalApp.cs
index b1f94f9d..c1ae8dcd 100644
--- a/Blog.Core.Common/Core/InternalApp.cs
+++ b/Blog.Core.Common/Core/InternalApp.cs
@@ -1,4 +1,4 @@
-using Microsoft.Extensions.Hosting;
+using Microsoft.AspNetCore.Builder;
using System;
namespace Blog.Core.Common.Core;
@@ -8,8 +8,10 @@ public static class InternalApp
/// 根服务
public static IServiceProvider RootServices;
- public static void ConfigureApplication(this IHost app)
+ public static void ConfigureApplication(this WebApplication app)
{
- RootServices = app.Services;
+ app.Lifetime.ApplicationStarted.Register(() => { InternalApp.RootServices = app.Services; });
+
+ app.Lifetime.ApplicationStopped.Register(() => { InternalApp.RootServices = null; });
}
}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
index 3646625d..3d83b002 100644
--- a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
+++ b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
@@ -1,5 +1,5 @@
using Blog.Core.Model.Models.RootTkey;
-using Blog.Core.Model.Models.RootTkey.Interface;
+using Blog.Core.Model.Tenants;
using SqlSugar;
using System;
diff --git a/Blog.Core.Common/DB/BaseDBConfig.cs b/Blog.Core.Common/DB/BaseDBConfig.cs
index dc7fee4e..b832b6d0 100644
--- a/Blog.Core.Common/DB/BaseDBConfig.cs
+++ b/Blog.Core.Common/DB/BaseDBConfig.cs
@@ -11,6 +11,7 @@ public class BaseDBConfig
* 目前是多库操作,默认加载的是appsettings.json设置为true的第一个db连接。
*/
public static (List allDbs, List slaveDbs) MutiConnectionString => MutiInitConn();
+
private static string DifDBConnOfSecurity(params string[] conn)
{
foreach (var item in conn)
@@ -22,7 +23,9 @@ private static string DifDBConnOfSecurity(params string[] conn)
return File.ReadAllText(item).Trim();
}
}
- catch (System.Exception) { }
+ catch (System.Exception)
+ {
+ }
}
return conn[conn.Length - 1];
@@ -37,8 +40,9 @@ public static (List, List) MutiInitConn()
{
SpecialDbString(i);
}
- List listdatabaseSimpleDB = new List();//单库
- List listdatabaseSlaveDB = new List();//从库
+
+ List listdatabaseSimpleDB = new List(); //单库
+ List listdatabaseSlaveDB = new List(); //从库
// 单库,且不开启读写分离,只保留一个
if (!AppSettings.app(new string[] { "CQRSEnabled" }).ObjToBool() && !AppSettings.app(new string[] { "MutiDBEnabled" }).ObjToBool())
@@ -54,6 +58,7 @@ public static (List, List) MutiInitConn()
{
dbFirst = listdatabase.FirstOrDefault();
}
+
listdatabaseSimpleDB.Add(dbFirst);
return (listdatabaseSimpleDB, listdatabaseSlaveDB);
}
@@ -70,7 +75,6 @@ public static (List, List) MutiInitConn()
}
-
return (listdatabase, listdatabaseSlaveDB);
//}
}
@@ -115,24 +119,29 @@ public enum DataBaseType
Dm = 5,
Kdbndp = 6,
}
+
public class MutiDBOperate
{
///
/// 连接启用开关
///
public bool Enabled { get; set; }
+
///
/// 连接ID
///
public string ConnId { get; set; }
+
///
/// 从库执行级别,越大越先执行
///
public int HitRate { get; set; }
+
///
/// 连接字符串
///
public string Connection { get; set; }
+
///
/// 数据库类型
///
diff --git a/Blog.Core.Common/DB/RepositorySetting.cs b/Blog.Core.Common/DB/RepositorySetting.cs
index 4f2e67d2..e55c7a03 100644
--- a/Blog.Core.Common/DB/RepositorySetting.cs
+++ b/Blog.Core.Common/DB/RepositorySetting.cs
@@ -1,5 +1,6 @@
using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Model.Models.RootTkey.Interface;
+using Blog.Core.Model.Tenants;
using SqlSugar;
using System;
using System.Collections.Generic;
diff --git a/Blog.Core.Common/DB/TenantUtil.cs b/Blog.Core.Common/DB/TenantUtil.cs
new file mode 100644
index 00000000..37ad6909
--- /dev/null
+++ b/Blog.Core.Common/DB/TenantUtil.cs
@@ -0,0 +1,28 @@
+using System;
+using Blog.Core.Model.Models;
+using SqlSugar;
+
+namespace Blog.Core.Common.DB;
+
+public static class TenantUtil
+{
+ public static ConnectionConfig GetConnectionConfig(this SysTenant tenant)
+ {
+ if (tenant.DbType is null)
+ {
+ throw new ArgumentException("Tenant DbType Must");
+ }
+
+ return new ConnectionConfig()
+ {
+ ConfigId = tenant.ConfigId,
+ DbType = tenant.DbType.Value,
+ ConnectionString = tenant.Connection,
+ IsAutoCloseConnection = true,
+ MoreSettings = new ConnMoreSettings()
+ {
+ IsAutoRemoveDataCache = true
+ },
+ };
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 64aeba95..fdbb1ee8 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -11,6 +11,8 @@
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
+using Blog.Core.Model.Tenants;
+using SqlSugar;
namespace Blog.Core.Common.Seed
{
@@ -97,7 +99,9 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
var modelTypes = referencedAssemblies
.SelectMany(a => a.DefinedTypes)
.Select(type => type.AsType())
- .Where(x => x.IsClass && x.Namespace is "Blog.Core.Model.Models").ToList();
+ .Where(x => x.IsClass && x.Namespace is "Blog.Core.Model.Models")
+ .Where(s => !s.IsDefined(typeof(MultiTenantAttribute), false))
+ .ToList();
modelTypes.ForEach(t =>
{
// 这里只支持添加表,不支持删除
@@ -326,7 +330,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
#endregion
//种子初始化
- await SeedDataAsync(myContext);
+ await SeedDataAsync(myContext.Db);
ConsoleHelper.WriteSuccessLine($"Done seeding database!");
}
@@ -347,12 +351,142 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
///
///
///
- private static async Task SeedDataAsync(MyContext myContext)
+ private static async Task SeedDataAsync(ISqlSugarClient db)
{
// 获取所有种子配置-初始化数据
var seedDataTypes = AssemblysExtensions.GetAllAssemblies().SelectMany(s => s.DefinedTypes)
- .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass &&
- u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(IEntitySeedData<>))));
+ .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass)
+ .Where(u =>
+ {
+ var esd = u.GetInterfaces().FirstOrDefault(i => i.HasImplementedRawGeneric(typeof(IEntitySeedData<>)));
+ if (esd is null)
+ {
+ return false;
+ }
+
+ var eType = esd.GenericTypeArguments[0];
+ if (eType.GetCustomAttribute() is null)
+ {
+ return true;
+ }
+
+ return false;
+ });
+
+ if (!seedDataTypes.Any()) return;
+ foreach (var seedType in seedDataTypes)
+ {
+ dynamic instance = Activator.CreateInstance(seedType);
+ //初始化数据
+ {
+ var seedData = instance.InitSeedData();
+ if (seedData != null && Enumerable.Any(seedData))
+ {
+ var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
+ var entity = db.EntityMaintenance.GetEntityInfo(entityType);
+
+ if (!await db.Queryable(entity.DbTableName, "").AnyAsync())
+ {
+ await db.Insertable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
+ Console.WriteLine($"Table:{entity.DbTableName} init success!");
+ }
+ }
+ }
+
+ //种子数据
+ {
+ var seedData = instance.SeedData();
+ if (seedData != null && Enumerable.Any(seedData))
+ {
+ var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
+ var entity = db.EntityMaintenance.GetEntityInfo(entityType);
+
+ await db.Storageable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
+ Console.WriteLine($"Table:{entity.DbTableName} seedData success!");
+ }
+ }
+
+ //自定义处理
+ {
+ await instance.CustomizeSeedData(db);
+ }
+ }
+ }
+
+
+ ///
+ /// 初始化 多租户
+ ///
+ ///
+ ///
+ public static async Task TenantSeedAsync(MyContext myContext)
+ {
+ var tenants = await myContext.Db.Queryable().Where(s => s.TenantType == TenantTypeEnum.Db).ToListAsync();
+ if (!tenants.Any())
+ {
+ return;
+ }
+
+ Console.WriteLine($@"Init Multi Tenant Db");
+ foreach (var tenant in tenants)
+ {
+ Console.WriteLine($@"Init Multi Tenant Db : {tenant.ConfigId}/{tenant.Name}");
+ await InitTenantSeedAsync(myContext.Db.AsTenant(), tenant.GetConnectionConfig());
+ }
+ }
+
+ public static async Task InitTenantSeedAsync(ITenant itenant, ConnectionConfig config)
+ {
+ itenant.AddConnection(config);
+
+ var db = itenant.GetConnectionScope(config.ConfigId);
+
+ db.DbMaintenance.CreateDatabase();
+ ConsoleHelper.WriteSuccessLine($"Init Multi Tenant Db : {config.ConfigId} Database created successfully!");
+
+
+ Console.WriteLine($@"Init Multi Tenant Db : {config.ConfigId} Create Tables");
+ // 获取所有实体表-初始化租户业务表
+ var entityTypes = RepositorySetting.Entitys
+ .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass)
+ .Where(s => s.IsDefined(typeof(MultiTenantAttribute), false));
+ if (!entityTypes.Any()) return;
+ foreach (var entityType in entityTypes)
+ {
+ var splitTable = entityType.GetCustomAttribute();
+ if (splitTable == null)
+ db.CodeFirst.InitTables(entityType);
+ else
+ db.CodeFirst.SplitTables().InitTables(entityType);
+
+ Console.WriteLine(entityType.Name);
+ }
+
+ //多租户初始化种子数据
+ await TenantSeedDataAsync(db);
+ }
+
+ private static async Task TenantSeedDataAsync(ISqlSugarClient db)
+ {
+ // 获取所有种子配置-初始化数据
+ var seedDataTypes = AssemblysExtensions.GetAllAssemblies().SelectMany(s => s.DefinedTypes)
+ .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass)
+ .Where(u =>
+ {
+ var esd = u.GetInterfaces().FirstOrDefault(i => i.HasImplementedRawGeneric(typeof(IEntitySeedData<>)));
+ if (esd is null)
+ {
+ return false;
+ }
+
+ var eType = esd.GenericTypeArguments[0];
+ if (eType.GetCustomAttribute() is null)
+ {
+ return false;
+ }
+
+ return true;
+ });
if (!seedDataTypes.Any()) return;
foreach (var seedType in seedDataTypes)
{
@@ -363,11 +497,11 @@ private static async Task SeedDataAsync(MyContext myContext)
if (seedData != null && Enumerable.Any(seedData))
{
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
- var entity = myContext.Db.EntityMaintenance.GetEntityInfo(entityType);
+ var entity = db.EntityMaintenance.GetEntityInfo(entityType);
- if (!await myContext.Db.Queryable(entity.DbTableName, "").AnyAsync())
+ if (!await db.Queryable(entity.DbTableName, "").AnyAsync())
{
- await myContext.Db.Insertable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
+ await db.Insertable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
Console.WriteLine($"Table:{entity.DbTableName} init success!");
}
}
@@ -379,18 +513,18 @@ private static async Task SeedDataAsync(MyContext myContext)
if (seedData != null && Enumerable.Any(seedData))
{
var entityType = seedType.GetInterfaces().First().GetGenericArguments().First();
- var entity = myContext.Db.EntityMaintenance.GetEntityInfo(entityType);
+ var entity = db.EntityMaintenance.GetEntityInfo(entityType);
- await myContext.Db.Storageable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
+ await db.Storageable(Enumerable.ToList(seedData)).ExecuteCommandAsync();
Console.WriteLine($"Table:{entity.DbTableName} seedData success!");
}
}
//自定义处理
{
- await instance.CustomizeSeedData(myContext.Db);
+ await instance.CustomizeSeedData(db);
}
}
}
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/SubBusinessDataSeedData.cs b/Blog.Core.Common/Seed/SeedData/SubBusinessDataSeedData.cs
new file mode 100644
index 00000000..be8462e8
--- /dev/null
+++ b/Blog.Core.Common/Seed/SeedData/SubBusinessDataSeedData.cs
@@ -0,0 +1,70 @@
+using Blog.Core.Model.Models;
+using SqlSugar;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Seed.SeedData;
+
+public class SubBusinessDataSeedData : IEntitySeedData
+{
+ public IEnumerable InitSeedData()
+ {
+ return default;
+ }
+
+ public IEnumerable SeedData()
+ {
+ return default;
+ }
+
+ public async Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ //初始化分库数据
+ //只是用于测试
+ if (db.CurrentConnectionConfig.ConfigId == "Tenant_3")
+ {
+ if (!await db.Queryable().AnyAsync())
+ {
+ await db.Insertable(new List()
+ {
+ new()
+ {
+ Id = SnowFlakeSingle.Instance.NextId(),
+ Name = "王五业务数据1",
+ Amount = 100,
+ },
+ new()
+ {
+ Id = SnowFlakeSingle.Instance.NextId(),
+ Name = "王五业务数据2",
+ Amount = 1000,
+ },
+ }).ExecuteReturnSnowflakeIdListAsync();
+ }
+ }
+ else if (db.CurrentConnectionConfig.ConfigId == "Tenant_4")
+ {
+ if (!await db.Queryable().AnyAsync())
+ {
+ await db.Insertable(new List()
+ {
+ new()
+ {
+ Id = SnowFlakeSingle.Instance.NextId(),
+ Name = "赵六业务数据1",
+ Amount = 50,
+ },
+ new()
+ {
+ Id = SnowFlakeSingle.Instance.NextId(),
+ Name = "赵六业务数据2",
+ Amount = 60,
+ },
+ }).ExecuteReturnSnowflakeIdListAsync();
+ }
+ }
+
+
+ await Task.Delay(1);
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs b/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
index 89945547..0a0fb5b4 100644
--- a/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
+++ b/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
@@ -1,7 +1,10 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.IO;
using System.Threading.Tasks;
-using Blog.Core.Model.CustomEnums;
+using Blog.Core.Common.DB;
using Blog.Core.Model.Models;
+using Blog.Core.Model.Tenants;
using SqlSugar;
namespace Blog.Core.Common.Seed.SeedData;
@@ -29,6 +32,24 @@ public IEnumerable InitSeedData()
Name = "李四",
TenantType = TenantTypeEnum.Id
},
+ new SysTenant()
+ {
+ Id = 1000003,
+ ConfigId = "Tenant_3",
+ Name = "王五",
+ TenantType = TenantTypeEnum.Db,
+ DbType = DbType.Sqlite,
+ Connection = $"DataSource=" + Path.Combine(Environment.CurrentDirectory, "WangWu.db"),
+ },
+ new SysTenant()
+ {
+ Id = 1000004,
+ ConfigId = "Tenant_4",
+ Name = "赵六",
+ TenantType = TenantTypeEnum.Db,
+ DbType = DbType.Sqlite,
+ Connection = $"DataSource=" + Path.Combine(Environment.CurrentDirectory, "ZhaoLiu.db"),
+ },
};
}
diff --git a/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs b/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
index c00eb798..8a96a030 100644
--- a/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
+++ b/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using Blog.Core.Model.Models;
using SqlSugar;
@@ -14,7 +15,12 @@ public IEnumerable InitSeedData()
public IEnumerable SeedData()
{
- return new[]
+ return default;
+ }
+
+ public async Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ var data = new List()
{
new SysUserInfo()
{
@@ -32,11 +38,35 @@ public IEnumerable SeedData()
Name = "李四",
TenantId = 1000002, //租户Id
},
+ new SysUserInfo()
+ {
+ Id = 10003,
+ LoginName = "wangwu",
+ LoginPWD = "E10ADC3949BA59ABBE56E057F20F883E",
+ Name = "王五",
+ TenantId = 1000003, //租户Id
+ },
+ new SysUserInfo()
+ {
+ Id = 10004,
+ LoginName = "zhaoliu",
+ LoginPWD = "E10ADC3949BA59ABBE56E057F20F883E",
+ Name = "赵六",
+ TenantId = 1000004, //租户Id
+ },
};
- }
- public Task CustomizeSeedData(ISqlSugarClient db)
- {
- return Task.CompletedTask;
+ var names = data.Select(s => s.LoginName).ToList();
+ names = await db.Queryable()
+ .Where(s => names.Contains(s.LoginName))
+ .Select(s => s.LoginName).ToListAsync();
+
+ var sysUserInfos = data.Where(s => !names.Contains(s.LoginName)).ToList();
+ if (sysUserInfos.Any())
+ {
+ await db.Insertable(sysUserInfos).ExecuteReturnIdentityAsync();
+ }
+
+ await Task.CompletedTask;
}
}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs b/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs
index beef5a75..868d750e 100644
--- a/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs
+++ b/Blog.Core.Extensions/HostedService/SeedDataHostedService.cs
@@ -38,6 +38,9 @@ private async Task DoWork()
if (AppSettings.app("AppSettings", "SeedDBEnabled").ObjToBool() || AppSettings.app("AppSettings", "SeedDBDataEnabled").ObjToBool())
{
await DBSeed.SeedAsync(_myContext, _webRootPath);
+
+ //多租户 同步
+ await DBSeed.TenantSeedAsync(_myContext);
}
}
catch (Exception ex)
diff --git a/Blog.Core.Model/Models/BusinessTable.cs b/Blog.Core.Model/Models/BusinessTable.cs
index 01a18716..b3b0140a 100644
--- a/Blog.Core.Model/Models/BusinessTable.cs
+++ b/Blog.Core.Model/Models/BusinessTable.cs
@@ -1,5 +1,5 @@
using Blog.Core.Model.Models.RootTkey;
-using Blog.Core.Model.Models.RootTkey.Interface;
+using Blog.Core.Model.Tenants;
namespace Blog.Core.Model.Models;
diff --git a/Blog.Core.Model/Models/SubLibraryBusinessTable.cs b/Blog.Core.Model/Models/SubLibraryBusinessTable.cs
new file mode 100644
index 00000000..446fb436
--- /dev/null
+++ b/Blog.Core.Model/Models/SubLibraryBusinessTable.cs
@@ -0,0 +1,22 @@
+using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model.Tenants;
+
+namespace Blog.Core.Model.Models;
+
+///
+/// 多租户-多库方案 业务表
+/// 公共库无需标记[MultiTenant]特性
+///
+[MultiTenant]
+public class SubLibraryBusinessTable : BaseEntity
+{
+ ///
+ /// 名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 金额
+ ///
+ public decimal Amount { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/SysTenant.cs b/Blog.Core.Model/Models/SysTenant.cs
index 7e6f195d..61d03866 100644
--- a/Blog.Core.Model/Models/SysTenant.cs
+++ b/Blog.Core.Model/Models/SysTenant.cs
@@ -1,4 +1,4 @@
-using Blog.Core.Model.CustomEnums;
+using Blog.Core.Model.Tenants;
using SqlSugar;
namespace Blog.Core.Model.Models;
diff --git a/Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs b/Blog.Core.Model/Tenants/ITenantEntity.cs
similarity index 81%
rename from Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs
rename to Blog.Core.Model/Tenants/ITenantEntity.cs
index 350312b8..2d0c5dc9 100644
--- a/Blog.Core.Model/Models/RootTkey/Interface/ITenantEntity.cs
+++ b/Blog.Core.Model/Tenants/ITenantEntity.cs
@@ -1,6 +1,6 @@
using SqlSugar;
-namespace Blog.Core.Model.Models.RootTkey.Interface;
+namespace Blog.Core.Model.Tenants;
///
/// 租户模型接口
diff --git a/Blog.Core.Model/Tenants/MultiTenantAttribute.cs b/Blog.Core.Model/Tenants/MultiTenantAttribute.cs
new file mode 100644
index 00000000..9c3938a9
--- /dev/null
+++ b/Blog.Core.Model/Tenants/MultiTenantAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Blog.Core.Model.Tenants;
+
+///
+/// 标识 多租户-分库 的业务表
+/// 公共表无需区分 直接使用主库 各自业务在各自库中
+///
+[AttributeUsage(AttributeTargets.Class)]
+public class MultiTenantAttribute : Attribute
+{
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/CustomEnums/TenantTypeEnum.cs b/Blog.Core.Model/Tenants/TenantTypeEnum.cs
similarity index 89%
rename from Blog.Core.Model/CustomEnums/TenantTypeEnum.cs
rename to Blog.Core.Model/Tenants/TenantTypeEnum.cs
index a445414b..46ae999c 100644
--- a/Blog.Core.Model/CustomEnums/TenantTypeEnum.cs
+++ b/Blog.Core.Model/Tenants/TenantTypeEnum.cs
@@ -1,6 +1,6 @@
using System.ComponentModel;
-namespace Blog.Core.Model.CustomEnums;
+namespace Blog.Core.Model.Tenants;
///
/// 租户隔离方案
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index 82900689..1845e958 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -8,6 +8,10 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
+using Blog.Core.Common.DB;
+using Blog.Core.Common.HttpContextUser;
+using Blog.Core.Model.Models;
+using Blog.Core.Model.Tenants;
using Blog.Core.Repository.UnitOfWorks;
namespace Blog.Core.Repository.Base
@@ -22,11 +26,12 @@ private ISqlSugarClient _db
get
{
ISqlSugarClient db = _dbBase;
+
/* 如果要开启多库支持,
* 1、在appsettings.json 中开启MutiDBEnabled节点为true,必填
* 2、设置一个主连接的数据库ID,节点MainDB,对应的连接字符串的Enabled也必须true,必填
*/
- if (AppSettings.app(new[] {"MutiDBEnabled"}).ObjToBool())
+ if (AppSettings.app(new[] { "MutiDBEnabled" }).ObjToBool())
{
//修改使用 model备注字段作为切换数据库条件,使用sqlsugar TenantAttribute存放数据库ConnId
//参考 https://www.donet5.com/Home/Doc?typeId=2246
@@ -35,6 +40,27 @@ private ISqlSugarClient _db
{
//统一处理 configId 小写
db = _dbBase.GetConnectionScope(tenantAttr.configId.ToString().ToLower());
+ return db;
+ }
+ }
+
+ //多租户
+ if (typeof(TEntity).GetCustomAttribute() != null)
+ {
+ //获取租户信息 租户信息可以提前缓存下来
+ if (App.User is { TenantId: > 0 })
+ {
+ var tenant = db.Queryable().WithCache().Where(s => s.Id == App.User.TenantId).First();
+ if (tenant != null)
+ {
+ var iTenant = db.AsTenant();
+ if (!iTenant.IsAnyConnection(tenant.ConfigId))
+ {
+ iTenant.AddConnection(tenant.GetConnectionConfig());
+ }
+
+ return iTenant.GetConnectionScope(tenant.ConfigId);
+ }
}
}
@@ -51,12 +77,12 @@ public BaseRepository(IUnitOfWorkManage unitOfWorkManage)
}
-
public async Task QueryById(object objId)
{
//return await Task.Run(() => _db.Queryable().InSingle(objId));
return await _db.Queryable().In(objId).SingleAsync();
}
+
///
/// 功能描述:根据ID查询一条数据
/// 作 者:Blog.Core
@@ -161,25 +187,28 @@ public async Task Update(object operateAnonymousObjects)
}
public async Task Update(
- TEntity entity,
- List lstColumns = null,
- List lstIgnoreColumns = null,
- string where = ""
- )
+ TEntity entity,
+ List lstColumns = null,
+ List lstIgnoreColumns = null,
+ string where = ""
+ )
{
IUpdateable up = _db.Updateable(entity);
if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0)
{
up = up.IgnoreColumns(lstIgnoreColumns.ToArray());
}
+
if (lstColumns != null && lstColumns.Count > 0)
{
up = up.UpdateColumns(lstColumns.ToArray());
}
+
if (!string.IsNullOrEmpty(where))
{
up = up.Where(where);
}
+
return await up.ExecuteCommandHasChangeAsync();
}
@@ -214,7 +243,6 @@ public async Task DeleteByIds(object[] ids)
}
-
///
/// 功能描述:查询所有数据
/// 作 者:Blog.Core
@@ -284,6 +312,7 @@ public async Task> Query(Expression> whereExpr
{
return await _db.Queryable().WhereIF(whereExpression != null, whereExpression).OrderByIF(orderByFields != null, orderByFields).ToListAsync();
}
+
///
/// 功能描述:查询一个列表
///
@@ -393,18 +422,16 @@ public async Task> Query(
/// 排序字段,如name asc,age desc
/// 数据列表
public async Task> Query(
- string where,
- int pageIndex,
- int pageSize,
-
- string orderByFields)
+ string where,
+ int pageIndex,
+ int pageSize,
+ string orderByFields)
{
return await _db.Queryable().OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
.WhereIF(!string.IsNullOrEmpty(where), where).ToPageListAsync(pageIndex, pageSize);
}
-
///
/// 分页查询[使用版本,其他分页未测试]
///
@@ -415,12 +442,11 @@ public async Task> Query(
///
public async Task> QueryPage(Expression> whereExpression, int pageIndex = 1, int pageSize = 20, string orderByFields = null)
{
-
RefAsync totalCount = 0;
var list = await _db.Queryable()
- .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
- .WhereIF(whereExpression != null, whereExpression)
- .ToPageListAsync(pageIndex, pageSize, totalCount);
+ .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
+ .WhereIF(whereExpression != null, whereExpression)
+ .ToPageListAsync(pageIndex, pageSize, totalCount);
return new PageModel(pageIndex, totalCount, pageSize, list);
}
@@ -446,6 +472,7 @@ public async Task> QueryMuch(
{
return await _db.Queryable(joinExpression).Select(selectExpression).ToListAsync();
}
+
return await _db.Queryable(joinExpression).Where(whereLambda).Select(selectExpression).ToListAsync();
}
@@ -471,13 +498,12 @@ public async Task> QueryTabsPage(
int pageSize = 20,
string orderByFields = null)
{
-
RefAsync totalCount = 0;
var list = await _db.Queryable(joinExpression)
- .Select(selectExpression)
- .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
- .WhereIF(whereExpression != null, whereExpression)
- .ToPageListAsync(pageIndex, pageSize, totalCount);
+ .Select(selectExpression)
+ .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
+ .WhereIF(whereExpression != null, whereExpression)
+ .ToPageListAsync(pageIndex, pageSize, totalCount);
return new PageModel(pageIndex, totalCount, pageSize, list);
}
@@ -506,10 +532,10 @@ public async Task> QueryTabsPage(
{
RefAsync totalCount = 0;
var list = await _db.Queryable(joinExpression).GroupBy(groupExpression)
- .Select(selectExpression)
- .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
- .WhereIF(whereExpression != null, whereExpression)
- .ToPageListAsync(pageIndex, pageSize, totalCount);
+ .Select(selectExpression)
+ .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
+ .WhereIF(whereExpression != null, whereExpression)
+ .ToPageListAsync(pageIndex, pageSize, totalCount);
return new PageModel(pageIndex, totalCount, pageSize, list);
}
@@ -531,7 +557,5 @@ public async Task> QueryTabsPage(
// groupName = s.groupName,
// jobName = s.jobName
// }, exp, s => new { s.uID, s.uRealName, s.groupName, s.jobName }, model.currentPage, model.pageSize, model.orderField + " " + model.orderType);
-
}
-
-}
+}
\ No newline at end of file
From d85087cbdb3b44e559da5d65adf7448f96363f35 Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Sat, 18 Feb 2023 20:58:43 +0800
Subject: [PATCH 028/190] =?UTF-8?q?=F0=9F=8E=A8=E2=9C=A8=20=E5=A4=9A?=
=?UTF-8?q?=E7=A7=9F=E6=88=B7=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1.完善多租户-多库方案
2.增加租户管理 (实际业务中 也是运维、系统管理员等角色来操作 甚至直接维护数据库而不会开放接口)
---
Blog.Core.Api/Blog.Core.xml | 44 ++++++++++
.../Tenant/TenantByDbController.cs | 14 ++-
.../Tenant/TenantManagerController.cs | 87 +++++++++++++++++++
Blog.Core.Common/DB/BaseDBConfig.cs | 5 +-
Blog.Core.Common/DB/TenantUtil.cs | 22 +++++
Blog.Core.Common/Seed/DBSeed.cs | 3 +-
Blog.Core.IServices/ITenantService.cs | 12 +++
Blog.Core.Services/TenantService.cs | 57 ++++++++++++
8 files changed, 241 insertions(+), 3 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/Tenant/TenantManagerController.cs
create mode 100644 Blog.Core.IServices/ITenantService.cs
create mode 100644 Blog.Core.Services/TenantService.cs
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 8effc9f8..b41b293c 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -1247,6 +1247,12 @@
+
+
+ 新增数据
+
+
+
多租户-Id方案 测试
@@ -1264,6 +1270,44 @@
+
+
+ 租户管理
+
+
+
+
+ 获取全部租户
+
+
+
+
+
+ 获取租户信息
+
+
+
+
+
+ 新增租户信息
+ 此处只做演示,具体要以实际业务为准
+
+
+
+
+
+ 修改租户信息
+ 此处只做演示,具体要以实际业务为准
+
+
+
+
+
+ 删除租户
+ 此处只做演示,具体要以实际业务为准
+
+
+
自定义路由 /api/{version}/[controler]/[action]
diff --git a/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs b/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs
index 0d403adb..046f7f7b 100644
--- a/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs
+++ b/Blog.Core.Api/Controllers/Tenant/TenantByDbController.cs
@@ -9,7 +9,7 @@
namespace Blog.Core.Api.Controllers.Tenant;
///
-/// 多租户测试
+/// 多租户-多库方案 测试
///
[Produces("application/json")]
[Route("api/Tenant/ByDb")]
@@ -35,4 +35,16 @@ public async Task>> GetAll()
var data = await _services.Query();
return Success(data);
}
+
+ ///
+ /// 新增数据
+ ///
+ ///
+ [HttpPost]
+ public async Task Post(SubLibraryBusinessTable data)
+ {
+ await _services.Db.Insertable(data).ExecuteReturnSnowflakeIdAsync();
+
+ return Success();
+ }
}
\ No newline at end of file
diff --git a/Blog.Core.Api/Controllers/Tenant/TenantManagerController.cs b/Blog.Core.Api/Controllers/Tenant/TenantManagerController.cs
new file mode 100644
index 00000000..90133fdb
--- /dev/null
+++ b/Blog.Core.Api/Controllers/Tenant/TenantManagerController.cs
@@ -0,0 +1,87 @@
+using Blog.Core.Controllers;
+using Blog.Core.IServices;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Api.Controllers.Tenant;
+
+///
+/// 租户管理
+///
+[Produces("application/json")]
+[Route("api/TenantManager")]
+[Authorize]
+public class TenantManagerController : BaseApiController
+{
+ private readonly ITenantService _services;
+
+ public TenantManagerController(ITenantService services)
+ {
+ _services = services;
+ }
+
+
+ ///
+ /// 获取全部租户
+ ///
+ ///
+ [HttpGet]
+ public async Task>> GetAll()
+ {
+ var data = await _services.Query();
+ return Success(data);
+ }
+
+
+ ///
+ /// 获取租户信息
+ ///
+ ///
+ [HttpGet("{id}")]
+ public async Task> GetInfo(long id)
+ {
+ var data = await _services.QueryById(id);
+ return Success(data);
+ }
+
+ ///
+ /// 新增租户信息
+ /// 此处只做演示,具体要以实际业务为准
+ ///
+ ///
+ [HttpPost]
+ public async Task Post(SysTenant tenant)
+ {
+ await _services.SaveTenant(tenant);
+ return Success();
+ }
+
+ ///
+ /// 修改租户信息
+ /// 此处只做演示,具体要以实际业务为准
+ ///
+ ///
+ [HttpPut]
+ public async Task Put(SysTenant tenant)
+ {
+ await _services.SaveTenant(tenant);
+ return Success();
+ }
+
+ ///
+ /// 删除租户
+ /// 此处只做演示,具体要以实际业务为准
+ ///
+ ///
+ [HttpDelete]
+ public async Task Delete(long id)
+ {
+ //是否删除租户库?
+ //要根据实际情况而定
+ //例如直接删除租户库、备份租户库到xx
+ await _services.DeleteById(id);
+ return Success();
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/BaseDBConfig.cs b/Blog.Core.Common/DB/BaseDBConfig.cs
index b832b6d0..1d86369a 100644
--- a/Blog.Core.Common/DB/BaseDBConfig.cs
+++ b/Blog.Core.Common/DB/BaseDBConfig.cs
@@ -1,4 +1,5 @@
-using System;
+using SqlSugar;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -106,6 +107,8 @@ private static MutiDBOperate SpecialDbString(MutiDBOperate mutiDBOperate)
return mutiDBOperate;
}
+
+
}
diff --git a/Blog.Core.Common/DB/TenantUtil.cs b/Blog.Core.Common/DB/TenantUtil.cs
index 37ad6909..deac60a4 100644
--- a/Blog.Core.Common/DB/TenantUtil.cs
+++ b/Blog.Core.Common/DB/TenantUtil.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Blog.Core.Model.Models;
using SqlSugar;
@@ -6,6 +7,26 @@ namespace Blog.Core.Common.DB;
public static class TenantUtil
{
+ public static SysTenant DefaultTenantConfig(this SysTenant tenant)
+ {
+ tenant.DbType ??= DbType.Sqlite;
+
+ //如果没有配置连接
+ if (tenant.Connection.IsNullOrEmpty())
+ {
+ //此处默认配置 Sqlite 地址
+ //实际业务中 也会有运维、系统管理员等来维护
+ switch (tenant.DbType.Value)
+ {
+ case DbType.Sqlite:
+ tenant.Connection = $"DataSource={Path.Combine(Environment.CurrentDirectory, tenant.ConfigId)}.db" ;
+ break;
+ }
+ }
+
+ return tenant;
+ }
+
public static ConnectionConfig GetConnectionConfig(this SysTenant tenant)
{
if (tenant.DbType is null)
@@ -13,6 +34,7 @@ public static ConnectionConfig GetConnectionConfig(this SysTenant tenant)
throw new ArgumentException("Tenant DbType Must");
}
+
return new ConnectionConfig()
{
ConfigId = tenant.ConfigId,
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index fdbb1ee8..a6952e6e 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -372,7 +372,7 @@ private static async Task SeedDataAsync(ISqlSugarClient db)
return false;
});
-
+
if (!seedDataTypes.Any()) return;
foreach (var seedType in seedDataTypes)
{
@@ -437,6 +437,7 @@ public static async Task TenantSeedAsync(MyContext myContext)
public static async Task InitTenantSeedAsync(ITenant itenant, ConnectionConfig config)
{
+ itenant.RemoveConnection(config.ConfigId);
itenant.AddConnection(config);
var db = itenant.GetConnectionScope(config.ConfigId);
diff --git a/Blog.Core.IServices/ITenantService.cs b/Blog.Core.IServices/ITenantService.cs
new file mode 100644
index 00000000..0927b793
--- /dev/null
+++ b/Blog.Core.IServices/ITenantService.cs
@@ -0,0 +1,12 @@
+using System.Threading.Tasks;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model.Models;
+
+namespace Blog.Core.IServices;
+
+public interface ITenantService : IBaseServices
+{
+ public Task SaveTenant(SysTenant tenant);
+
+ public Task InitTenantDb(SysTenant tenant);
+}
\ No newline at end of file
diff --git a/Blog.Core.Services/TenantService.cs b/Blog.Core.Services/TenantService.cs
new file mode 100644
index 00000000..a552442b
--- /dev/null
+++ b/Blog.Core.Services/TenantService.cs
@@ -0,0 +1,57 @@
+using Blog.Core.Common.DB;
+using Blog.Core.Common.Seed;
+using Blog.Core.IServices;
+using Blog.Core.Model.Models;
+using Blog.Core.Repository.UnitOfWorks;
+using Blog.Core.Services.BASE;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Services;
+
+public class TenantService : BaseServices, ITenantService
+{
+ private readonly IUnitOfWorkManage _uowManager;
+
+ public TenantService(IUnitOfWorkManage uowManage)
+ {
+ this._uowManager = uowManage;
+ }
+
+
+ public async Task SaveTenant(SysTenant tenant)
+ {
+ bool initDb = tenant.Id == 0;
+ using (var uow = _uowManager.CreateUnitOfWork())
+ {
+
+ tenant.DefaultTenantConfig();
+
+ if (tenant.Id == 0)
+ {
+ await Db.Insertable(tenant).ExecuteReturnSnowflakeIdAsync();
+ }
+ else
+ {
+ var oldTenant = await QueryById(tenant.Id);
+ if (oldTenant.Connection != tenant.Connection)
+ {
+ initDb = true;
+ }
+
+ await Db.Updateable(tenant).ExecuteCommandAsync();
+ }
+
+ uow.Commit();
+ }
+
+ if (initDb)
+ {
+ await InitTenantDb(tenant);
+ }
+ }
+
+ public async Task InitTenantDb(SysTenant tenant)
+ {
+ await DBSeed.InitTenantSeedAsync(Db.AsTenant(), tenant.GetConnectionConfig());
+ }
+}
\ No newline at end of file
From bd484137a65431c6ba5af07f93991b72e6afaf38 Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Tue, 21 Feb 2023 01:50:51 +0800
Subject: [PATCH 029/190] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=F0=9F=8E=A8=20?=
=?UTF-8?q?=E5=AE=8C=E7=BE=8E=E4=BC=98=E9=9B=85=E7=9A=84=E5=A4=84=E7=90=86?=
=?UTF-8?q?=E5=A4=9A=E7=A7=9F=E6=88=B7-=E5=88=86=E8=A1=A8=E6=96=B9?=
=?UTF-8?q?=E6=A1=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
1.扩展原有的MultiTenantAttribute 标识多库、多表
2.扩展原有的种子数据生成 用于多表的种子数据
3.巧妙优雅使用Sqlsugar表映射 解决多租户分表问题,原有代码无需改动 登录用户如果是租户用户自动切换到租户分表
目前来看(如果想要升级业务 扩展SAAS)
多表方案:代码侵入最小
id方案:侵入最大,需要增加列
多库方案:相对少
如果是从0到1 最推荐多库
如果是从0.5到1 最推荐多表
---
Blog.Core.Api/Blog.Core.Api.csproj | 1 -
Blog.Core.Api/Blog.Core.Model.xml | 104 +++++++++++-------
Blog.Core.Api/Blog.Core.xml | 19 +++-
.../Tenant/TenantByTableController.cs | 57 ++++++++++
Blog.Core.Common/DB/RepositorySetting.cs | 4 +
Blog.Core.Common/DB/TenantUtil.cs | 54 ++++++++-
.../Extensions/UntilExtensions.cs | 18 +++
Blog.Core.Common/Seed/DBSeed.cs | 78 +++++++++----
.../SeedData/MultiBusinessDataSeedData.cs | 38 +++++++
.../SeedData/MultiBusinessSubDataSeedData.cs | 38 +++++++
.../Seed/SeedData/TenantSeedData.cs | 7 ++
.../Seed/SeedData/UserInfoSeedData.cs | 8 ++
.../Models/{ => Tenant}/BusinessTable.cs | 0
.../Models/Tenant/MultiBusinessSubTable.cs | 14 +++
.../Models/Tenant/MultiBusinessTable.cs | 26 +++++
.../{ => Tenant}/SubLibraryBusinessTable.cs | 0
.../Tenants/MultiTenantAttribute.cs | 16 ++-
Blog.Core.Model/Tenants/TenantTypeEnum.cs | 6 +
Blog.Core.Repository/BASE/BaseRepository.cs | 12 +-
Blog.Core.Tests/Repository_Test/OrmTest.cs | 73 ++++++++++++
20 files changed, 503 insertions(+), 70 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/Tenant/TenantByTableController.cs
create mode 100644 Blog.Core.Common/Extensions/UntilExtensions.cs
create mode 100644 Blog.Core.Common/Seed/SeedData/MultiBusinessDataSeedData.cs
create mode 100644 Blog.Core.Common/Seed/SeedData/MultiBusinessSubDataSeedData.cs
rename Blog.Core.Model/Models/{ => Tenant}/BusinessTable.cs (100%)
create mode 100644 Blog.Core.Model/Models/Tenant/MultiBusinessSubTable.cs
create mode 100644 Blog.Core.Model/Models/Tenant/MultiBusinessTable.cs
rename Blog.Core.Model/Models/{ => Tenant}/SubLibraryBusinessTable.cs (100%)
create mode 100644 Blog.Core.Tests/Repository_Test/OrmTest.cs
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 7e17937a..77d681f1 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -98,7 +98,6 @@
-
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index eb7eaab1..0e9ddbb0 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -311,27 +311,6 @@
博客文章 评论
-
-
- 业务数据
- 多租户 (Id 隔离)
-
-
-
-
- 无需手动赋值
-
-
-
-
- 名称
-
-
-
-
- 金额
-
-
部门表
@@ -917,22 +896,6 @@
软删除 过滤器
-
-
- 多租户-多库方案 业务表
- 公共库无需标记[MultiTenant]特性
-
-
-
-
- 名称
-
-
-
-
- 金额
-
-
系统租户表
@@ -1145,6 +1108,63 @@
任务内存中的状态
+
+
+ 业务数据
+ 多租户 (Id 隔离)
+
+
+
+
+ 无需手动赋值
+
+
+
+
+ 名称
+
+
+
+
+ 金额
+
+
+
+
+ 多租户-多表方案 业务表 子表
+
+
+
+
+ 多租户-多表方案 业务表
+
+
+
+
+ 名称
+
+
+
+
+ 金额
+
+
+
+
+ 多租户-多库方案 业务表
+ 公共库无需标记[MultiTenant]特性
+
+
+
+
+ 名称
+
+
+
+
+ 金额
+
+
Tibug 类别
@@ -1894,8 +1914,9 @@
- 标识 多租户-分库 的业务表
- 公共表无需区分 直接使用主库 各自业务在各自库中
+ 标识 多租户 的业务表
+ 默认设置是多库
+ 公共表无需区分 直接使用主库 各自业务在各自库中
@@ -1913,6 +1934,11 @@
库隔离
+
+
+ 表隔离
+
+
广告类
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index b41b293c..8180287b 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -1238,7 +1238,7 @@
- 多租户测试
+ 多租户-多库方案 测试
@@ -1270,6 +1270,23 @@
+
+
+ 多租户-多表方案 测试
+
+
+
+
+ 获取租户下全部业务数据
+
+
+
+
+
+ 新增数据
+
+
+
租户管理
diff --git a/Blog.Core.Api/Controllers/Tenant/TenantByTableController.cs b/Blog.Core.Api/Controllers/Tenant/TenantByTableController.cs
new file mode 100644
index 00000000..6c0b110e
--- /dev/null
+++ b/Blog.Core.Api/Controllers/Tenant/TenantByTableController.cs
@@ -0,0 +1,57 @@
+using Blog.Core.Common.HttpContextUser;
+using Blog.Core.Controllers;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+
+namespace Blog.Core.Api.Controllers.Tenant;
+
+///
+/// 多租户-多表方案 测试
+///
+[Produces("application/json")]
+[Route("api/Tenant/ByTable")]
+[Authorize]
+public class TenantByTableController : BaseApiController
+{
+ private readonly IBaseServices _services;
+ private readonly IUser _user;
+
+ public TenantByTableController(IUser user, IBaseServices services)
+ {
+ _user = user;
+ _services = services;
+ }
+
+ ///
+ /// 获取租户下全部业务数据
+ ///
+ ///
+ [HttpGet]
+ public async Task>> GetAll()
+ {
+ //查询
+ // var data = await _services.Query();
+
+ //关联查询
+ var data = await _services.Db
+ .Queryable()
+ .Includes(s => s.Child)
+ .ToListAsync();
+ return Success(data);
+ }
+
+ ///
+ /// 新增数据
+ ///
+ ///
+ [HttpPost]
+ public async Task Post(MultiBusinessTable data)
+ {
+ await _services.Db.Insertable(data).ExecuteReturnSnowflakeIdAsync();
+
+ return Success();
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/RepositorySetting.cs b/Blog.Core.Common/DB/RepositorySetting.cs
index e55c7a03..bfca7174 100644
--- a/Blog.Core.Common/DB/RepositorySetting.cs
+++ b/Blog.Core.Common/DB/RepositorySetting.cs
@@ -39,6 +39,10 @@ public static void SetTenantEntityFilter(SqlSugarScopeProvider db)
return;
}
+ //多租户 单表
db.QueryFilter.AddTableFilter(it => it.TenantId == App.User.TenantId || it.TenantId == 0);
+
+ //多租户 多表
+ db.SetTenantTable(App.User.TenantId.ToString());
}
}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/TenantUtil.cs b/Blog.Core.Common/DB/TenantUtil.cs
index deac60a4..8d57189b 100644
--- a/Blog.Core.Common/DB/TenantUtil.cs
+++ b/Blog.Core.Common/DB/TenantUtil.cs
@@ -1,6 +1,10 @@
using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
+using System.Reflection;
using Blog.Core.Model.Models;
+using Blog.Core.Model.Tenants;
using SqlSugar;
namespace Blog.Core.Common.DB;
@@ -19,7 +23,7 @@ public static SysTenant DefaultTenantConfig(this SysTenant tenant)
switch (tenant.DbType.Value)
{
case DbType.Sqlite:
- tenant.Connection = $"DataSource={Path.Combine(Environment.CurrentDirectory, tenant.ConfigId)}.db" ;
+ tenant.Connection = $"DataSource={Path.Combine(Environment.CurrentDirectory, tenant.ConfigId)}.db";
break;
}
}
@@ -47,4 +51,52 @@ public static ConnectionConfig GetConnectionConfig(this SysTenant tenant)
},
};
}
+
+ public static List GetTenantEntityTypes(TenantTypeEnum? tenantType = null)
+ {
+ return RepositorySetting.Entitys
+ .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass)
+ .Where(s => IsTenantEntity(s, tenantType))
+ .ToList();
+ }
+
+ public static bool IsTenantEntity(this Type u, TenantTypeEnum? tenantType = null)
+ {
+ var mta = u.GetCustomAttribute();
+ if (mta is null)
+ {
+ return false;
+ }
+
+ if (tenantType != null)
+ {
+ if (mta.TenantType != tenantType)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public static string GetTenantTableName(this Type type, ISqlSugarClient db, string id)
+ {
+ var entityInfo = db.EntityMaintenance.GetEntityInfo(type);
+ return $@"{entityInfo.DbTableName}_{id}";
+ }
+
+ public static string GetTenantTableName(this Type type, ISqlSugarClient db, SysTenant tenant)
+ {
+ return GetTenantTableName(type, db, tenant.Id.ToString());
+ }
+
+ public static void SetTenantTable(this ISqlSugarClient db, string id)
+ {
+ var types = GetTenantEntityTypes(TenantTypeEnum.Tables);
+
+ foreach (var type in types)
+ {
+ db.MappingTables.Add(type.Name, type.GetTenantTableName(db, id));
+ }
+ }
}
\ No newline at end of file
diff --git a/Blog.Core.Common/Extensions/UntilExtensions.cs b/Blog.Core.Common/Extensions/UntilExtensions.cs
new file mode 100644
index 00000000..1ae503b2
--- /dev/null
+++ b/Blog.Core.Common/Extensions/UntilExtensions.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+
+namespace Blog.Core.Common.Extensions;
+
+public static class UntilExtensions
+{
+ public static void AddOrModify(this IDictionary dic, TKey key, TValue value)
+ {
+ if (dic.TryGetValue(key, out _))
+ {
+ dic[key] = value;
+ }
+ else
+ {
+ dic.Add(key, value);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index a6952e6e..36bf184c 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -2,8 +2,10 @@
using Blog.Core.Common.Extensions;
using Blog.Core.Common.Helper;
using Blog.Core.Model.Models;
+using Blog.Core.Model.Tenants;
using Magicodes.ExporterAndImporter.Excel;
using Newtonsoft.Json;
+using SqlSugar;
using System;
using System.Collections.Generic;
using System.IO;
@@ -11,8 +13,6 @@
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
-using Blog.Core.Model.Tenants;
-using SqlSugar;
namespace Blog.Core.Common.Seed
{
@@ -422,19 +422,62 @@ private static async Task SeedDataAsync(ISqlSugarClient db)
public static async Task TenantSeedAsync(MyContext myContext)
{
var tenants = await myContext.Db.Queryable().Where(s => s.TenantType == TenantTypeEnum.Db).ToListAsync();
- if (!tenants.Any())
+ if (tenants.Any())
{
- return;
+ Console.WriteLine($@"Init Multi Tenant Db");
+ foreach (var tenant in tenants)
+ {
+ Console.WriteLine($@"Init Multi Tenant Db : {tenant.ConfigId}/{tenant.Name}");
+ await InitTenantSeedAsync(myContext.Db.AsTenant(), tenant.GetConnectionConfig());
+ }
}
- Console.WriteLine($@"Init Multi Tenant Db");
- foreach (var tenant in tenants)
+ tenants = await myContext.Db.Queryable().Where(s => s.TenantType == TenantTypeEnum.Tables).ToListAsync();
+ if (tenants.Any())
{
- Console.WriteLine($@"Init Multi Tenant Db : {tenant.ConfigId}/{tenant.Name}");
- await InitTenantSeedAsync(myContext.Db.AsTenant(), tenant.GetConnectionConfig());
+ await InitTenantSeedAsync(myContext, tenants);
}
}
+ #region 多租户 多表 初始化
+
+ private static async Task InitTenantSeedAsync(MyContext myContext, List tenants)
+ {
+ ConsoleHelper.WriteInfoLine($"Init Multi Tenant Tables : {myContext.Db.CurrentConnectionConfig.ConfigId}");
+
+ // 获取所有实体表-初始化租户业务表
+ var entityTypes = TenantUtil.GetTenantEntityTypes(TenantTypeEnum.Tables);
+ if (!entityTypes.Any()) return;
+
+ foreach (var sysTenant in tenants)
+ {
+ foreach (var entityType in entityTypes)
+ {
+ myContext.Db.CodeFirst
+ .As(entityType, entityType.GetTenantTableName(myContext.Db, sysTenant))
+ .InitTables(entityType);
+
+ Console.WriteLine($@"Init Tables:{entityType.GetTenantTableName(myContext.Db, sysTenant)}");
+ }
+
+ myContext.Db.SetTenantTable(sysTenant.Id.ToString());
+ //多租户初始化种子数据
+ await TenantSeedDataAsync(myContext.Db, TenantTypeEnum.Tables);
+ }
+
+ ConsoleHelper.WriteSuccessLine($"Init Multi Tenant Tables : {myContext.Db.CurrentConnectionConfig.ConfigId} created successfully!");
+ }
+
+ #endregion
+
+ #region 多租户 多库 初始化
+
+ ///
+ /// 初始化多库
+ ///
+ ///
+ ///
+ ///
public static async Task InitTenantSeedAsync(ITenant itenant, ConnectionConfig config)
{
itenant.RemoveConnection(config.ConfigId);
@@ -445,12 +488,10 @@ public static async Task InitTenantSeedAsync(ITenant itenant, ConnectionConfig c
db.DbMaintenance.CreateDatabase();
ConsoleHelper.WriteSuccessLine($"Init Multi Tenant Db : {config.ConfigId} Database created successfully!");
-
Console.WriteLine($@"Init Multi Tenant Db : {config.ConfigId} Create Tables");
+
// 获取所有实体表-初始化租户业务表
- var entityTypes = RepositorySetting.Entitys
- .Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass)
- .Where(s => s.IsDefined(typeof(MultiTenantAttribute), false));
+ var entityTypes = TenantUtil.GetTenantEntityTypes(TenantTypeEnum.Db);
if (!entityTypes.Any()) return;
foreach (var entityType in entityTypes)
{
@@ -464,10 +505,12 @@ public static async Task InitTenantSeedAsync(ITenant itenant, ConnectionConfig c
}
//多租户初始化种子数据
- await TenantSeedDataAsync(db);
+ await TenantSeedDataAsync(db, TenantTypeEnum.Db);
}
- private static async Task TenantSeedDataAsync(ISqlSugarClient db)
+ #endregion
+
+ private static async Task TenantSeedDataAsync(ISqlSugarClient db, TenantTypeEnum tenantType)
{
// 获取所有种子配置-初始化数据
var seedDataTypes = AssemblysExtensions.GetAllAssemblies().SelectMany(s => s.DefinedTypes)
@@ -481,12 +524,7 @@ private static async Task TenantSeedDataAsync(ISqlSugarClient db)
}
var eType = esd.GenericTypeArguments[0];
- if (eType.GetCustomAttribute() is null)
- {
- return false;
- }
-
- return true;
+ return eType.IsTenantEntity(tenantType);
});
if (!seedDataTypes.Any()) return;
foreach (var seedType in seedDataTypes)
diff --git a/Blog.Core.Common/Seed/SeedData/MultiBusinessDataSeedData.cs b/Blog.Core.Common/Seed/SeedData/MultiBusinessDataSeedData.cs
new file mode 100644
index 00000000..4ca1a7dd
--- /dev/null
+++ b/Blog.Core.Common/Seed/SeedData/MultiBusinessDataSeedData.cs
@@ -0,0 +1,38 @@
+using Blog.Core.Model.Models;
+using SqlSugar;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Seed.SeedData;
+
+public class MultiBusinessDataSeedData : IEntitySeedData
+{
+ public IEnumerable InitSeedData()
+ {
+ return new List()
+ {
+ new()
+ {
+ Id = 1001,
+ Name = "业务数据1",
+ Amount = 100,
+ },
+ new()
+ {
+ Id = 1002,
+ Name = "业务数据2",
+ Amount = 1000,
+ },
+ };
+ }
+
+ public IEnumerable SeedData()
+ {
+ return default;
+ }
+
+ public Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/MultiBusinessSubDataSeedData.cs b/Blog.Core.Common/Seed/SeedData/MultiBusinessSubDataSeedData.cs
new file mode 100644
index 00000000..e73d4603
--- /dev/null
+++ b/Blog.Core.Common/Seed/SeedData/MultiBusinessSubDataSeedData.cs
@@ -0,0 +1,38 @@
+using Blog.Core.Model.Models;
+using SqlSugar;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Seed.SeedData;
+
+public class MultiBusinessSubDataSeedData : IEntitySeedData
+{
+ public IEnumerable InitSeedData()
+ {
+ return new List()
+ {
+ new()
+ {
+ Id = 100,
+ MainId = 1001,
+ Memo = "子数据",
+ },
+ new()
+ {
+ Id = 1001,
+ MainId = 1001,
+ Memo = "子数据2",
+ },
+ };
+ }
+
+ public IEnumerable SeedData()
+ {
+ return default;
+ }
+
+ public Task CustomizeSeedData(ISqlSugarClient db)
+ {
+ return Task.CompletedTask;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs b/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
index 0a0fb5b4..f33f83b2 100644
--- a/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
+++ b/Blog.Core.Common/Seed/SeedData/TenantSeedData.cs
@@ -50,6 +50,13 @@ public IEnumerable InitSeedData()
DbType = DbType.Sqlite,
Connection = $"DataSource=" + Path.Combine(Environment.CurrentDirectory, "ZhaoLiu.db"),
},
+ new SysTenant()
+ {
+ Id = 1000005,
+ ConfigId = "Tenant_5",
+ Name = "孙七",
+ TenantType = TenantTypeEnum.Tables,
+ },
};
}
diff --git a/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs b/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
index 8a96a030..414a506b 100644
--- a/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
+++ b/Blog.Core.Common/Seed/SeedData/UserInfoSeedData.cs
@@ -54,6 +54,14 @@ public async Task CustomizeSeedData(ISqlSugarClient db)
Name = "赵六",
TenantId = 1000004, //租户Id
},
+ new SysUserInfo()
+ {
+ Id = 10005,
+ LoginName = "sunqi",
+ LoginPWD = "E10ADC3949BA59ABBE56E057F20F883E",
+ Name = "孙七",
+ TenantId = 1000005, //租户Id
+ },
};
var names = data.Select(s => s.LoginName).ToList();
diff --git a/Blog.Core.Model/Models/BusinessTable.cs b/Blog.Core.Model/Models/Tenant/BusinessTable.cs
similarity index 100%
rename from Blog.Core.Model/Models/BusinessTable.cs
rename to Blog.Core.Model/Models/Tenant/BusinessTable.cs
diff --git a/Blog.Core.Model/Models/Tenant/MultiBusinessSubTable.cs b/Blog.Core.Model/Models/Tenant/MultiBusinessSubTable.cs
new file mode 100644
index 00000000..1ada394d
--- /dev/null
+++ b/Blog.Core.Model/Models/Tenant/MultiBusinessSubTable.cs
@@ -0,0 +1,14 @@
+using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model.Tenants;
+
+namespace Blog.Core.Model.Models;
+
+///
+/// 多租户-多表方案 业务表 子表
+///
+[MultiTenant(TenantTypeEnum.Tables)]
+public class MultiBusinessSubTable : BaseEntity
+{
+ public long MainId { get; set; }
+ public string Memo { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/Tenant/MultiBusinessTable.cs b/Blog.Core.Model/Models/Tenant/MultiBusinessTable.cs
new file mode 100644
index 00000000..619bdaaf
--- /dev/null
+++ b/Blog.Core.Model/Models/Tenant/MultiBusinessTable.cs
@@ -0,0 +1,26 @@
+using System.Collections.Generic;
+using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model.Tenants;
+using SqlSugar;
+
+namespace Blog.Core.Model.Models;
+
+///
+/// 多租户-多表方案 业务表
+///
+[MultiTenant(TenantTypeEnum.Tables)]
+public class MultiBusinessTable : BaseEntity
+{
+ ///
+ /// 名称
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// 金额
+ ///
+ public decimal Amount { get; set; }
+
+ [Navigate(NavigateType.OneToMany, nameof(MultiBusinessSubTable.MainId))]
+ public List Child { get; set; }
+}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/SubLibraryBusinessTable.cs b/Blog.Core.Model/Models/Tenant/SubLibraryBusinessTable.cs
similarity index 100%
rename from Blog.Core.Model/Models/SubLibraryBusinessTable.cs
rename to Blog.Core.Model/Models/Tenant/SubLibraryBusinessTable.cs
diff --git a/Blog.Core.Model/Tenants/MultiTenantAttribute.cs b/Blog.Core.Model/Tenants/MultiTenantAttribute.cs
index 9c3938a9..443745bf 100644
--- a/Blog.Core.Model/Tenants/MultiTenantAttribute.cs
+++ b/Blog.Core.Model/Tenants/MultiTenantAttribute.cs
@@ -3,10 +3,22 @@
namespace Blog.Core.Model.Tenants;
///
-/// 标识 多租户-分库 的业务表
-/// 公共表无需区分 直接使用主库 各自业务在各自库中
+/// 标识 多租户 的业务表
+/// 默认设置是多库
+/// 公共表无需区分 直接使用主库 各自业务在各自库中
///
[AttributeUsage(AttributeTargets.Class)]
public class MultiTenantAttribute : Attribute
{
+ public MultiTenantAttribute()
+ {
+ }
+
+ public MultiTenantAttribute(TenantTypeEnum tenantType)
+ {
+ TenantType = tenantType;
+ }
+
+
+ public TenantTypeEnum TenantType { get; set; } = TenantTypeEnum.Db;
}
\ No newline at end of file
diff --git a/Blog.Core.Model/Tenants/TenantTypeEnum.cs b/Blog.Core.Model/Tenants/TenantTypeEnum.cs
index 46ae999c..f4af3bda 100644
--- a/Blog.Core.Model/Tenants/TenantTypeEnum.cs
+++ b/Blog.Core.Model/Tenants/TenantTypeEnum.cs
@@ -20,4 +20,10 @@ public enum TenantTypeEnum
///
[Description("库隔离")]
Db = 2,
+
+ ///
+ /// 表隔离
+ ///
+ [Description("表隔离")]
+ Tables = 3,
}
\ No newline at end of file
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index 1845e958..828f9506 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -1,6 +1,10 @@
using Blog.Core.Common;
+using Blog.Core.Common.DB;
using Blog.Core.IRepository.Base;
using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Blog.Core.Model.Tenants;
+using Blog.Core.Repository.UnitOfWorks;
using SqlSugar;
using System;
using System.Collections.Generic;
@@ -8,11 +12,6 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
-using Blog.Core.Common.DB;
-using Blog.Core.Common.HttpContextUser;
-using Blog.Core.Model.Models;
-using Blog.Core.Model.Tenants;
-using Blog.Core.Repository.UnitOfWorks;
namespace Blog.Core.Repository.Base
{
@@ -45,7 +44,8 @@ private ISqlSugarClient _db
}
//多租户
- if (typeof(TEntity).GetCustomAttribute() != null)
+ var mta = typeof(TEntity).GetCustomAttribute();
+ if (mta is { TenantType: TenantTypeEnum.Db })
{
//获取租户信息 租户信息可以提前缓存下来
if (App.User is { TenantId: > 0 })
diff --git a/Blog.Core.Tests/Repository_Test/OrmTest.cs b/Blog.Core.Tests/Repository_Test/OrmTest.cs
new file mode 100644
index 00000000..fa4629f7
--- /dev/null
+++ b/Blog.Core.Tests/Repository_Test/OrmTest.cs
@@ -0,0 +1,73 @@
+using System;
+using Autofac;
+using Blog.Core.Common.Extensions;
+using Blog.Core.IRepository.Base;
+using Blog.Core.Model.Models;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
+using SqlSugar;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace Blog.Core.Tests;
+
+public class OrmTest
+{
+ private readonly ITestOutputHelper _testOutputHelper;
+ private readonly IBaseRepository _baseRepository;
+ DI_Test dI_Test = new DI_Test();
+
+ public OrmTest(ITestOutputHelper testOutputHelper)
+ {
+ _testOutputHelper = testOutputHelper;
+
+ var container = dI_Test.DICollections();
+
+ _baseRepository = container.Resolve>();
+ _baseRepository.Db.Aop.OnLogExecuting = (sql, p) =>
+ {
+ _testOutputHelper.WriteLine("");
+ _testOutputHelper.WriteLine("==================FullSql=====================", "", new string[] { sql.GetType().ToString(), GetParas(p), "【SQL语句】:" + sql });
+ _testOutputHelper.WriteLine("【SQL语句】:" + sql);
+ _testOutputHelper.WriteLine(GetParas(p));
+ _testOutputHelper.WriteLine("==============================================");
+ _testOutputHelper.WriteLine("");
+ };
+ }
+
+ private static string GetParas(SugarParameter[] pars)
+ {
+ string key = "【SQL参数】:";
+ foreach (var param in pars)
+ {
+ key += $"{param.ParameterName}:{param.Value}\n";
+ }
+
+ return key;
+ }
+
+ [Fact]
+ public void MultiTables()
+ {
+ var sql = _baseRepository.Db.Queryable()
+ .AS($@"{nameof(BlogArticle)}_TenantA")
+ .ToSqlString();
+ //_testOutputHelper.WriteLine(sql);
+
+ _baseRepository.Db.MappingTables.Add(nameof(BlogArticle), $@"{nameof(BlogArticle)}_TenantA");
+
+ var query = _baseRepository.Db.Queryable()
+ .LeftJoin((a, c) => a.bID == c.bID);
+ // query.QueryBuilder.AsTables.AddOrModify(nameof(BlogArticle), $@"{nameof(BlogArticle)}_TenantA");
+ //query.QueryBuilder.AsTables.AddOrModify(nameof(BlogArticleComment), $@"{nameof(BlogArticleComment)}_TenantA");
+ // query.QueryBuilder.AsTables.AddOrModify(nameof(BlogArticleComment), $@"{nameof(BlogArticleComment)}_TenantA");
+ // query.QueryBuilder.AsTables.AddOrModify(nameof(SysUserInfo), $@"{nameof(SysUserInfo)}_TenantA");
+
+
+ sql = query.ToSqlString();
+
+ _testOutputHelper.WriteLine(sql);
+
+ sql = _baseRepository.Db.Deleteable().ToSqlString();
+ _testOutputHelper.WriteLine(sql);
+ }
+}
\ No newline at end of file
From 8d9aeed6229069b800396cd4a93fe0746afc544e Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 24 Feb 2023 09:31:27 +0800
Subject: [PATCH 030/190] feat: change permission api para
---
Blog.Core.Api/Blog.Core.xml | 3 ++-
Blog.Core.Api/Controllers/PermissionController.cs | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 8180287b..1464a9b1 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -374,12 +374,13 @@
-
+
获取菜单
+
diff --git a/Blog.Core.Api/Controllers/PermissionController.cs b/Blog.Core.Api/Controllers/PermissionController.cs
index d3000766..70f8f689 100644
--- a/Blog.Core.Api/Controllers/PermissionController.cs
+++ b/Blog.Core.Api/Controllers/PermissionController.cs
@@ -61,13 +61,13 @@ public PermissionController(IPermissionServices permissionServices, IModuleServi
///
///
///
+ ///
///
// GET: api/User
[HttpGet]
- public async Task>> Get(int page = 1, string key = "")
+ public async Task>> Get(int page = 1, string key = "", int pageSize = 50)
{
PageModel permissions = new PageModel();
- int intPageSize = 50;
if (string.IsNullOrEmpty(key) || string.IsNullOrWhiteSpace(key))
{
key = "";
@@ -88,7 +88,7 @@ public async Task>> Get(int page = 1, string
- permissions = await _permissionServices.QueryPage(a => a.IsDeleted != true && (a.Name != null && a.Name.Contains(key)), page, intPageSize, " Id desc ");
+ permissions = await _permissionServices.QueryPage(a => a.IsDeleted != true && (a.Name != null && a.Name.Contains(key)), page, pageSize, " Id desc ");
#region 单独处理
From 99bb71816543d59e89a83229ddf2c085c9d246a6 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Fri, 24 Feb 2023 17:37:58 +0800
Subject: [PATCH 031/190] feat:change quartz endtime
---
Blog.Core.Api/wwwroot/BlogCore.Data.json/TasksQz.tsv | 8 ++++----
Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs | 2 ++
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/TasksQz.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/TasksQz.tsv
index c9f80890..2fa2c648 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/TasksQz.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/TasksQz.tsv
@@ -2,16 +2,16 @@
{
"Name": "博客管理",
"JobGroup": "博客测试组",
- "TriggerType": 1,
- "Cron": "0 */10 * * * ?",
+ "TriggerType": 1,
+ "Cron": "0 */5 * * * ?",
"AssemblyName": "Blog.Core.Tasks",
"ClassName": "Job_Blogs_Quartz",
"Remark": "",
"RunTimes": 0,
"BeginTime": "\/Date(1546272000000+0800)\/",
- "EndTime": "\/Date(1640966400000+0800)\/",
+ "EndTime": "\/Date(8888888800000+0800)\/",
"IntervalSecond": 0,
- "CycleRunTimes": 0,
+ "CycleRunTimes": 0,
"IsStart": true,
"JobParams": 1,
"IsDeleted": false,
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
index 173e996e..41310533 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
@@ -1,5 +1,6 @@
using Blog.Core.IServices;
using Quartz;
+using System;
using System.Threading.Tasks;
///
@@ -22,6 +23,7 @@ public async Task Execute(IJobExecutionContext context)
}
public async Task Run(IJobExecutionContext context)
{
+ System.Console.WriteLine($"Job_Blogs_Quartz 执行 {DateTime.Now.ToShortTimeString()}");
var list = await _blogArticleServices.Query();
// 也可以通过数据库配置,获取传递过来的参数
JobDataMap data = context.JobDetail.JobDataMap;
From 1f1525640c4ff5aeb97357ce042d4c9d983809cc Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 25 Feb 2023 14:02:29 +0800
Subject: [PATCH 032/190] Fixed #334 BUG
---
Blog.Core.Common/Helper/SM/SM4.cs | 3 ++-
Blog.Core.Gateway/Blog.Core.Gateway.csproj | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/Blog.Core.Common/Helper/SM/SM4.cs b/Blog.Core.Common/Helper/SM/SM4.cs
index 4b1f1996..b4aa3ebf 100644
--- a/Blog.Core.Common/Helper/SM/SM4.cs
+++ b/Blog.Core.Common/Helper/SM/SM4.cs
@@ -10,7 +10,9 @@ public class SM4
private long GET_ULONG_BE(SByte[] b, int i)
{
+#pragma warning disable CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符
long n2 = (b[i] & 0xFF) << 24 | (b[(i + 1)] & 0xFF) << 16 | (b[(i + 2)] & 0xFF) << 8 | b[(i + 3)] & 0xFF & 0xFFFFFFFF;
+#pragma warning restore CS0675 // 对进行了带符号扩展的操作数使用了按位或运算符
return n2;
}
@@ -207,7 +209,6 @@ public SByte[] sm4_crypt_ecb(SM4_Context ctx, SByte[] input)
int length = input.Length;
SByte[] bins = new SByte[length];
SByte[] bous = new SByte[length];
- SByte[] output = null;
Array.Copy(input, 0, bins, 0, length);
diff --git a/Blog.Core.Gateway/Blog.Core.Gateway.csproj b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
index 47398520..f784da5c 100644
--- a/Blog.Core.Gateway/Blog.Core.Gateway.csproj
+++ b/Blog.Core.Gateway/Blog.Core.Gateway.csproj
@@ -15,9 +15,9 @@
-
-
-
+
+
+
From 82bea16164be19860f63ca1221dcba0710823f16 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sat, 25 Feb 2023 16:27:45 +0800
Subject: [PATCH 033/190] Update README.md
---
README.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 7f37ce66..74076edc 100644
--- a/README.md
+++ b/README.md
@@ -74,7 +74,7 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x
#### 框架模块:
- [x] 采用`仓储+服务+接口`的形式封装框架;
- [x] 异步 async/await 开发;
-- [x] 接入国产数据库ORM组件 —— SqlSugar,封装数据库操作;
+- [x] 接入国产数据库ORM组件 —— SqlSugar,封装数据库操作,支持级联操作;
- [x] 支持自由切换多种数据库,MySql/SqlServer/Sqlite/Oracle/Postgresql/达梦/人大金仓;
- [x] 实现项目启动,自动生成种子数据 ✨;
- [x] 实现数据库主键类型配置化,什么类型都可以自定义 ✨;
@@ -87,6 +87,8 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x
- [x] 封装`Blog.Core.Webapi.Template`项目模板,一键重建自己的项目 ✨;
- [x] 搭配多个前端案例供参考和借鉴:Blog.Vue、Blog.Admin、Nuxt.tbug、Blog.Mvp.Blazor ✨;
- [x] 统一集成 IdentityServer4 认证 ✨;
+- [x] 统一实现多租户;
+
组件模块:
- [x] 提供 Redis 做缓存处理;
@@ -111,6 +113,9 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x
- [x] 新增 Kafka 消息队列,并配合实现EventBus ✨;
- [x] 新增 微信公众号管理,并集成到Blog.Admin后台 ✨;
- [x] 新增 - 数据部门权限;
+- [x] 新增 - Log4net集成日志数据持久化到数据库;
+- [x] 新增 - 多租户模式(单表,多表,多库三种模式);
+
微服务模块:
- [x] 可配合 Docker 实现容器化;
From 6ad74a5385c447c3ca190450869f2fcd3b5c6732 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Sun, 26 Feb 2023 17:36:39 +0800
Subject: [PATCH 034/190] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 74076edc..9b88b0a0 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,7 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x
- [x] 五种日志记录,审计/异常/请求响应/服务操作/Sql记录等,并自动持久化到数据库表🎶;
- [x] 支持项目事务处理(若要分布式,用cap即可)✨;
- [x] 设计4种 AOP 切面编程,功能涵盖:日志、缓存、审计、事务 ✨;
+- [x] Log4net 多种日志自动生成到数据库中,目前支持MySql/SqlServer/Sqlite/Oracle/Postgresql🎉;
- [x] 设计并支持按钮级别的RBAC权限控制,同时支持一键同步接口和菜单 🎶;
- [x] 支持 T4 代码模板,自动生成每层代码;
- [x] 或使用 DbFirst 一键创建自己项目的四层文件(支持多库);
From 77f16b55e18a9105ad97fc35b11cee7ea87690e9 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 26 Feb 2023 18:32:49 +0800
Subject: [PATCH 035/190] feat: :flipper: update publish linux sh
---
Blog.Core.Build.bat | 1 -
Blog.Core.Gateway/Program.cs | 4 +++-
...tings.Development.json => appsettings.gw.Development.json} | 0
Blog.Core.Gateway/{appsettings.json => appsettings.gw.json} | 0
Blog.Core.Publish.Linux.sh | 3 ++-
5 files changed, 5 insertions(+), 3 deletions(-)
rename Blog.Core.Gateway/{appsettings.Development.json => appsettings.gw.Development.json} (100%)
rename Blog.Core.Gateway/{appsettings.json => appsettings.gw.json} (100%)
diff --git a/Blog.Core.Build.bat b/Blog.Core.Build.bat
index 632e841c..7d614aa4 100644
--- a/Blog.Core.Build.bat
+++ b/Blog.Core.Build.bat
@@ -1,4 +1,3 @@
-git pull
@echo off
diff --git a/Blog.Core.Gateway/Program.cs b/Blog.Core.Gateway/Program.cs
index 1ba46816..9c1ba1ce 100644
--- a/Blog.Core.Gateway/Program.cs
+++ b/Blog.Core.Gateway/Program.cs
@@ -15,7 +15,9 @@ public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
- config.AddJsonFile("ocelot.json", optional: true, reloadOnChange: true)
+ config.AddJsonFile("appsettings.gw.json", optional: true, reloadOnChange: false)
+ .AddJsonFile($"appsettings.gw.{hostingContext.HostingEnvironment.EnvironmentName}.json", optional: true, reloadOnChange: false)
+ .AddJsonFile("ocelot.json", optional: true, reloadOnChange: true)
.AddJsonFile($"ocelot.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true);
})
.ConfigureWebHostDefaults(webBuilder =>
diff --git a/Blog.Core.Gateway/appsettings.Development.json b/Blog.Core.Gateway/appsettings.gw.Development.json
similarity index 100%
rename from Blog.Core.Gateway/appsettings.Development.json
rename to Blog.Core.Gateway/appsettings.gw.Development.json
diff --git a/Blog.Core.Gateway/appsettings.json b/Blog.Core.Gateway/appsettings.gw.json
similarity index 100%
rename from Blog.Core.Gateway/appsettings.json
rename to Blog.Core.Gateway/appsettings.gw.json
diff --git a/Blog.Core.Publish.Linux.sh b/Blog.Core.Publish.Linux.sh
index 05eb8103..7599f204 100644
--- a/Blog.Core.Publish.Linux.sh
+++ b/Blog.Core.Publish.Linux.sh
@@ -1,8 +1,9 @@
-git pull;
+
find .PublishFiles/ -type f -and ! -path '*/wwwroot/images/*' ! -name 'appsettings.*' |xargs rm -rf
dotnet build;
rm -rf /home/Blog.Core/Blog.Core.Api/bin/Debug/.PublishFiles;
dotnet publish -o /home/Blog.Core/Blog.Core.Api/bin/Debug/.PublishFiles;
+rm -rf /home/Blog.Core/Blog.Core.Api/bin/Debug/.PublishFiles/WMBlog.db;
# cp -r /home/Blog.Core/Blog.Core.Api/bin/Debug/.PublishFiles ./;
awk 'BEGIN { cmd="cp -ri /home/Blog.Core/Blog.Core.Api/bin/Debug/.PublishFiles ./"; print "n" |cmd; }'
echo "Successfully!!!! ^ please see the file .PublishFiles";
\ No newline at end of file
From 56082ca0ecc464f1b16a378ff2be12bc822a0afe Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Mon, 27 Feb 2023 20:30:58 +0800
Subject: [PATCH 036/190] =?UTF-8?q?=E4=B8=BB=E8=A6=81=E4=BC=98=E5=8C=96=20?=
=?UTF-8?q?1.=E6=B7=BB=E5=8A=A0=E8=B0=83=E5=BA=A6=E6=97=A5=E5=BF=97?=
=?UTF-8?q?=E5=AD=90=E8=A1=A8=202.=E6=B7=BB=E5=8A=A0=E8=B0=83=E5=BA=A6?=
=?UTF-8?q?=E6=97=A5=E5=BF=97=E6=9F=A5=E8=AF=A2=203.=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E8=B0=83=E5=BA=A6=E6=97=A5=E5=BF=97=E6=8A=98=E7=BA=BF=E5=9B=BE?=
=?UTF-8?q?=E6=9F=A5=E8=AF=A2=204.=E5=AE=8C=E5=96=84=E8=B0=83=E5=BA=A6?=
=?UTF-8?q?=E6=8C=89=E5=BE=AA=E7=8E=AF=E6=AC=A1=E6=95=B0=E6=89=A7=E8=A1=8C?=
=?UTF-8?q?=E4=BB=BB=E5=8A=A1=E5=AE=8C=E6=88=90=E5=90=8E=E4=B8=8D=E8=87=AA?=
=?UTF-8?q?=E5=8A=A8=E7=BB=93=E6=9D=9F=E4=BB=BB=E5=8A=A1=E5=AF=BC=E8=87=B4?=
=?UTF-8?q?=E4=B8=8B=E6=AC=A1=E5=90=AF=E5=8A=A8=E9=A1=B9=E7=9B=AE=E4=BC=9A?=
=?UTF-8?q?=E9=87=8D=E5=A4=8D=E6=89=A7=E8=A1=8C=E8=B0=83=E5=BA=A6=E4=BB=BB?=
=?UTF-8?q?=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 90 +++
Blog.Core.Api/Blog.Core.xml | 18 +
.../Controllers/TasksQzController.cs | 35 +-
Blog.Core.Api/appsettings.json | 596 +++++++++---------
.../wwwroot/BlogCore.Data.json/Modules.tsv | 44 ++
.../wwwroot/BlogCore.Data.json/Permission.tsv | 42 ++
Blog.Core.Common/Seed/DBSeed.cs | 13 +
Blog.Core.IServices/ITasksLogServices.cs | 19 +
Blog.Core.Model/Models/TasksLog.cs | 87 +++
Blog.Core.Model/Models/TasksQz.cs | 4 +
Blog.Core.Services/TasksLogServices.cs | 133 ++++
Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs | 43 +-
.../Jobs/Job_AccessTrendLog_Quartz.cs | 3 +-
.../QuartzNet/Jobs/Job_Blogs_Quartz.cs | 4 +-
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 6 +-
.../QuartzNet/SchedulerCenterServer.cs | 6 +
16 files changed, 824 insertions(+), 319 deletions(-)
create mode 100644 Blog.Core.IServices/ITasksLogServices.cs
create mode 100644 Blog.Core.Model/Models/TasksLog.cs
create mode 100644 Blog.Core.Services/TasksLogServices.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 0e9ddbb0..6bbfd4fe 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -1023,6 +1023,91 @@
租户Id
+
+
+ 任务日志表
+
+
+
+
+ 任务ID
+
+
+
+
+ 任务耗时
+
+
+
+
+ 执行结果(0-失败 1-成功)
+
+
+
+
+ 运行时间
+
+
+
+
+ 结束时间
+
+
+
+
+ 执行参数
+
+
+
+
+ 异常信息
+
+
+
+
+ 异常堆栈
+
+
+
+
+ 创建ID
+
+
+
+
+ 创建者
+
+
+
+
+ 创建时间
+
+
+
+
+ 修改ID
+
+
+
+
+ 修改者
+
+
+
+
+ 修改时间
+
+
+
+
+ 任务名称
+
+
+
+
+ 任务分组
+
+
任务计划表
@@ -1088,6 +1173,11 @@
循环执行次数
+
+
+ 已循环次数
+
+
是否启动
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 1464a9b1..af6321da 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -576,6 +576,24 @@
+
+
+ 获取任务运行日志
+
+
+
+
+
+
+
+
+ 任务概况
+
+
+
+
+
+
类别管理【无权限】
diff --git a/Blog.Core.Api/Controllers/TasksQzController.cs b/Blog.Core.Api/Controllers/TasksQzController.cs
index 264fa195..e5c866c3 100644
--- a/Blog.Core.Api/Controllers/TasksQzController.cs
+++ b/Blog.Core.Api/Controllers/TasksQzController.cs
@@ -4,11 +4,14 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
+using Blog.Core.Common.Extensions;
+using Blog.Core.Common.WebApiClients.HttpApis;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Blog.Core.Model.ViewModels;
using Blog.Core.Repository.UnitOfWorks;
+using Blog.Core.Services;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -22,14 +25,16 @@ namespace Blog.Core.Controllers
public class TasksQzController : ControllerBase
{
private readonly ITasksQzServices _tasksQzServices;
+ private readonly ITasksLogServices _tasksLogServices;
private readonly ISchedulerCenter _schedulerCenter;
private readonly IUnitOfWorkManage _unitOfWorkManage;
- public TasksQzController(ITasksQzServices tasksQzServices, ISchedulerCenter schedulerCenter, IUnitOfWorkManage unitOfWorkManage)
+ public TasksQzController(ITasksQzServices tasksQzServices, ISchedulerCenter schedulerCenter, IUnitOfWorkManage unitOfWorkManage,ITasksLogServices tasksLogServices)
{
_unitOfWorkManage = unitOfWorkManage;
- _tasksQzServices = tasksQzServices;
+ _tasksQzServices = tasksQzServices;
_schedulerCenter = schedulerCenter;
+ _tasksLogServices = tasksLogServices;
}
///
@@ -523,6 +528,32 @@ public async Task> ExecuteJob(int jobId)
}
return data;
}
+ ///
+ /// 获取任务运行日志
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task>> GetTaskLogs(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart =null, DateTime? runTimeEnd = null)
+ {
+ var model = await _tasksLogServices.GetTaskLogs(jobId, page, pageSize, runTimeStart, runTimeEnd);
+ return MessageModel>.Message(model.dataCount >= 0, "获取成功", model);
+ }
+ ///
+ /// 任务概况
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public async Task> GetTaskOverview(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null, string type ="month")
+ {
+ var model = await _tasksLogServices.GetTaskOverview(jobId, runTimeStart, runTimeEnd, type);
+ return MessageModel.Message(true, "获取成功", model);
+ }
}
}
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index ea678174..3c117375 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -1,98 +1,98 @@
{
- "urls": "http://*:9291", //web服务端口,如果用IIS部署,把这个去掉
- "Logging": {
- "LogLevel": {
- "Default": "Information", //加入Default否则log4net本地写入不了日志
- "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
+ "urls": "http://*:9291", //web服务端口,如果用IIS部署,把这个去掉
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information", //加入Default否则log4net本地写入不了日志
+ "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
+ },
+ "Debug": {
+ "IncludeScopes": false,
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "Console": {
+ "IncludeScopes": false,
+ "LogLevel": {
+ "Default": "Warning",
+ "Microsoft.Hosting.Lifetime": "Debug"
+ }
+ },
+ "Log4Net": {
+ "Name": "Blog.Core"
+ }
},
- "Debug": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Warning"
- }
+ "AllowedHosts": "*",
+ "Redis": {
+ "ConnectionString": "127.0.0.1:6319,password=admin"
},
- "Console": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Warning",
- "Microsoft.Hosting.Lifetime": "Debug"
- }
+ "RabbitMQ": {
+ "Enabled": false,
+ "Connection": "118.25.251.13",
+ "UserName": "",
+ "Password": "!",
+ "RetryCount": 3
},
- "Log4Net": {
- "Name": "Blog.Core"
- }
- },
- "AllowedHosts": "*",
- "Redis": {
- "ConnectionString": "127.0.0.1:6319,password=admin"
- },
- "RabbitMQ": {
- "Enabled": false,
- "Connection": "118.25.251.13",
- "UserName": "",
- "Password": "!",
- "RetryCount": 3
- },
- "Kafka": {
- "Enabled": false,
- "Servers": "localhost:9092",
- "Topic": "blog",
- "GroupId": "blog-consumer",
- "NumPartitions": 3 //主题分区数量
- },
- "EventBus": {
- "Enabled": false,
- "SubscriptionClientName": "Blog.Core"
- },
- "AppSettings": {
- "RedisCachingAOP": {
- "Enabled": false
- },
- "MemoryCachingAOP": {
- "Enabled": true
- },
- "LogAOP": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- }
+ "Kafka": {
+ "Enabled": false,
+ "Servers": "localhost:9092",
+ "Topic": "blog",
+ "GroupId": "blog-consumer",
+ "NumPartitions": 3 //主题分区数量
},
- "TranAOP": {
- "Enabled": true
+ "EventBus": {
+ "Enabled": false,
+ "SubscriptionClientName": "Blog.Core"
},
- "SqlAOP": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": false
- },
- "LogToConsole": {
- "Enabled": true
- }
+ "AppSettings": {
+ "RedisCachingAOP": {
+ "Enabled": false
+ },
+ "MemoryCachingAOP": {
+ "Enabled": true
+ },
+ "LogAOP": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ }
+ },
+ "TranAOP": {
+ "Enabled": true
+ },
+ "SqlAOP": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": false
+ },
+ "LogToConsole": {
+ "Enabled": true
+ }
+ },
+ "Date": "2018-08-28",
+ "SeedDBEnabled": true, //只生成表结构
+ "SeedDBDataEnabled": true, //生成表,并初始化数据
+ "Author": "Blog.Core",
+ "SvcName": "", // /svc/blog
+ "UseLoadTest": false
},
- "Date": "2018-08-28",
- "SeedDBEnabled": true, //只生成表结构
- "SeedDBDataEnabled": true, //生成表,并初始化数据
- "Author": "Blog.Core",
- "SvcName": "", // /svc/blog
- "UseLoadTest": false
- },
- // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
- // *** 单库操作,把 MutiDBEnabled 设为false ***;
- // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
- // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
+ // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
+ // *** 单库操作,把 MutiDBEnabled 设为false ***;
+ // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
+ // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
- "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
- "MutiDBEnabled": false, //是否开启多库模式
- "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
- "DBS": [
- /*
+ "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
+ "MutiDBEnabled": false, //是否开启多库模式
+ "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
+ "DBS": [
+ /*
对应下边的 DBType
MySql = 0,
SqlServer = 1,
@@ -102,225 +102,225 @@
Dm = 5,//达梦
Kdbndp = 6,//人大金仓
*/
- {
- "ConnId": "WMBLOG_SQLITE",
- "DBType": 2,
- "Enabled": true,
- "HitRate": 50, // 值越大,优先级越高
- "Connection": "WMBlog.db" //sqlite只写数据库名就行
- },
- {
- "ConnId": "WMBLOG_MSSQL_1",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 40,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MSSQL_2",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 30,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MYSQL",
- "DBType": 0,
- "Enabled": false,
- "HitRate": 20,
- "Connection": "server=.;Database=ddd;Uid=root;Pwd=123456;Port=10060;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_MYSQL_2",
- "DBType": 0,
- "Enabled": true,
- "HitRate": 20,
- "Connection": "server=localhost;Database=blogcore001;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_ORACLE",
- "DBType": 3,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
- },
- {
- "ConnId": "WMBLOG_DM",
- "DBType": 5,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
- },
- {
- "ConnId": "WMBLOG_KDBNDP",
- "DBType": 6,
- "Enabled": true,
- "HitRate": 10,
- "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
- }
- ],
- "Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
- "Issuer": "Blog.Core",
- "Audience": "wr"
- },
- "Mongo": {
- "ConnectionString": "mongodb://nosql.data",
- "Database": "BlogCoreDb"
- },
- "Startup": {
- "Domain": "http://localhost:9291",
- "Cors": {
- "PolicyName": "CorsIpAccess", //策略名称
- "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
- // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
- // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
- "IPs": "http://127.0.0.1:2364,http://localhost:2364,http://127.0.0.1:6688,http://localhost:6688"
- },
- "AppConfigAlert": {
- "Enabled": true
- },
- "ApiName": "Blog.Core",
- "IdentityServer4": {
- "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
- "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
- "ApiName": "blog.core.api" // 资源服务器
- },
- "Authing": {
- "Enabled": false,
- "Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
- "Audience": "63d51c4205c2849803be5178",
- "JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
- },
- "RedisMq": {
- "Enabled": false //redis 消息队列
+ {
+ "ConnId": "WMBLOG_SQLITE",
+ "DBType": 2,
+ "Enabled": true,
+ "HitRate": 50, // 值越大,优先级越高
+ "Connection": "WMBlog.db" //sqlite只写数据库名就行
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_1",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 40,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MSSQL_2",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 30,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=localhost;Database=blog;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL_2",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=localhost;Database=blogcore001;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_ORACLE",
+ "DBType": 3,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
+ },
+ {
+ "ConnId": "WMBLOG_DM",
+ "DBType": 5,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
+ },
+ {
+ "ConnId": "WMBLOG_KDBNDP",
+ "DBType": 6,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
+ }
+ ],
+ "Audience": {
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
+ "Issuer": "Blog.Core",
+ "Audience": "wr"
},
- "MiniProfiler": {
- "Enabled": false //性能分析开启
+ "Mongo": {
+ "ConnectionString": "mongodb://nosql.data",
+ "Database": "BlogCoreDb"
},
- "Nacos": {
- "Enabled": false //Nacos注册中心
- }
- },
- "Middleware": {
- "RequestResponseLog": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- }
- },
- "IPLog": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- }
+ "Startup": {
+ "Domain": "http://localhost:9291",
+ "Cors": {
+ "PolicyName": "CorsIpAccess", //策略名称
+ "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
+ // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
+ // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
+ "IPs": "http://127.0.0.1:2364,http://localhost:2364,http://127.0.0.1:6688,http://localhost:6688"
+ },
+ "AppConfigAlert": {
+ "Enabled": true
+ },
+ "ApiName": "Blog.Core",
+ "IdentityServer4": {
+ "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
+ "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
+ "ApiName": "blog.core.api" // 资源服务器
+ },
+ "Authing": {
+ "Enabled": false,
+ "Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
+ "Audience": "63d51c4205c2849803be5178",
+ "JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
+ },
+ "RedisMq": {
+ "Enabled": false //redis 消息队列
+ },
+ "MiniProfiler": {
+ "Enabled": false //性能分析开启
+ },
+ "Nacos": {
+ "Enabled": false //Nacos注册中心
+ }
},
- "RecordAccessLogs": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- },
- "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
+ "Middleware": {
+ "RequestResponseLog": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ }
+ },
+ "IPLog": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ }
+ },
+ "RecordAccessLogs": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ },
+ "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
+ },
+ "SignalR": {
+ "Enabled": false
+ },
+ "SignalRSendLog": {
+ "Enabled": false
+ },
+ "QuartzNetJob": {
+ "Enabled": true
+ },
+ "Consul": {
+ "Enabled": false
+ },
+ "IpRateLimit": {
+ "Enabled": true
+ }
},
- "SignalR": {
- "Enabled": false
+ "IpRateLimiting": {
+ "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
+ "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
+ "RealIpHeader": "X-Real-IP",
+ "ClientIdHeader": "X-ClientId",
+ "IpWhitelist": [], //白名单
+ "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
+ "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
+ "QuotaExceededResponse": {
+ "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
+ "ContentType": "application/json",
+ "StatusCode": 429
+ },
+ "HttpStatusCode": 429, //返回状态码
+ "GeneralRules": [ //api规则,结尾一定要带*
+ {
+ "Endpoint": "*:/api/blog*",
+ "Period": "1m",
+ "Limit": 20
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1s",
+ "Limit": 3
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1m",
+ "Limit": 30
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "12h",
+ "Limit": 500
+ }
+ ]
+
},
- "SignalRSendLog": {
- "Enabled": false
+ "ConsulSetting": {
+ "ServiceName": "BlogCoreService",
+ "ServiceIP": "localhost",
+ "ServicePort": "9291",
+ "ServiceHealthCheck": "/healthcheck",
+ "ConsulAddress": "http://localhost:8500"
},
- "QuartzNetJob": {
- "Enabled": true
+ "PayInfo": { //建行聚合支付信息
+ "MERCHANTID": "", //商户号
+ "POSID": "", //柜台号
+ "BRANCHID": "", //分行号
+ "pubKey": "", //公钥
+ "USER_ID": "", //操作员号
+ "PASSWORD": "", //密码
+ "OutAddress": "http://127.0.0.1:12345" //外联地址
},
- "Consul": {
- "Enabled": false
+ "nacos": {
+ "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
+ "DefaultTimeOut": 15000, // 默认超时时间
+ "Namespace": "public", // 命名空间
+ "ListenInterval": 10000, // 监听的频率
+ "ServiceName": "blog.Core.Api", // 服务名
+ "Port": "9291", // 服务端口号
+ "RegisterEnabled": true // 是否直接注册nacos
},
- "IpRateLimit": {
- "Enabled": true
+ "LogFiedOutPutConfigs": {
+ "tcpAddressHost": "", // 输出elk的tcp连接地址
+ "tcpAddressPort": 0, // 输出elk的tcp端口号
+ "ConfigsInfo": [ // 配置的输出elk节点内容 常用语动态标识
+ {
+ "FiedName": "applicationName",
+ "FiedValue": "Blog.Core.Api"
+ }
+ ]
}
- },
- "IpRateLimiting": {
- "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
- "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
- "RealIpHeader": "X-Real-IP",
- "ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //白名单
- "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
- "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
- "QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
- "ContentType": "application/json",
- "StatusCode": 429
- },
- "HttpStatusCode": 429, //返回状态码
- "GeneralRules": [ //api规则,结尾一定要带*
- {
- "Endpoint": "*:/api/blog*",
- "Period": "1m",
- "Limit": 20
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1s",
- "Limit": 3
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1m",
- "Limit": 30
- },
- {
- "Endpoint": "*/api/*",
- "Period": "12h",
- "Limit": 500
- }
- ]
-
- },
- "ConsulSetting": {
- "ServiceName": "BlogCoreService",
- "ServiceIP": "localhost",
- "ServicePort": "9291",
- "ServiceHealthCheck": "/healthcheck",
- "ConsulAddress": "http://localhost:8500"
- },
- "PayInfo": { //建行聚合支付信息
- "MERCHANTID": "", //商户号
- "POSID": "", //柜台号
- "BRANCHID": "", //分行号
- "pubKey": "", //公钥
- "USER_ID": "", //操作员号
- "PASSWORD": "", //密码
- "OutAddress": "http://127.0.0.1:12345" //外联地址
- },
- "nacos": {
- "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
- "DefaultTimeOut": 15000, // 默认超时时间
- "Namespace": "public", // 命名空间
- "ListenInterval": 10000, // 监听的频率
- "ServiceName": "blog.Core.Api", // 服务名
- "Port": "9291", // 服务端口号
- "RegisterEnabled": true // 是否直接注册nacos
- },
- "LogFiedOutPutConfigs": {
- "tcpAddressHost": "", // 输出elk的tcp连接地址
- "tcpAddressPort": 0, // 输出elk的tcp端口号
- "ConfigsInfo": [ // 配置的输出elk节点内容 常用语动态标识
- {
- "FiedName": "applicationName",
- "FiedValue": "Blog.Core.Api"
- }
- ]
- }
}
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv
index 2bb130a1..76c55a22 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Modules.tsv
@@ -1535,5 +1535,49 @@
"ModifyBy": null,
"ModifyTime": "\/Date(1546272000000+0800)\/",
"Id": 72
+ },
+ {
+ "IsDeleted": 0,
+ "ParentId": null,
+ "Name": "任务日志查询",
+ "LinkUrl": "\/api\/TasksQz\/GetTaskLogs",
+ "Area": null,
+ "Controller": null,
+ "Action": null,
+ "Icon": null,
+ "Code": null,
+ "OrderSort": 0,
+ "Description": null,
+ "IsMenu": 0,
+ "Enabled": 1,
+ "CreateId": 23,
+ "CreateBy": "后台总管理员",
+ "CreateTime": "\/Date(1546272000000+0800)\/",
+ "ModifyId": null,
+ "ModifyBy": null,
+ "ModifyTime": "\/Date(1546272000000+0800)\/",
+ "Id": 73
+ },
+ {
+ "IsDeleted": 0,
+ "ParentId": null,
+ "Name": "任务概况",
+ "LinkUrl": "\/api\/TasksQz\/GetTaskOverview",
+ "Area": null,
+ "Controller": null,
+ "Action": null,
+ "Icon": null,
+ "Code": null,
+ "OrderSort": 0,
+ "Description": null,
+ "IsMenu": 0,
+ "Enabled": 1,
+ "CreateId": 23,
+ "CreateBy": "后台总管理员",
+ "CreateTime": "\/Date(1546272000000+0800)\/",
+ "ModifyId": null,
+ "ModifyBy": null,
+ "ModifyTime": "\/Date(1546272000000+0800)\/",
+ "Id": 74
}
]
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
index 52493a12..d1a5c3f8 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
@@ -2571,5 +2571,47 @@
"IsDeleted": 0,
"Id": 122,
"IsHide": 0
+ },
+ {
+ "Code": " ",
+ "Name": "日志查询",
+ "IsButton": 1,
+ "Pid": 76,
+ "Mid": 73,
+ "OrderSort": 0,
+ "Icon": null,
+ "Description": null,
+ "Enabled": 1,
+ "CreateId": 23,
+ "Func": "handleLog",
+ "CreateBy": "后台总管理员",
+ "CreateTime": "\/Date(1546272000000+0800)\/",
+ "ModifyId": null,
+ "ModifyBy": null,
+ "ModifyTime": "\/Date(1546272000000+0800)\/",
+ "IsDeleted": 0,
+ "Id": 123,
+ "IsHide": 0
+ },
+ {
+ "Code": " ",
+ "Name": "任务概况",
+ "IsButton": 1,
+ "Pid": 76,
+ "Mid": 74,
+ "OrderSort": 0,
+ "Icon": null,
+ "Description": null,
+ "Enabled": 1,
+ "CreateId": 23,
+ "Func": "handleOverview",
+ "CreateBy": "后台总管理员",
+ "CreateTime": "\/Date(1546272000000+0800)\/",
+ "ModifyId": null,
+ "ModifyBy": null,
+ "ModifyTime": "\/Date(1546272000000+0800)\/",
+ "IsDeleted": 0,
+ "Id": 124,
+ "IsHide": 0
}
]
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 36bf184c..7b594109 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -313,6 +313,19 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
#endregion
+ #region TasksLog
+
+ if (!await myContext.Db.Queryable().AnyAsync())
+ {
+ Console.WriteLine("Table:TasksLog created success!");
+ }
+ else
+ {
+ Console.WriteLine("Table:TasksLog already exists...");
+ }
+
+ #endregion
+
#region Department
if (!await myContext.Db.Queryable().AnyAsync())
diff --git a/Blog.Core.IServices/ITasksLogServices.cs b/Blog.Core.IServices/ITasksLogServices.cs
new file mode 100644
index 00000000..fb15c8dd
--- /dev/null
+++ b/Blog.Core.IServices/ITasksLogServices.cs
@@ -0,0 +1,19 @@
+
+using System;
+using System.Threading.Tasks;
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+
+namespace Blog.Core.IServices
+{
+ ///
+ /// ITasksLogServices
+ ///
+ public interface ITasksLogServices :IBaseServices
+ {
+ public Task> GetTaskLogs(int jobId, int page, int intPageSize,DateTime? runTime,DateTime? endTime);
+ public Task GetTaskOverview(int jobId, DateTime? runTime, DateTime? endTime, string type);
+ }
+}
+
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/TasksLog.cs b/Blog.Core.Model/Models/TasksLog.cs
new file mode 100644
index 00000000..b4317c95
--- /dev/null
+++ b/Blog.Core.Model/Models/TasksLog.cs
@@ -0,0 +1,87 @@
+using SqlSugar;
+using System;
+
+namespace Blog.Core.Model.Models
+{
+ ///
+ /// 任务日志表
+ ///
+ public class TasksLog : RootEntityTkey
+ {
+ ///
+ /// 任务ID
+ ///
+ public int JobId { get; set; }
+ ///
+ /// 任务耗时
+ ///
+ public double TotalTime { get; set; }
+ ///
+ /// 执行结果(0-失败 1-成功)
+ ///
+ public bool RunResult { get; set; }
+ ///
+ /// 运行时间
+ ///
+ public DateTime RunTime { get; set; }
+ ///
+ /// 结束时间
+ ///
+ public DateTime EndTime { get; set; }
+ ///
+ /// 执行参数
+ ///
+ [SugarColumn(Length = 500, IsNullable = true)]
+ public string RunPars { get; set; }
+ ///
+ /// 异常信息
+ ///
+ [SugarColumn(Length = 500, IsNullable = true)]
+ public string ErrMessage { get; set; }
+ ///
+ /// 异常堆栈
+ ///
+ [SugarColumn(Length = 2000, IsNullable = true)]
+ public string ErrStackTrace { get; set; }
+ ///
+ /// 创建ID
+ ///
+ [SugarColumn(IsNullable = true)]
+ public int? CreateId { get; set; }
+ ///
+ /// 创建者
+ ///
+ [SugarColumn(Length = 50, IsNullable = true)]
+ public string CreateBy { get; set; }
+ ///
+ /// 创建时间
+ ///
+ [SugarColumn(IsNullable = true)]
+ public DateTime CreateTime { get; set; } = DateTime.Now;
+ ///
+ /// 修改ID
+ ///
+ [SugarColumn(IsNullable = true)]
+ public int? ModifyId { get; set; }
+ ///
+ /// 修改者
+ ///
+ [SugarColumn(Length = 100, IsNullable = true)]
+ public string ModifyBy { get; set; }
+ ///
+ /// 修改时间
+ ///
+ [SugarColumn(IsNullable = true)]
+ public DateTime? ModifyTime { get; set; } = DateTime.Now;
+ ///
+ /// 任务名称
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public string Name { get; set; }
+ ///
+ /// 任务分组
+ ///
+ [SugarColumn(IsIgnore = true)]
+ public string JobGroup { get; set; }
+ }
+}
diff --git a/Blog.Core.Model/Models/TasksQz.cs b/Blog.Core.Model/Models/TasksQz.cs
index 5c812f79..1c07b60e 100644
--- a/Blog.Core.Model/Models/TasksQz.cs
+++ b/Blog.Core.Model/Models/TasksQz.cs
@@ -65,6 +65,10 @@ public class TasksQz : RootEntityTkey
///
public int CycleRunTimes { get; set; }
///
+ /// 已循环次数
+ ///
+ public int CycleHasRunTimes { get; set; }
+ ///
/// 是否启动
///
public bool IsStart { get; set; } = false;
diff --git a/Blog.Core.Services/TasksLogServices.cs b/Blog.Core.Services/TasksLogServices.cs
new file mode 100644
index 00000000..eac9a739
--- /dev/null
+++ b/Blog.Core.Services/TasksLogServices.cs
@@ -0,0 +1,133 @@
+using System.Linq.Expressions;
+using System;
+using System.Threading.Tasks;
+using Blog.Core.IServices;
+using Blog.Core.Model.Models;
+using Blog.Core.Services.BASE;
+using Blog.Core.Common.Extensions;
+using System.Drawing.Printing;
+using SqlSugar;
+using Blog.Core.Model;
+using System.Collections.Generic;
+using System.Linq;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
+
+namespace Blog.Core.Services
+{
+ public partial class TasksLogServices : BaseServices, ITasksLogServices
+ {
+ public async Task> GetTaskLogs(int jobId, int page, int intPageSize, DateTime? runTime, DateTime? endTime)
+ {
+ RefAsync totalCount = 0;
+ Expression> whereExpression = log => true;
+ if (jobId > 0) whereExpression = whereExpression.And(log => log.JobId == jobId);
+ var data = await this.Db.Queryable()
+ .LeftJoin((log, qz) => log.JobId == qz.Id)
+ .OrderByDescending((log) => log.RunTime)
+ .WhereIF(jobId > 0, (log) => log.JobId == jobId)
+ .WhereIF(runTime != null, (log) => log.RunTime >= runTime.Value)
+ .WhereIF(endTime != null, (log) => log.RunTime <= endTime.Value)
+ .Select((log, qz) => new TasksLog
+ {
+ RunPars = log.RunPars,
+ RunResult = log.RunResult,
+ RunTime = log.RunTime,
+ EndTime = log.EndTime,
+ ErrMessage = log.ErrMessage,
+ ErrStackTrace = log.ErrStackTrace,
+ TotalTime = log.TotalTime,
+ Name = qz.Name,
+ JobGroup = qz.JobGroup
+
+ })
+ .ToPageListAsync(page, intPageSize, totalCount);
+ return new PageModel(page, totalCount, intPageSize, data);
+ }
+ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime? endTime,string type)
+ {
+
+ //按年
+ if ("year".Equals(type))
+ {
+
+ var days = endTime.Value.Year - runTime.Value.Year;
+ var dayArray = new List();
+ while (days >= 0)
+ {
+ dayArray.Add(new DateTime(runTime.Value.Year + days,1,1));
+ days--;
+ }
+ var queryableLeft = this.Db.Reportable(dayArray).ToQueryable();
+ var queryableRight = this.Db.Queryable().Where((x) => x.RunTime.Year >= runTime.Value.Year && x.RunTime.Year <= endTime.Value.Year); ; ; //声名表
+
+ var list = this.Db.Queryable(queryableLeft, queryableRight, JoinType.Left,
+ (x1, x2) => x1.ColumnName.Year == x2.RunTime.Year)
+ .GroupBy((x1, x2) => x1.ColumnName)
+ .Select((x1, x2) => new
+ {
+ 执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
+ date = x1.ColumnName.Year.ToString()+"年"
+ }).ToList().OrderBy(t => t.date);
+ return list;
+ }else if ("month".Equals(type))
+ {
+ //按月
+ var queryableLeft = this.Db.Reportable(ReportableDateType.MonthsInLast1years).ToQueryable(); //生成月份 //ReportableDateType.MonthsInLast1yea 表式近一年月份 并且queryable之后还能在where过滤
+ var queryableRight = this.Db.Queryable().Where((x) => x.RunTime.Year == runTime.Value.Year); //声名表
+
+ //月份和表JOIN
+ var list = queryableLeft
+ .LeftJoin(queryableRight, (x1, x2) => x2.RunTime.ToString("MM月") == x1.ColumnName.ToString("MM月"))
+
+ .GroupBy((x1, x2) => x1.ColumnName)
+ .Select((x1, x2) => new
+ {
+ //null的数据要为0所以不能用count
+ 执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
+ date = x1.ColumnName.ToString("MM月")
+ }
+ ).ToList().OrderBy(t => t.date);
+ return list;
+ }else if ("day".Equals(type))
+ {
+ //按日
+ var time = runTime.Value;
+ var days = DateTime.DaysInMonth(time.Year, time.Month);
+ var dayArray = Enumerable.Range(1, days).Select(it => Convert.ToDateTime(time.ToString("yyyy-MM-" + it))).ToList();//转成时间数组
+ var queryableLeft = this.Db.Reportable(dayArray).ToQueryable();
+ var star = Convert.ToDateTime(runTime.Value.ToString("yyyy-MM-01 00:00:00"));
+ var end = Convert.ToDateTime(runTime.Value.ToString($"yyyy-MM-{days} 23:59:59"));
+ var queryableRight = this.Db.Queryable().Where((x) => x.RunTime >= star && x.RunTime <= end); ;; //声名表
+
+ var list = this.Db.Queryable(queryableLeft, queryableRight, JoinType.Left,
+ (x1, x2) => x1.ColumnName.Date == x2.RunTime.Date)
+ .GroupBy((x1, x2) => x1.ColumnName)
+ .Select((x1, x2) => new
+ {
+ 执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
+ date = x1.ColumnName.Day
+ }).ToList().OrderBy(t => t.date);
+ return list;
+ }else if ("hour".Equals(type))
+ {
+ //按小时
+ var time = runTime.Value;
+ var days = 24;
+ var dayArray = Enumerable.Range(0, days).Select(it => Convert.ToDateTime(time.ToString($"yyyy-MM-dd {it.ToString().PadLeft(2, '0')}:00:00"))).ToList();//转成时间数组
+ var queryableLeft = this.Db.Reportable(dayArray).ToQueryable();
+ var queryableRight = this.Db.Queryable().Where((x) => x.RunTime >= runTime.Value.Date && x.RunTime<= runTime.Value.Date.AddDays(1).AddMilliseconds(-1)); //声名表
+
+ var list = this.Db.Queryable(queryableLeft, queryableRight, JoinType.Left,
+ (x1, x2) => x1.ColumnName.Hour == x2.RunTime.Hour)
+ .GroupBy((x1, x2) => x1.ColumnName)
+ .Select((x1, x2) => new
+ {
+ 执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
+ date = x1.ColumnName.Hour
+ }).ToList().OrderBy(t => t.date);
+ return list;
+ }
+ return null;
+ }
+ }
+}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
index 4a71fbf5..b4486dfc 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/JobBase.cs
@@ -1,5 +1,6 @@
using Blog.Core.Common.Helper;
using Blog.Core.IServices;
+using Blog.Core.Model.Models;
using Quartz;
using System;
using System.Diagnostics;
@@ -10,6 +11,12 @@ namespace Blog.Core.Tasks
public class JobBase
{
public ITasksQzServices _tasksQzServices;
+ public ITasksLogServices _tasksLogServices;
+ public JobBase(ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
+ {
+ _tasksQzServices = tasksQzServices;
+ _tasksLogServices = tasksLogServices;
+ }
///
/// 执行指定任务
///
@@ -17,40 +24,50 @@ public class JobBase
///
public async Task ExecuteJob(IJobExecutionContext context, Func func)
{
- //记录Job时间
- Stopwatch stopwatch = new Stopwatch();
+ //记录Job
+ TasksLog tasksLog = new TasksLog();
//JOBID
int jobid = context.JobDetail.Key.Name.ObjToInt();
//JOB组名
string groupName = context.JobDetail.Key.Group;
//日志
- string jobHistory = $"【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行开始】【Id:{jobid},组别:{groupName}】";
- //耗时
- double taskSeconds = 0;
+ tasksLog.JobId = jobid;
+ tasksLog.RunTime = DateTime.Now;
+ string jobHistory = $"【{tasksLog.RunTime.ToString("yyyy-MM-dd HH:mm:ss")}】【执行开始】【Id:{jobid},组别:{groupName}】";
try
{
- stopwatch.Start();
await func();//执行任务
- stopwatch.Stop();
- jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行成功】";
+ tasksLog.EndTime = DateTime.Now;
+ tasksLog.RunResult = true;
+ jobHistory += $",【{tasksLog.EndTime.ToString("yyyy-MM-dd HH:mm:ss")}】【执行成功】";
+
+ JobDataMap jobPars = context.JobDetail.JobDataMap;
+ tasksLog.RunPars = jobPars.GetString("JobParam");
}
catch (Exception ex)
{
- JobExecutionException e2 = new JobExecutionException(ex);
+ tasksLog.EndTime = DateTime.Now;
+ tasksLog.RunResult = false;
+ //JobExecutionException e2 = new JobExecutionException(ex);
//true 是立即重新执行任务
- e2.RefireImmediately = true;
- jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行失败:{ex.Message}】";
+ //e2.RefireImmediately = true;
+ tasksLog.ErrMessage = ex.Message;
+ tasksLog.ErrStackTrace = ex.StackTrace;
+ jobHistory += $",【{tasksLog.EndTime.ToString("yyyy-MM-dd HH:mm:ss")}】【执行失败:{ex.Message}】";
}
finally
{
- taskSeconds = Math.Round(stopwatch.Elapsed.TotalSeconds, 3);
- jobHistory += $",【{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}】【执行结束】(耗时:{taskSeconds}秒)";
+ tasksLog.TotalTime = Math.Round((tasksLog.EndTime - tasksLog.RunTime).TotalSeconds,3);
+ jobHistory += $"(耗时:{tasksLog.TotalTime}秒)";
if (_tasksQzServices != null)
{
var model = await _tasksQzServices.QueryById(jobid);
if (model != null)
{
+ if(_tasksLogServices != null) await _tasksLogServices.Add(tasksLog);
model.RunTimes += 1;
+ if (model.TriggerType == 0) model.CycleHasRunTimes += 1;
+ if (model.TriggerType == 0 && model.CycleRunTimes != 0 && model.CycleHasRunTimes >= model.CycleRunTimes) model.IsStart = false;//循环完善,当循环任务完成后,停止该任务,防止下次启动再次执行
var separator = "
";
// 这里注意数据库字段的长度问题,超过限制,会造成数据库remark不更新问题。
model.Remark =
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index 743180c3..1dcc57ed 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -21,7 +21,8 @@ public class Job_AccessTrendLog_Quartz : JobBase, IJob
private readonly IAccessTrendLogServices _accessTrendLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_AccessTrendLog_Quartz(IAccessTrendLogServices accessTrendLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
+ public Job_AccessTrendLog_Quartz(IAccessTrendLogServices accessTrendLogServices, IWebHostEnvironment environment, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
+ : base(tasksQzServices, tasksLogServices)
{
_accessTrendLogServices = accessTrendLogServices;
_environment = environment;
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
index 41310533..f116fe05 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_Blogs_Quartz.cs
@@ -12,10 +12,10 @@ public class Job_Blogs_Quartz : JobBase, IJob
{
private readonly IBlogArticleServices _blogArticleServices;
- public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices)
+ public Job_Blogs_Quartz(IBlogArticleServices blogArticleServices, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
+ : base(tasksQzServices, tasksLogServices)
{
_blogArticleServices = blogArticleServices;
- _tasksQzServices = tasksQzServices;
}
public async Task Execute(IJobExecutionContext context)
{
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index 8e9b3847..18c4c298 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -20,11 +20,11 @@ public class Job_OperateLog_Quartz : JobBase, IJob
private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, ITasksQzServices tasksQzServices, IWebHostEnvironment environment)
+ public Job_OperateLog_Quartz(IOperateLogServices operateLogServices,IWebHostEnvironment environment, ITasksQzServices tasksQzServices,ITasksLogServices tasksLogServices)
+ :base(tasksQzServices, tasksLogServices)
{
_operateLogServices = operateLogServices;
- _environment = environment;
- _tasksQzServices = tasksQzServices;
+ _environment = environment;
}
public async Task Execute(IJobExecutionContext context)
{
diff --git a/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs b/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
index 8c21115c..474a2a9a 100644
--- a/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
+++ b/Blog.Core.Tasks/QuartzNet/SchedulerCenterServer.cs
@@ -125,6 +125,12 @@ public async Task> AddScheduleJobAsync(TasksQz tasksQz)
result.msg = $"该任务计划已经在执行:【{tasksQz.Name}】,请勿重复启动!";
return result;
}
+ if(tasksQz.TriggerType == 0 && tasksQz.CycleRunTimes != 0 && tasksQz.CycleHasRunTimes>=tasksQz.CycleRunTimes)
+ {
+ result.success = false;
+ result.msg = $"该任务计划已完成:【{tasksQz.Name}】,无需重复启动,如需启动请修改已循环次数再提交";
+ return result;
+ }
#region 设置开始时间和结束时间
if (tasksQz.BeginTime == null)
From 2d8d99e8d3a37084d0fb52c036ee4810d6014bce Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 4 Mar 2023 00:12:57 +0000
Subject: [PATCH 037/190] Bump MongoDB.Driver from 2.17.1 to 2.19.0 in
/Blog.Core.Repository
Bumps [MongoDB.Driver](https://github.com/mongodb/mongo-csharp-driver) from 2.17.1 to 2.19.0.
- [Release notes](https://github.com/mongodb/mongo-csharp-driver/releases)
- [Commits](https://github.com/mongodb/mongo-csharp-driver/compare/v2.17.1...v2.19.0)
---
updated-dependencies:
- dependency-name: MongoDB.Driver
dependency-type: direct:production
...
Signed-off-by: dependabot[bot]
---
Blog.Core.Repository/Blog.Core.Repository.csproj | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Blog.Core.Repository/Blog.Core.Repository.csproj b/Blog.Core.Repository/Blog.Core.Repository.csproj
index 5c9764b0..19fb6d4c 100644
--- a/Blog.Core.Repository/Blog.Core.Repository.csproj
+++ b/Blog.Core.Repository/Blog.Core.Repository.csproj
@@ -8,7 +8,7 @@
-
+
From ff238ed1e71b396fb54c03377b774064d6404a21 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Tue, 7 Mar 2023 21:21:01 +0800
Subject: [PATCH 038/190] Update README.md
---
README.md | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md
index 9b88b0a0..29d427ec 100644
--- a/README.md
+++ b/README.md
@@ -235,9 +235,9 @@ Contributions of any kind are welcome!
## 售后服务与支持
-鼓励作者,简单打赏,入微信群,随时随地解答我框架中(NetCore、Vue、DDD、IdentityServer4等)的疑难杂症。
-注意主要是帮忙解决bug和思路,不会远程授课,但是可以适当发我代码,我帮忙调试,
-打赏的时候,备注自己的微信号,我拉你进群,两天内没回应,QQ私聊我(3143422472);
+鼓励作者,简单打赏~~
+打赏的时候,备注自己的微信号,加个微信,交个朋友,两天内没回应,QQ私聊我(3143422472);
+目前精力有限,主要针对企业级用户答疑,或者购买授权版的个人用户。
[赞赏列表](http://apk.neters.club/.doc/Contribution/)
From 225b86c0dba29bf13d285792425ea5c052dc0ca5 Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Thu, 9 Mar 2023 23:16:34 +0800
Subject: [PATCH 039/190] Update Blog.Core.Repository.csproj
---
Blog.Core.Repository/Blog.Core.Repository.csproj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Repository/Blog.Core.Repository.csproj b/Blog.Core.Repository/Blog.Core.Repository.csproj
index 19fb6d4c..df05250e 100644
--- a/Blog.Core.Repository/Blog.Core.Repository.csproj
+++ b/Blog.Core.Repository/Blog.Core.Repository.csproj
@@ -6,8 +6,8 @@
-
-
+
+
From 192bdbd59e8d42792ca6140e0f16f4d8ad636909 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 11 Mar 2023 10:14:42 +0800
Subject: [PATCH 040/190] Update ValuesController.cs
---
Blog.Core.Api/Controllers/ValuesController.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/Blog.Core.Api/Controllers/ValuesController.cs b/Blog.Core.Api/Controllers/ValuesController.cs
index 52eb0ea1..1347ca16 100644
--- a/Blog.Core.Api/Controllers/ValuesController.cs
+++ b/Blog.Core.Api/Controllers/ValuesController.cs
@@ -298,7 +298,6 @@ public object Post([FromBody] BlogArticle blogArticle, int id)
///
///
[HttpPost]
- [Route("TestPostPara")]
[AllowAnonymous]
public object TestPostPara(string name)
{
From d7190d677cfcf04f05e682deb63e51f9a678bc84 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sat, 11 Mar 2023 11:07:20 +0800
Subject: [PATCH 041/190] feat: :+1: beautiful api
---
Blog.Core.Api/Blog.Core.xml | 6 --
Blog.Core.Api/Controllers/BlogController.cs | 6 +-
.../Controllers/DepartmentController.cs | 7 --
Blog.Core.Api/Controllers/ModuleController.cs | 5 +-
.../Controllers/MonitorController.cs | 7 --
Blog.Core.Api/Controllers/NacosController.cs | 1 -
Blog.Core.Api/Controllers/PayController.cs | 4 +-
Blog.Core.Api/Controllers/RoleController.cs | 3 +-
.../Controllers/TasksQzController.cs | 64 ++++++++-----------
Blog.Core.Api/Controllers/TopicController.cs | 4 +-
.../Controllers/TopicDetailController.cs | 5 +-
.../Controllers/TransactionController.cs | 5 +-
Blog.Core.Api/Controllers/UserController.cs | 7 +-
.../Controllers/UserRoleController.cs | 3 +-
.../Controllers/WeChatCompanyController.cs | 1 -
.../Controllers/WeChatConfigController.cs | 1 -
Blog.Core.Api/Controllers/WeChatController.cs | 5 +-
.../Controllers/WeChatPushLogController.cs | 1 -
.../Controllers/WeChatSubController.cs | 1 -
Blog.Core.Services/TasksLogServices.cs | 30 +++++----
20 files changed, 53 insertions(+), 113 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index af6321da..89cb3213 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -580,18 +580,12 @@
获取任务运行日志
-
-
-
任务概况
-
-
-
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 6525448e..83fad967 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -1,8 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
+using System.Linq.Expressions;
using System.Text.RegularExpressions;
-using System.Threading.Tasks;
using Blog.Core.Common.Helper;
using Blog.Core.IServices;
using Blog.Core.Model;
@@ -11,7 +8,6 @@
using Blog.Core.SwaggerHelper;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
using StackExchange.Profiling;
using static Blog.Core.Extensions.CustomApiVersion;
diff --git a/Blog.Core.Api/Controllers/DepartmentController.cs b/Blog.Core.Api/Controllers/DepartmentController.cs
index 1674883f..bca7bf6d 100644
--- a/Blog.Core.Api/Controllers/DepartmentController.cs
+++ b/Blog.Core.Api/Controllers/DepartmentController.cs
@@ -4,17 +4,10 @@
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
using System.Linq.Expressions;
using System.Text;
-using System.Threading.Tasks;
namespace Blog.Core.Api.Controllers
{
diff --git a/Blog.Core.Api/Controllers/ModuleController.cs b/Blog.Core.Api/Controllers/ModuleController.cs
index 334a8ea4..2da284ba 100644
--- a/Blog.Core.Api/Controllers/ModuleController.cs
+++ b/Blog.Core.Api/Controllers/ModuleController.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using System.Threading.Tasks;
+using System.Linq.Expressions;
using Blog.Core.Common.HttpContextUser;
using Blog.Core.IServices;
using Blog.Core.Model;
diff --git a/Blog.Core.Api/Controllers/MonitorController.cs b/Blog.Core.Api/Controllers/MonitorController.cs
index c0dbed52..77b4e5bf 100644
--- a/Blog.Core.Api/Controllers/MonitorController.cs
+++ b/Blog.Core.Api/Controllers/MonitorController.cs
@@ -6,19 +6,12 @@
using Blog.Core.Model;
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
-using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
using System.Diagnostics;
-using System.IO;
-using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
-using System.Threading.Tasks;
using Blog.Core.Extensions.Middlewares;
namespace Blog.Core.Controllers
diff --git a/Blog.Core.Api/Controllers/NacosController.cs b/Blog.Core.Api/Controllers/NacosController.cs
index a8701b39..e5223851 100644
--- a/Blog.Core.Api/Controllers/NacosController.cs
+++ b/Blog.Core.Api/Controllers/NacosController.cs
@@ -4,7 +4,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Nacos.V2;
-using System.Threading.Tasks;
namespace Blog.Core.Api.Controllers
{
diff --git a/Blog.Core.Api/Controllers/PayController.cs b/Blog.Core.Api/Controllers/PayController.cs
index 0cbe0541..6c05c249 100644
--- a/Blog.Core.Api/Controllers/PayController.cs
+++ b/Blog.Core.Api/Controllers/PayController.cs
@@ -1,10 +1,8 @@
-using System.Threading.Tasks;
-using Blog.Core.IServices;
+using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
namespace Blog.Core.Controllers
{
diff --git a/Blog.Core.Api/Controllers/RoleController.cs b/Blog.Core.Api/Controllers/RoleController.cs
index 36df73a4..c96502c8 100644
--- a/Blog.Core.Api/Controllers/RoleController.cs
+++ b/Blog.Core.Api/Controllers/RoleController.cs
@@ -1,5 +1,4 @@
-using System.Threading.Tasks;
-using Blog.Core.Common.HttpContextUser;
+using Blog.Core.Common.HttpContextUser;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Api/Controllers/TasksQzController.cs b/Blog.Core.Api/Controllers/TasksQzController.cs
index e5c866c3..ca9d37bc 100644
--- a/Blog.Core.Api/Controllers/TasksQzController.cs
+++ b/Blog.Core.Api/Controllers/TasksQzController.cs
@@ -1,17 +1,10 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Linq.Expressions;
+using System.Linq.Expressions;
using System.Reflection;
-using System.Threading.Tasks;
-using Blog.Core.Common.Extensions;
-using Blog.Core.Common.WebApiClients.HttpApis;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Blog.Core.Model.ViewModels;
using Blog.Core.Repository.UnitOfWorks;
-using Blog.Core.Services;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -29,10 +22,10 @@ public class TasksQzController : ControllerBase
private readonly ISchedulerCenter _schedulerCenter;
private readonly IUnitOfWorkManage _unitOfWorkManage;
- public TasksQzController(ITasksQzServices tasksQzServices, ISchedulerCenter schedulerCenter, IUnitOfWorkManage unitOfWorkManage,ITasksLogServices tasksLogServices)
+ public TasksQzController(ITasksQzServices tasksQzServices, ISchedulerCenter schedulerCenter, IUnitOfWorkManage unitOfWorkManage, ITasksLogServices tasksLogServices)
{
_unitOfWorkManage = unitOfWorkManage;
- _tasksQzServices = tasksQzServices;
+ _tasksQzServices = tasksQzServices;
_schedulerCenter = schedulerCenter;
_tasksLogServices = tasksLogServices;
}
@@ -63,7 +56,7 @@ public async Task>> Get(int page = 1, string key
item.Triggers = await _schedulerCenter.GetTaskStaus(item);
}
}
- return MessageModel>.Message(data.dataCount >= 0, "获取成功", data);
+ return MessageModel>.Message(data.dataCount >= 0, "获取成功", data);
}
///
@@ -91,32 +84,33 @@ public async Task> Post([FromBody] TasksQz tasksQz)
var ResuleModel = await _schedulerCenter.AddScheduleJobAsync(tasksQz);
data.success = ResuleModel.success;
if (ResuleModel.success)
- {
+ {
data.msg = $"{data.msg}=>启动成功=>{ResuleModel.msg}";
}
else
- {
+ {
data.msg = $"{data.msg}=>启动失败=>{ResuleModel.msg}";
}
}
}
else
- {
+ {
data.msg = "添加失败";
- }
+ }
}
catch (Exception)
{
throw;
}
finally
- { if(data.success)
+ {
+ if (data.success)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
}
- return data;
+ return data;
}
@@ -140,7 +134,7 @@ public async Task> Put([FromBody] TasksQz tasksQz)
data.msg = "修改成功";
data.response = tasksQz?.Id.ObjToString();
if (tasksQz.IsStart)
- {
+ {
var ResuleModelStop = await _schedulerCenter.StopScheduleJobAsync(tasksQz);
data.msg = $"{data.msg}=>停止:{ResuleModelStop.msg}";
var ResuleModelStar = await _schedulerCenter.AddScheduleJobAsync(tasksQz);
@@ -168,7 +162,7 @@ public async Task> Put([FromBody] TasksQz tasksQz)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
- }
+ }
}
return data;
}
@@ -212,7 +206,7 @@ public async Task> Delete(int jobId)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
- }
+ }
}
else
{
@@ -234,7 +228,7 @@ public async Task> StartJob(int jobId)
var model = await _tasksQzServices.QueryById(jobId);
if (model != null)
{
- _unitOfWorkManage.BeginTran();
+ _unitOfWorkManage.BeginTran();
try
{
model.IsStart = true;
@@ -270,7 +264,7 @@ public async Task> StartJob(int jobId)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
- }
+ }
}
else
{
@@ -326,10 +320,10 @@ public async Task> StopJob(int jobId)
[HttpGet]
public async Task> PauseJob(int jobId)
{
- var data = new MessageModel();
+ var data = new MessageModel();
var model = await _tasksQzServices.QueryById(jobId);
if (model != null)
- {
+ {
_unitOfWorkManage.BeginTran();
try
{
@@ -364,7 +358,7 @@ public async Task> PauseJob(int jobId)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
- }
+ }
}
else
{
@@ -384,7 +378,7 @@ public async Task> ResumeJob(int jobId)
var model = await _tasksQzServices.QueryById(jobId);
if (model != null)
- {
+ {
_unitOfWorkManage.BeginTran();
try
{
@@ -420,7 +414,7 @@ public async Task> ResumeJob(int jobId)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
- }
+ }
}
else
{
@@ -480,7 +474,7 @@ public async Task> ReCovery(int jobId)
_unitOfWorkManage.CommitTran();
else
_unitOfWorkManage.RollbackTran();
- }
+ }
}
else
{
@@ -493,7 +487,7 @@ public async Task> ReCovery(int jobId)
/// 获取任务命名空间
///
///
- [HttpGet]
+ [HttpGet]
public MessageModel> GetTaskNameSpace()
{
var baseType = typeof(IJob);
@@ -506,7 +500,7 @@ public MessageModel> GetTaskNameSpace()
var implementTypes = types.Where(x => x.IsClass).Select(item => new QuartzReflectionViewModel { nameSpace = item.Namespace, nameClass = item.Name, remark = "" }).ToList();
return MessageModel>.Success("获取成功", implementTypes);
}
-
+
///
/// 立即执行任务
///
@@ -531,12 +525,9 @@ public async Task> ExecuteJob(int jobId)
///
/// 获取任务运行日志
///
- ///
- ///
- ///
///
[HttpGet]
- public async Task>> GetTaskLogs(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart =null, DateTime? runTimeEnd = null)
+ public async Task>> GetTaskLogs(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null)
{
var model = await _tasksLogServices.GetTaskLogs(jobId, page, pageSize, runTimeStart, runTimeEnd);
return MessageModel>.Message(model.dataCount >= 0, "获取成功", model);
@@ -544,12 +535,9 @@ public async Task>> GetTaskLogs(int jobId, int
///
/// 任务概况
///
- ///
- ///
- ///
///
[HttpGet]
- public async Task> GetTaskOverview(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null, string type ="month")
+ public async Task> GetTaskOverview(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null, string type = "month")
{
var model = await _tasksLogServices.GetTaskOverview(jobId, runTimeStart, runTimeEnd, type);
return MessageModel.Message(true, "获取成功", model);
diff --git a/Blog.Core.Api/Controllers/TopicController.cs b/Blog.Core.Api/Controllers/TopicController.cs
index 1fe2d4a3..308ad082 100644
--- a/Blog.Core.Api/Controllers/TopicController.cs
+++ b/Blog.Core.Api/Controllers/TopicController.cs
@@ -1,6 +1,4 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Blog.Core.IServices;
+using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Microsoft.AspNetCore.Authorization;
diff --git a/Blog.Core.Api/Controllers/TopicDetailController.cs b/Blog.Core.Api/Controllers/TopicDetailController.cs
index 264fe2df..55af1a75 100644
--- a/Blog.Core.Api/Controllers/TopicDetailController.cs
+++ b/Blog.Core.Api/Controllers/TopicDetailController.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Linq;
-using System.Threading.Tasks;
-using Blog.Core.Common.Helper;
+using Blog.Core.Common.Helper;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Api/Controllers/TransactionController.cs b/Blog.Core.Api/Controllers/TransactionController.cs
index dd6b0384..67ab576e 100644
--- a/Blog.Core.Api/Controllers/TransactionController.cs
+++ b/Blog.Core.Api/Controllers/TransactionController.cs
@@ -1,7 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Blog.Core.IServices;
+using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
using Blog.Core.Repository.UnitOfWorks;
diff --git a/Blog.Core.Api/Controllers/UserController.cs b/Blog.Core.Api/Controllers/UserController.cs
index 6a2a18fa..43f7f610 100644
--- a/Blog.Core.Api/Controllers/UserController.cs
+++ b/Blog.Core.Api/Controllers/UserController.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using AutoMapper;
+using AutoMapper;
using Blog.Core.AuthHelper.OverWrite;
using Blog.Core.Common.Helper;
using Blog.Core.Common.HttpContextUser;
@@ -13,7 +9,6 @@
using Blog.Core.Repository.UnitOfWorks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
namespace Blog.Core.Controllers
{
diff --git a/Blog.Core.Api/Controllers/UserRoleController.cs b/Blog.Core.Api/Controllers/UserRoleController.cs
index d14d6a73..c21ec6f4 100644
--- a/Blog.Core.Api/Controllers/UserRoleController.cs
+++ b/Blog.Core.Api/Controllers/UserRoleController.cs
@@ -1,5 +1,4 @@
-using System.Threading.Tasks;
-using AutoMapper;
+using AutoMapper;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Api/Controllers/WeChatCompanyController.cs b/Blog.Core.Api/Controllers/WeChatCompanyController.cs
index 4fa6eea5..dc12930b 100644
--- a/Blog.Core.Api/Controllers/WeChatCompanyController.cs
+++ b/Blog.Core.Api/Controllers/WeChatCompanyController.cs
@@ -1,4 +1,3 @@
-using System.Threading.Tasks;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Api/Controllers/WeChatConfigController.cs b/Blog.Core.Api/Controllers/WeChatConfigController.cs
index c597cb3f..1f3b705d 100644
--- a/Blog.Core.Api/Controllers/WeChatConfigController.cs
+++ b/Blog.Core.Api/Controllers/WeChatConfigController.cs
@@ -1,4 +1,3 @@
-using System.Threading.Tasks;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Api/Controllers/WeChatController.cs b/Blog.Core.Api/Controllers/WeChatController.cs
index 4c4877f6..9927eb78 100644
--- a/Blog.Core.Api/Controllers/WeChatController.cs
+++ b/Blog.Core.Api/Controllers/WeChatController.cs
@@ -1,11 +1,8 @@
-using System.IO;
-using System.Threading.Tasks;
-using Blog.Core.IServices;
+using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-using Microsoft.Extensions.Logging;
namespace Blog.Core.Controllers
{
diff --git a/Blog.Core.Api/Controllers/WeChatPushLogController.cs b/Blog.Core.Api/Controllers/WeChatPushLogController.cs
index 1fe1603d..af168091 100644
--- a/Blog.Core.Api/Controllers/WeChatPushLogController.cs
+++ b/Blog.Core.Api/Controllers/WeChatPushLogController.cs
@@ -1,4 +1,3 @@
-using System.Threading.Tasks;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Api/Controllers/WeChatSubController.cs b/Blog.Core.Api/Controllers/WeChatSubController.cs
index bd8d1759..94f982d2 100644
--- a/Blog.Core.Api/Controllers/WeChatSubController.cs
+++ b/Blog.Core.Api/Controllers/WeChatSubController.cs
@@ -1,4 +1,3 @@
-using System.Threading.Tasks;
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
diff --git a/Blog.Core.Services/TasksLogServices.cs b/Blog.Core.Services/TasksLogServices.cs
index eac9a739..49393cd4 100644
--- a/Blog.Core.Services/TasksLogServices.cs
+++ b/Blog.Core.Services/TasksLogServices.cs
@@ -5,12 +5,10 @@
using Blog.Core.Model.Models;
using Blog.Core.Services.BASE;
using Blog.Core.Common.Extensions;
-using System.Drawing.Printing;
using SqlSugar;
using Blog.Core.Model;
using System.Collections.Generic;
using System.Linq;
-using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
namespace Blog.Core.Services
{
@@ -43,9 +41,8 @@ public async Task> GetTaskLogs(int jobId, int page, int intP
.ToPageListAsync(page, intPageSize, totalCount);
return new PageModel(page, totalCount, intPageSize, data);
}
- public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime? endTime,string type)
+ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime? endTime, string type)
{
-
//按年
if ("year".Equals(type))
{
@@ -54,7 +51,7 @@ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime
var dayArray = new List();
while (days >= 0)
{
- dayArray.Add(new DateTime(runTime.Value.Year + days,1,1));
+ dayArray.Add(new DateTime(runTime.Value.Year + days, 1, 1));
days--;
}
var queryableLeft = this.Db.Reportable(dayArray).ToQueryable();
@@ -66,10 +63,11 @@ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime
.Select((x1, x2) => new
{
执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
- date = x1.ColumnName.Year.ToString()+"年"
+ date = x1.ColumnName.Year.ToString() + "年"
}).ToList().OrderBy(t => t.date);
return list;
- }else if ("month".Equals(type))
+ }
+ else if ("month".Equals(type))
{
//按月
var queryableLeft = this.Db.Reportable(ReportableDateType.MonthsInLast1years).ToQueryable(); //生成月份 //ReportableDateType.MonthsInLast1yea 表式近一年月份 并且queryable之后还能在where过滤
@@ -78,7 +76,7 @@ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime
//月份和表JOIN
var list = queryableLeft
.LeftJoin(queryableRight, (x1, x2) => x2.RunTime.ToString("MM月") == x1.ColumnName.ToString("MM月"))
-
+
.GroupBy((x1, x2) => x1.ColumnName)
.Select((x1, x2) => new
{
@@ -87,8 +85,10 @@ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime
date = x1.ColumnName.ToString("MM月")
}
).ToList().OrderBy(t => t.date);
+ await Task.CompletedTask;
return list;
- }else if ("day".Equals(type))
+ }
+ else if ("day".Equals(type))
{
//按日
var time = runTime.Value;
@@ -97,7 +97,7 @@ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime
var queryableLeft = this.Db.Reportable(dayArray).ToQueryable();
var star = Convert.ToDateTime(runTime.Value.ToString("yyyy-MM-01 00:00:00"));
var end = Convert.ToDateTime(runTime.Value.ToString($"yyyy-MM-{days} 23:59:59"));
- var queryableRight = this.Db.Queryable().Where((x) => x.RunTime >= star && x.RunTime <= end); ;; //声名表
+ var queryableRight = this.Db.Queryable().Where((x) => x.RunTime >= star && x.RunTime <= end); ; ; //声名表
var list = this.Db.Queryable(queryableLeft, queryableRight, JoinType.Left,
(x1, x2) => x1.ColumnName.Date == x2.RunTime.Date)
@@ -107,26 +107,30 @@ public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime
执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
date = x1.ColumnName.Day
}).ToList().OrderBy(t => t.date);
+ await Task.CompletedTask;
return list;
- }else if ("hour".Equals(type))
+ }
+ else if ("hour".Equals(type))
{
//按小时
var time = runTime.Value;
var days = 24;
var dayArray = Enumerable.Range(0, days).Select(it => Convert.ToDateTime(time.ToString($"yyyy-MM-dd {it.ToString().PadLeft(2, '0')}:00:00"))).ToList();//转成时间数组
var queryableLeft = this.Db.Reportable(dayArray).ToQueryable();
- var queryableRight = this.Db.Queryable().Where((x) => x.RunTime >= runTime.Value.Date && x.RunTime<= runTime.Value.Date.AddDays(1).AddMilliseconds(-1)); //声名表
+ var queryableRight = this.Db.Queryable().Where((x) => x.RunTime >= runTime.Value.Date && x.RunTime <= runTime.Value.Date.AddDays(1).AddMilliseconds(-1)); //声名表
var list = this.Db.Queryable(queryableLeft, queryableRight, JoinType.Left,
- (x1, x2) => x1.ColumnName.Hour == x2.RunTime.Hour)
+ (x1, x2) => x1.ColumnName.Hour == x2.RunTime.Hour)
.GroupBy((x1, x2) => x1.ColumnName)
.Select((x1, x2) => new
{
执行次数 = SqlFunc.AggregateSum(SqlFunc.IIF(x2.Id > 0, 1, 0)),
date = x1.ColumnName.Hour
}).ToList().OrderBy(t => t.date);
+ await Task.CompletedTask;
return list;
}
+ await Task.CompletedTask;
return null;
}
}
From d1288b103ecf582d5491712f63e5dbd8c05048dc Mon Sep 17 00:00:00 2001
From: ansonzhang <3143422472@qq.com>
Date: Thu, 23 Mar 2023 16:39:57 +0800
Subject: [PATCH 042/190] Update README.md
---
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 29d427ec..ee36dc2c 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,8 @@ Blog.Core 开箱即用的企业级前后端分离【 .NET Core6.0 Api + Vue 2.x
#### 框架模块:
- [x] 采用`仓储+服务+接口`的形式封装框架;
-- [x] 异步 async/await 开发;
+- [x] 自定义项目模板 `CreateYourProject.bat` ,可以一键生成自己的项目;🎶
+- [x] 异步 async/await 开发;
- [x] 接入国产数据库ORM组件 —— SqlSugar,封装数据库操作,支持级联操作;
- [x] 支持自由切换多种数据库,MySql/SqlServer/Sqlite/Oracle/Postgresql/达梦/人大金仓;
- [x] 实现项目启动,自动生成种子数据 ✨;
From 798a7f64228960d181fb296aace484a915a2b919 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 24 Mar 2023 21:24:24 +0800
Subject: [PATCH 043/190] =?UTF-8?q?=E8=AE=A2=E9=98=85=E9=93=BE=E6=8E=A5?=
=?UTF-8?q?=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Controllers/TrojanController.cs | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Controllers/TrojanController.cs b/Blog.Core.Api/Controllers/TrojanController.cs
index 8ec64c8a..cdb010e8 100644
--- a/Blog.Core.Api/Controllers/TrojanController.cs
+++ b/Blog.Core.Api/Controllers/TrojanController.cs
@@ -15,6 +15,7 @@
using Blog.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
namespace Blog.Core.Controllers
{
@@ -357,9 +358,12 @@ public async Task>> AddUrlServers(TrojanUrlS
private string GetSplice(TrojanServers item,string passwordshow)
{
if ("0".Equals(item.servertype))
- return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?allowinsecure=0&tfo=0&peer={(string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress)}#{item.servername}";
+ return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?allowinsecure=0&tfo=0&fp=chrome&peer={(string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress)}#{item.servername}";
else if ("1".Equals(item.servertype))
- return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?wspath={item.serverpath}&ws=1&peer={(string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress)}#{item.servername}";
+ {
+ var sni = string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress;
+ return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?wspath={item.serverpath}&ws=1&peer={sni}&path={item.serverpath}&host={sni}&fp=chrome&type=ws&sni={sni}#{item.servername}";
+ }
else
return $"servertype:({item.servertype})错误";
}
From 042c4a6c4497437ac09f93d4c9ec8bbb178a92c1 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Sun, 26 Mar 2023 15:36:45 +0800
Subject: [PATCH 044/190] fix bug
---
Blog.Core.Api/Controllers/TrojanController.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Blog.Core.Api/Controllers/TrojanController.cs b/Blog.Core.Api/Controllers/TrojanController.cs
index cdb010e8..d8d005dc 100644
--- a/Blog.Core.Api/Controllers/TrojanController.cs
+++ b/Blog.Core.Api/Controllers/TrojanController.cs
@@ -357,11 +357,12 @@ public async Task>> AddUrlServers(TrojanUrlS
}
private string GetSplice(TrojanServers item,string passwordshow)
{
+ var sni = string.IsNullOrEmpty(item.serverpeer) ? item.serveraddress : item.serverpeer;
if ("0".Equals(item.servertype))
- return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?allowinsecure=0&tfo=0&fp=chrome&peer={(string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress)}#{item.servername}";
+ return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?allowinsecure=0&tfo=0&fp=chrome&peer={sni}&host={sni}&sni={sni}#{item.servername}";
else if ("1".Equals(item.servertype))
{
- var sni = string.IsNullOrEmpty(item.serverpeer) ? item.serverpeer : item.serveraddress;
+
return $"trojan://{passwordshow}@{item.serveraddress}:{item.serverport}?wspath={item.serverpath}&ws=1&peer={sni}&path={item.serverpath}&host={sni}&fp=chrome&type=ws&sni={sni}#{item.servername}";
}
else
From 67efee3ee1bd7d8337ee3e4af2667c1139e93b11 Mon Sep 17 00:00:00 2001
From: Nine
Date: Thu, 30 Mar 2023 15:38:17 +0800
Subject: [PATCH 045/190] =?UTF-8?q?Sqlsugar=20=E5=88=86=E8=A1=A8=20CRUD=20?=
=?UTF-8?q?demo?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 44 ++++
.../Controllers/SplitDemoController.cs | 199 ++++++++++++++++++
Blog.Core.Api/Program.cs | 4 +
Blog.Core.Api/Startup.cs | 4 +
Blog.Core.Common/Helper/NumberConverter.cs | 174 +++++++++++++++
Blog.Core.Common/Seed/DBSeed.cs | 2 +-
Blog.Core.IServices/BASE/IBaseServices.cs | 10 +-
Blog.Core.IServices/ISplitDemoServices.cs | 15 ++
Blog.Core.Model/Models/SplitDemo.cs | 27 +++
Blog.Core.Repository/BASE/BaseRepository.cs | 72 ++++++-
Blog.Core.Repository/BASE/IBaseRepository.cs | 40 ++++
Blog.Core.Services/BASE/BaseServices.cs | 31 +++
Blog.Core.Services/SplitDemoServices.cs | 23 ++
13 files changed, 642 insertions(+), 3 deletions(-)
create mode 100644 Blog.Core.Api/Controllers/SplitDemoController.cs
create mode 100644 Blog.Core.Common/Helper/NumberConverter.cs
create mode 100644 Blog.Core.IServices/ISplitDemoServices.cs
create mode 100644 Blog.Core.Model/Models/SplitDemo.cs
create mode 100644 Blog.Core.Services/SplitDemoServices.cs
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 89cb3213..9891d5d9 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -1249,6 +1249,50 @@
+
+
+ 分表demo
+
+
+
+
+ 分页获取数据
+
+
+
+
+
+
+
+
+
+
+ 根据ID获取信息
+
+
+
+
+
+
+ 添加一条测试数据
+
+
+
+
+
+
+ 修改一条测试数据
+
+
+
+
+
+
+ 根据id删除数据
+
+
+
+
多租户-多库方案 测试
diff --git a/Blog.Core.Api/Controllers/SplitDemoController.cs b/Blog.Core.Api/Controllers/SplitDemoController.cs
new file mode 100644
index 00000000..fb3c03c6
--- /dev/null
+++ b/Blog.Core.Api/Controllers/SplitDemoController.cs
@@ -0,0 +1,199 @@
+using Blog.Core.IServices;
+using Blog.Core.Model;
+using Blog.Core.Model.Models;
+using Blog.Core.Repository.UnitOfWorks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System.Linq.Expressions;
+
+namespace Blog.Core.Api.Controllers
+{
+ ///
+ /// 分表demo
+ ///
+ [Route("api/[controller]/[action]")]
+ [ApiController]
+ [Authorize(Permissions.Name)]
+ public class SplitDemoController : ControllerBase
+ {
+ readonly ISplitDemoServices splitDemoServices;
+ readonly IUnitOfWorkManage unitOfWorkManage;
+ public SplitDemoController(ISplitDemoServices _splitDemoServices, IUnitOfWorkManage _unitOfWorkManage)
+ {
+ splitDemoServices = _splitDemoServices;
+ unitOfWorkManage = _unitOfWorkManage;
+ }
+
+ ///
+ /// 分页获取数据
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ [AllowAnonymous]
+ public async Task>> Get(DateTime beginTime, DateTime endTime, int page = 1, string key = "", int pageSize = 10)
+ {
+ if (string.IsNullOrEmpty(key) || string.IsNullOrWhiteSpace(key))
+ {
+ key = "";
+ }
+ Expression> whereExpression = a => (a.Name != null && a.Name.Contains(key));
+ var data = await splitDemoServices.QueryPageSplit(whereExpression, beginTime, endTime, page, pageSize, " Id desc ");
+ return MessageModel>.Message(data.dataCount >= 0, "获取成功", data);
+ }
+
+ ///
+ /// 根据ID获取信息
+ ///
+ ///
+ ///
+ [HttpGet]
+ [AllowAnonymous]
+ public async Task> GetById(long id)
+ {
+ var data = new MessageModel();
+ var model = await splitDemoServices.QueryByIdSplit(id);
+ if (model != null)
+ {
+ return MessageModel.Success("获取成功", model);
+ }
+ else
+ {
+ return MessageModel.Fail("获取失败");
+ }
+ }
+
+ ///
+ /// 添加一条测试数据
+ ///
+ ///
+ ///
+ [HttpPost]
+ [AllowAnonymous]
+ public async Task> Post([FromBody] SplitDemo splitDemo)
+ {
+ var data = new MessageModel();
+ unitOfWorkManage.BeginTran();
+ var id = (await splitDemoServices.AddSplit(splitDemo));
+ data.success = (id == null ? false : true);
+ try
+ {
+ if (data.success)
+ {
+ data.response = id.FirstOrDefault().ToString();
+ data.msg = "添加成功";
+ }
+ else
+ {
+ data.msg = "添加失败";
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ finally
+ {
+ if (data.success)
+ unitOfWorkManage.CommitTran();
+ else
+ unitOfWorkManage.RollbackTran();
+ }
+ return data;
+ }
+
+ ///
+ /// 修改一条测试数据
+ ///
+ ///
+ ///
+ [HttpPut]
+ [AllowAnonymous]
+ public async Task> Put([FromBody] SplitDemo splitDemo)
+ {
+ var data = new MessageModel();
+ if (splitDemo != null && splitDemo.Id > 0)
+ {
+ unitOfWorkManage.BeginTran();
+ data.success = await splitDemoServices.UpdateSplit(splitDemo, splitDemo.CreateTime);
+ try
+ {
+ if (data.success)
+ {
+ data.msg = "修改成功";
+ data.response = splitDemo?.Id.ObjToString();
+ }
+ else
+ {
+ data.msg = "修改失败";
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ finally
+ {
+ if (data.success)
+ unitOfWorkManage.CommitTran();
+ else
+ unitOfWorkManage.RollbackTran();
+ }
+ }
+ return data;
+ }
+
+ ///
+ /// 根据id删除数据
+ ///
+ ///
+ ///
+ [HttpDelete]
+ [AllowAnonymous]
+ public async Task> Delete(long id)
+ {
+ var data = new MessageModel();
+
+ var model = await splitDemoServices.QueryByIdSplit(id);
+ if (model != null)
+ {
+ unitOfWorkManage.BeginTran();
+ data.success = await splitDemoServices.DeleteSplit(model,model.CreateTime);
+ try
+ {
+ data.response = id.ObjToString();
+ if (data.success)
+ {
+ data.msg = "删除成功";
+ }
+ else
+ {
+ data.msg = "删除失败";
+ }
+
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ finally
+ {
+ if (data.success)
+ unitOfWorkManage.CommitTran();
+ else
+ unitOfWorkManage.RollbackTran();
+ }
+ }
+ else
+ {
+ data.msg = "不存在";
+ }
+ return data;
+
+ }
+ }
+}
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index f5223beb..2a75498e 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -7,6 +7,7 @@
using Blog.Core;
using Blog.Core.Common;
using Blog.Core.Common.Core;
+using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Blog.Core.Extensions;
using Blog.Core.Extensions.Apollo;
@@ -14,6 +15,7 @@
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
+using Blog.Core.Model;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
@@ -111,6 +113,8 @@
//options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
options.SerializerSettings.Converters.Add(new StringEnumConverter());
+ //将long类型转为string
+ options.SerializerSettings.Converters.Add(new NumberConverter(NumberConverterShip.Int64));
})
//.AddFluentValidation(config =>
//{
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index bc1630f1..4f99b621 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -3,6 +3,7 @@
using System.Text;
using Autofac;
using Blog.Core.Common;
+using Blog.Core.Common.Helper;
using Blog.Core.Common.LogHelper;
using Blog.Core.Common.Seed;
using Blog.Core.Extensions;
@@ -10,6 +11,7 @@
using Blog.Core.Filter;
using Blog.Core.Hubs;
using Blog.Core.IServices;
+using Blog.Core.Model;
using Blog.Core.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
@@ -123,6 +125,8 @@ public void ConfigureServices(IServiceCollection services)
options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
//添加Enum转string
options.SerializerSettings.Converters.Add(new StringEnumConverter());
+ //将long类型转为string
+ options.SerializerSettings.Converters.Add(new NumberConverter(NumberConverterShip.Int64));
});
services.Replace(ServiceDescriptor.Transient());
diff --git a/Blog.Core.Common/Helper/NumberConverter.cs b/Blog.Core.Common/Helper/NumberConverter.cs
new file mode 100644
index 00000000..27890faf
--- /dev/null
+++ b/Blog.Core.Common/Helper/NumberConverter.cs
@@ -0,0 +1,174 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Common.Helper
+{
+ ///
+ ///
+ /// 大数据json序列化重写
+ ///
+ public sealed class NumberConverter : JsonConverter
+ {
+ ///
+ /// 转换成字符串的类型
+ ///
+ private readonly NumberConverterShip _ship;
+
+ ///
+ /// 大数据json序列化重写实例化
+ ///
+ public NumberConverter()
+ {
+ _ship = (NumberConverterShip)0xFF;
+ }
+
+ ///
+ /// 大数据json序列化重写实例化
+ ///
+ /// 转换成字符串的类型
+ public NumberConverter(NumberConverterShip ship)
+ {
+ _ship = ship;
+ }
+
+ ///
+ ///
+ /// 确定此实例是否可以转换指定的对象类型。
+ ///
+ /// 对象的类型。
+ /// 如果此实例可以转换指定的对象类型,则为:true,否则为:false
+ public override bool CanConvert(Type objectType)
+ {
+ var typecode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
+ switch (typecode)
+ {
+ case TypeCode.Decimal:
+ return (_ship & NumberConverterShip.Decimal) == NumberConverterShip.Decimal;
+ case TypeCode.Double:
+ return (_ship & NumberConverterShip.Double) == NumberConverterShip.Double;
+ case TypeCode.Int64:
+ return (_ship & NumberConverterShip.Int64) == NumberConverterShip.Int64;
+ case TypeCode.UInt64:
+ return (_ship & NumberConverterShip.UInt64) == NumberConverterShip.UInt64;
+ case TypeCode.Single:
+ return (_ship & NumberConverterShip.Single) == NumberConverterShip.Single;
+ default: return false;
+ }
+ }
+
+ ///
+ ///
+ /// 读取对象的JSON表示。
+ ///
+ /// 从 中读取。
+ /// 对象的类型。
+ /// 正在读取的对象的现有值。
+ /// 调用的序列化器实例。
+ /// 对象值。
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ return AsType(reader.Value.ToString(), objectType);
+ }
+
+ ///
+ /// 字符串格式数据转其他类型数据
+ ///
+ /// 输入的字符串
+ /// 目标格式
+ /// 转换结果
+ public static object AsType(string input, Type destinationType)
+ {
+ try
+ {
+ var converter = TypeDescriptor.GetConverter(destinationType);
+ if (converter.CanConvertFrom(typeof(string)))
+ {
+ return converter.ConvertFrom(null, null, input);
+ }
+
+ converter = TypeDescriptor.GetConverter(typeof(string));
+ if (converter.CanConvertTo(destinationType))
+ {
+ return converter.ConvertTo(null, null, input, destinationType);
+ }
+ }
+ catch
+ {
+ return null;
+ }
+ return null;
+ }
+
+ ///
+ ///
+ /// 写入对象的JSON表示形式。
+ ///
+ /// 要写入的 。
+ /// 要写入对象值
+ /// 调用的序列化器实例。
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ if (value == null)
+ {
+ writer.WriteNull();
+ }
+ else
+ {
+ var objectType = value.GetType();
+ var typeCode = Type.GetTypeCode(objectType.Name.Equals("Nullable`1") ? objectType.GetGenericArguments().First() : objectType);
+ switch (typeCode)
+ {
+ case TypeCode.Decimal:
+ writer.WriteValue(((decimal)value).ToString("f6"));
+ break;
+ case TypeCode.Double:
+ writer.WriteValue(((double)value).ToString("f4"));
+ break;
+ case TypeCode.Single:
+ writer.WriteValue(((float)value).ToString("f2"));
+ break;
+ default:
+ writer.WriteValue(value.ToString());
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 转换成字符串的类型
+ ///
+ [Flags]
+ public enum NumberConverterShip
+ {
+ ///
+ /// 长整数
+ ///
+ Int64 = 1,
+
+ ///
+ /// 无符号长整数
+ ///
+ UInt64 = 2,
+
+ ///
+ /// 浮点数
+ ///
+ Single = 4,
+
+ ///
+ /// 双精度浮点数
+ ///
+ Double = 8,
+
+ ///
+ /// 大数字
+ ///
+ Decimal =16
+ }
+}
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 7b594109..fb13768a 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -109,7 +109,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
if (!myContext.Db.DbMaintenance.IsAnyTable(t.Name))
{
Console.WriteLine(t.Name);
- myContext.Db.CodeFirst.InitTables(t);
+ myContext.Db.CodeFirst.SplitTables().InitTables(t);
}
});
ConsoleHelper.WriteSuccessLine($"Tables created successfully!");
diff --git a/Blog.Core.IServices/BASE/IBaseServices.cs b/Blog.Core.IServices/BASE/IBaseServices.cs
index 7856f8bf..4091b978 100644
--- a/Blog.Core.IServices/BASE/IBaseServices.cs
+++ b/Blog.Core.IServices/BASE/IBaseServices.cs
@@ -23,7 +23,7 @@ public interface IBaseServices where TEntity : class
Task DeleteById(object id);
Task Delete(TEntity model);
-
+
Task DeleteByIds(object[] ids);
Task Update(TEntity model);
@@ -59,6 +59,14 @@ Task> QueryMuch(
Expression> selectExpression,
Expression> whereLambda = null) where T : class, new();
Task> QueryPage(PaginationModel pagination);
+
+ #region 分表
+ Task QueryByIdSplit(object objId);
+ Task> AddSplit(TEntity entity);
+ Task DeleteSplit(TEntity entity, DateTime dateTime);
+ Task UpdateSplit(TEntity entity, DateTime dateTime);
+ Task> QueryPageSplit(Expression> whereExpression, DateTime beginTime, DateTime endTime, int pageIndex = 1, int pageSize = 20, string orderByFields = null);
+ #endregion
}
}
diff --git a/Blog.Core.IServices/ISplitDemoServices.cs b/Blog.Core.IServices/ISplitDemoServices.cs
new file mode 100644
index 00000000..55215761
--- /dev/null
+++ b/Blog.Core.IServices/ISplitDemoServices.cs
@@ -0,0 +1,15 @@
+
+
+using Blog.Core.IServices.BASE;
+using Blog.Core.Model.Models;
+using System.Threading.Tasks;
+
+namespace Blog.Core.IServices
+{
+ ///
+ /// sysUserInfoServices
+ ///
+ public interface ISplitDemoServices : IBaseServices
+ {
+ }
+}
diff --git a/Blog.Core.Model/Models/SplitDemo.cs b/Blog.Core.Model/Models/SplitDemo.cs
new file mode 100644
index 00000000..26329935
--- /dev/null
+++ b/Blog.Core.Model/Models/SplitDemo.cs
@@ -0,0 +1,27 @@
+using Newtonsoft.Json;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+
+namespace Blog.Core.Model.Models
+{
+ [SplitTable(SplitType.Day)]//按年分表 (自带分表支持 年、季、月、周、日)
+ [SugarTable("SplitDemo_{year}{month}{day}")]//3个变量必须要有,这么设计为了兼容开始按年,后面改成按月、按日
+ public class SplitDemo
+ {
+ [SugarColumn(IsPrimaryKey = true)]
+ public long Id { get; set; }
+
+ public string Name { get; set; }
+
+ [SugarColumn(IsNullable = true)]//设置为可空字段 (更多用法看文档 迁移)
+ public DateTime UpdateTime { get; set; }
+
+ [SplitField] //分表字段 在插入的时候会根据这个字段插入哪个表,在更新删除的时候用这个字段找出相关表
+ public DateTime CreateTime { get; set; }
+ }
+}
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index 828f9506..3048baa8 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -5,6 +5,7 @@
using Blog.Core.Model.Models;
using Blog.Core.Model.Tenants;
using Blog.Core.Repository.UnitOfWorks;
+using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using SqlSugar;
using System;
using System.Collections.Generic;
@@ -127,7 +128,6 @@ public async Task Add(TEntity entity)
return await insert.ExecuteReturnIdentityAsync();
}
-
///
/// 写入实体数据
///
@@ -557,5 +557,75 @@ public async Task> QueryTabsPage(
// groupName = s.groupName,
// jobName = s.jobName
// }, exp, s => new { s.uID, s.uRealName, s.groupName, s.jobName }, model.currentPage, model.pageSize, model.orderField + " " + model.orderType);
+ #region Split分表基础接口 (基础CRUD)
+ ///
+ /// 分页查询[使用版本,其他分页未测试]
+ ///
+ /// 条件表达式
+ /// 页码(下标0)
+ /// 页大小
+ /// 排序字段,如name asc,age desc
+ ///
+ public async Task> QueryPageSplit(Expression> whereExpression, DateTime beginTime, DateTime endTime, int pageIndex = 1, int pageSize = 20, string orderByFields = null)
+ {
+ RefAsync totalCount = 0;
+ var list = await _db.Queryable().SplitTable(beginTime, endTime)
+ .OrderByIF(!string.IsNullOrEmpty(orderByFields), orderByFields)
+ .WhereIF(whereExpression != null, whereExpression)
+ .ToPageListAsync(pageIndex, pageSize, totalCount);
+ var data= new PageModel(pageIndex, totalCount, pageSize, list);
+ return data;
+ }
+ ///
+ /// 写入实体数据
+ ///
+ /// 数据实体
+ ///
+ public async Task> AddSplit(TEntity entity)
+ {
+ var insert = _db.Insertable(entity).SplitTable();
+ //插入并返回雪花ID并且自动赋值ID
+ return await insert.ExecuteReturnSnowflakeIdListAsync();
+ }
+
+ ///
+ /// 更新实体数据
+ ///
+ /// 数据实体
+ ///
+ public async Task UpdateSplit(TEntity entity, DateTime dateTime)
+ {
+ //直接根据实体集合更新 (全自动 找表更新)
+ //return await _db.Updateable(entity).SplitTable().ExecuteCommandAsync();//,SplitTable不能少
+
+ //精准找单个表
+ var tableName = _db.SplitHelper().GetTableName(dateTime);//根据时间获取表名
+ return await _db.Updateable(entity).AS(tableName).ExecuteCommandHasChangeAsync();
+ }
+ ///
+ /// 删除数据
+ ///
+ ///
+ ///
+ ///
+ public async Task DeleteSplit(TEntity entity,DateTime dateTime)
+ {
+ ////直接根据实体集合删除 (全自动 找表插入),返回受影响数
+ //return await _db.Deleteable(entity).SplitTable().ExecuteCommandAsync();//,SplitTable不能少
+
+ //精准找单个表
+ var tableName = _db.SplitHelper().GetTableName(dateTime);//根据时间获取表名
+ return await _db.Deleteable().AS(tableName).Where(entity).ExecuteCommandHasChangeAsync();
+ }
+ ///
+ /// 根据ID查找数据
+ ///
+ ///
+ ///
+ public async Task QueryByIdSplit(object objId)
+ {
+ return await _db.Queryable().In(objId).SplitTable(tabs => tabs).SingleAsync();
+ }
+ #endregion
}
}
\ No newline at end of file
diff --git a/Blog.Core.Repository/BASE/IBaseRepository.cs b/Blog.Core.Repository/BASE/IBaseRepository.cs
index 29783505..5f70a4be 100644
--- a/Blog.Core.Repository/BASE/IBaseRepository.cs
+++ b/Blog.Core.Repository/BASE/IBaseRepository.cs
@@ -208,5 +208,45 @@ Task> QueryTabsPage(
int pageIndex = 1,
int pageSize = 20,
string orderByFields = null);
+
+ #region 分表
+ ///
+ /// 通过ID查询
+ ///
+ ///
+ ///
+ Task QueryByIdSplit(object objId);
+ ///
+ /// 自动分表插入
+ ///
+ ///
+ ///
+ Task> AddSplit(TEntity entity);
+ ///
+ /// 删除
+ ///
+ ///
+ ///
+ ///
+ Task DeleteSplit(TEntity entity, DateTime dateTime);
+ ///
+ /// 更新
+ ///
+ ///
+ ///
+ ///
+ Task UpdateSplit(TEntity entity, DateTime dateTime);
+ ///
+ /// 分页查询
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ Task> QueryPageSplit(Expression> whereExpression, DateTime beginTime, DateTime endTime, int pageIndex = 1, int pageSize = 20, string orderByFields = null);
+ #endregion
}
}
diff --git a/Blog.Core.Services/BASE/BaseServices.cs b/Blog.Core.Services/BASE/BaseServices.cs
index f8105165..7ee55eb1 100644
--- a/Blog.Core.Services/BASE/BaseServices.cs
+++ b/Blog.Core.Services/BASE/BaseServices.cs
@@ -332,5 +332,36 @@ public async Task> QueryPage(PaginationModel pagination)
var express = DynamicLinqFactory.CreateLambda(pagination.Conditions);
return await QueryPage(express, pagination.PageIndex, pagination.PageSize, pagination.OrderByFileds);
}
+ #region 分表
+ public async Task> AddSplit(TEntity entity)
+ {
+ return await BaseDal.AddSplit(entity);
+ }
+ public async Task UpdateSplit(TEntity entity, DateTime dateTime)
+ {
+ return await BaseDal.UpdateSplit(entity, dateTime);
+ }
+
+ ///
+ /// 根据实体删除一条数据
+ ///
+ /// 博文实体类
+ ///
+ public async Task DeleteSplit(TEntity entity, DateTime dateTime)
+ {
+ return await BaseDal.DeleteSplit(entity, dateTime);
+ }
+
+ public async Task QueryByIdSplit(object objId)
+ {
+ return await BaseDal.QueryByIdSplit(objId);
+ }
+ public async Task> QueryPageSplit(Expression> whereExpression, DateTime beginTime, DateTime endTime,
+ int pageIndex = 1, int pageSize = 20, string orderByFields = null)
+ {
+ return await BaseDal.QueryPageSplit(whereExpression, beginTime, endTime,
+ pageIndex, pageSize, orderByFields);
+ }
+ #endregion
}
}
\ No newline at end of file
diff --git a/Blog.Core.Services/SplitDemoServices.cs b/Blog.Core.Services/SplitDemoServices.cs
new file mode 100644
index 00000000..cf8e2cc1
--- /dev/null
+++ b/Blog.Core.Services/SplitDemoServices.cs
@@ -0,0 +1,23 @@
+using Blog.Core.IRepository.Base;
+using Blog.Core.IServices;
+using Blog.Core.Model.Models;
+using Blog.Core.Services.BASE;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace Blog.Core.FrameWork.Services
+{
+ ///
+ /// sysUserInfoServices
+ ///
+ public class SplitDemoServices : BaseServices, ISplitDemoServices
+ {
+ private readonly IBaseRepository _splitDemoRepository;
+ public SplitDemoServices(IBaseRepository splitDemoRepository)
+ {
+ _splitDemoRepository = splitDemoRepository;
+ }
+
+
+ }
+}
From 7b1f3a4c740f6cc7302219a12bb1033ab583018c Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Thu, 30 Mar 2023 15:49:30 +0800
Subject: [PATCH 046/190] feat: :airplane: change id to long
---
Blog.Core.Api/Blog.Core.Model.xml | 5 ---
Blog.Core.Api/Blog.Core.xml | 4 +-
.../Controllers/DbFirst/MigrateController.cs | 30 ++++++-------
.../Controllers/DepartmentController.cs | 2 +-
.../Controllers/PermissionController.cs | 24 +++++-----
Blog.Core.Api/Controllers/UserController.cs | 6 +--
.../wwwroot/BlogCore.Data.json/Permission.tsv | 44 +++++++++----------
.../RoleModulePermission.tsv | 12 ++---
Blog.Core.Common/DB/Aop/SqlsugarAop.cs | 10 ++++-
Blog.Core.Common/Helper/RecursionHelper.cs | 12 ++---
Blog.Core.Common/Seed/DBSeed.cs | 30 +++++++------
.../IRoleModulePermissionServices.cs | 2 +-
Blog.Core.Model/Models/AccessTrendLog.cs | 2 +-
Blog.Core.Model/Models/Advertisement.cs | 2 +-
Blog.Core.Model/Models/BlogArticle.cs | 4 +-
Blog.Core.Model/Models/BlogArticleComment.cs | 2 +-
Blog.Core.Model/Models/Department.cs | 2 +-
Blog.Core.Model/Models/GblLogAudit.cs | 4 +-
Blog.Core.Model/Models/Guestbook.cs | 6 +--
Blog.Core.Model/Models/Modules.cs | 2 +-
Blog.Core.Model/Models/OperateLog.cs | 2 +-
Blog.Core.Model/Models/PasswordLib.cs | 6 +--
Blog.Core.Model/Models/Permission.cs | 2 +-
Blog.Core.Model/Models/Role.cs | 2 +-
.../Models/RoleModulePermission.cs | 2 +-
Blog.Core.Model/Models/RootEntity.cs | 15 -------
Blog.Core.Model/Models/TasksLog.cs | 4 +-
Blog.Core.Model/Models/TasksQz.cs | 2 +-
Blog.Core.Model/Models/TestModels.cs | 6 +--
Blog.Core.Model/Models/Topic.cs | 2 +-
Blog.Core.Model/Models/TopicDetail.cs | 2 +-
Blog.Core.Model/Models/UserRole.cs | 6 +--
Blog.Core.Model/Models/sysUserInfo.cs | 4 +-
Blog.Core.Model/ViewModels/BlogViewModels.cs | 4 +-
.../IRoleModulePermissionRepository.cs | 2 +-
.../RoleModulePermissionRepository.cs | 2 +-
.../RoleModulePermissionServices.cs | 2 +-
37 files changed, 130 insertions(+), 140 deletions(-)
delete mode 100644 Blog.Core.Model/Models/RootEntity.cs
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index 6bbfd4fe..fe62d8e2 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -1795,11 +1795,6 @@
修改时间
-
-
- ID
-
-
部门表
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 89cb3213..faf9d522 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -413,14 +413,14 @@
-
+
获取路由树
-
+
获取路由树
diff --git a/Blog.Core.Api/Controllers/DbFirst/MigrateController.cs b/Blog.Core.Api/Controllers/DbFirst/MigrateController.cs
index 8006d1fb..7865cc69 100644
--- a/Blog.Core.Api/Controllers/DbFirst/MigrateController.cs
+++ b/Blog.Core.Api/Controllers/DbFirst/MigrateController.cs
@@ -81,7 +81,7 @@ public async Task> DataMigrateFromOld2New()
InitPermissionTree(permissions, permissionsAllList, apiList);
var actionPermissionIds = permissionsAllList.Where(d => d.Id >= filterPermissionId).Select(d => d.Id).ToList();
- List filterPermissionIds = new();
+ List filterPermissionIds = new();
FilterPermissionTree(permissionsAllList, actionPermissionIds, filterPermissionIds);
permissions = permissions.Where(d => filterPermissionIds.Contains(d.Id)).ToList();
@@ -93,10 +93,10 @@ public async Task> DataMigrateFromOld2New()
// 1、保持菜单和接口
await SavePermissionTreeAsync(permissions, pms);
- var rid = 0;
- var pid = 0;
- var mid = 0;
- var rpmid = 0;
+ long rid = 0;
+ long pid = 0;
+ long mid = 0;
+ long rpmid = 0;
// 2、保存关系表
foreach (var item in rmps)
@@ -116,8 +116,8 @@ public async Task> DataMigrateFromOld2New()
}
}
- pid = (pms.FirstOrDefault(d => d.PidOld == item.PermissionId)?.PidNew).ObjToInt();
- mid = (pms.FirstOrDefault(d => d.MidOld == item.ModuleId)?.MidNew).ObjToInt();
+ pid = (pms.FirstOrDefault(d => d.PidOld == item.PermissionId)?.PidNew).ObjToLong();
+ mid = (pms.FirstOrDefault(d => d.MidOld == item.ModuleId)?.MidNew).ObjToLong();
// 关系
if (rid > 0 && pid > 0)
{
@@ -282,7 +282,7 @@ private void InitPermissionTree(List permissionsTree, List permissionsAll, List actionPermissionId, List filterPermissionIds)
+ private void FilterPermissionTree(List permissionsAll, List actionPermissionId, List filterPermissionIds)
{
actionPermissionId = actionPermissionId.Distinct().ToList();
var doneIds = permissionsAll.Where(d => actionPermissionId.Contains(d.Id) && d.Pid == 0).Select(d => d.Id).ToList();
@@ -295,7 +295,7 @@ private void FilterPermissionTree(List permissionsAll, List act
}
}
- private async Task SavePermissionTreeAsync(List permissionsTree, List pms, int permissionId = 0)
+ private async Task SavePermissionTreeAsync(List permissionsTree, List pms, long permissionId = 0)
{
var parendId = permissionId;
@@ -304,9 +304,9 @@ private async Task SavePermissionTreeAsync(List permissionsTree, Lis
PM pm = new PM();
// 保留原始主键id
pm.PidOld = item.Id;
- pm.MidOld = (item.Module?.Id).ObjToInt();
+ pm.MidOld = (item.Module?.Id).ObjToLong();
- var mid = 0;
+ long mid = 0;
// 接口
if (item.Module != null)
{
@@ -351,9 +351,9 @@ private async Task SavePermissionTreeAsync(List permissionsTree, Lis
public class PM
{
- public int PidOld { get; set; }
- public int MidOld { get; set; }
- public int PidNew { get; set; }
- public int MidNew { get; set; }
+ public long PidOld { get; set; }
+ public long MidOld { get; set; }
+ public long PidNew { get; set; }
+ public long MidNew { get; set; }
}
}
diff --git a/Blog.Core.Api/Controllers/DepartmentController.cs b/Blog.Core.Api/Controllers/DepartmentController.cs
index bca7bf6d..b8174e90 100644
--- a/Blog.Core.Api/Controllers/DepartmentController.cs
+++ b/Blog.Core.Api/Controllers/DepartmentController.cs
@@ -83,7 +83,7 @@ public async Task>> GetTreeTable(long f = 0, strin
foreach (var item in departments)
{
- List pidarr = new() { };
+ List pidarr = new() { };
var parent = departmentList.FirstOrDefault(d => d.Id == item.Pid);
while (parent != null)
diff --git a/Blog.Core.Api/Controllers/PermissionController.cs b/Blog.Core.Api/Controllers/PermissionController.cs
index 70f8f689..9277a36b 100644
--- a/Blog.Core.Api/Controllers/PermissionController.cs
+++ b/Blog.Core.Api/Controllers/PermissionController.cs
@@ -99,7 +99,7 @@ public async Task>> Get(int page = 1, string
var permissionAll = await _permissionServices.Query(d => d.IsDeleted != true);
foreach (var item in permissionsView)
{
- List pidarr = new List
+ List pidarr = new()
{
item.Pid
};
@@ -177,7 +177,7 @@ public async Task>> GetTreeTable(int f = 0, string
foreach (var item in permissions)
{
- List pidarr = new List { };
+ List pidarr = new() { };
var parent = permissionsList.FirstOrDefault(d => d.Id == item.Pid);
while (parent != null)
@@ -353,13 +353,13 @@ orderby child.Id
///
///
[HttpGet]
- public async Task> GetNavigationBar(int uid)
+ public async Task> GetNavigationBar(long uid)
{
var data = new MessageModel();
var uidInHttpcontext1 = 0;
- var roleIds = new List();
+ var roleIds = new List();
// ids4和jwt切换
if (Permissions.IsUseIds4)
{
@@ -369,13 +369,13 @@ public async Task> GetNavigationBar(int uid)
select item.Value).FirstOrDefault().ObjToInt();
roleIds = (from item in _httpContext.HttpContext.User.Claims
where item.Type == "role"
- select item.Value.ObjToInt()).ToList();
+ select item.Value.ObjToLong()).ToList();
}
else
{
// jwt
uidInHttpcontext1 = ((JwtHelper.SerializeJwt(_httpContext.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "")))?.Uid).ObjToInt();
- roleIds = (await _userRoleServices.Query(d => d.IsDeleted == false && d.UserId == uid)).Select(d => d.RoleId.ObjToInt()).Distinct().ToList();
+ roleIds = (await _userRoleServices.Query(d => d.IsDeleted == false && d.UserId == uid)).Select(d => d.RoleId.ObjToLong()).Distinct().ToList();
}
@@ -383,7 +383,7 @@ public async Task> GetNavigationBar(int uid)
{
if (roleIds.Any())
{
- var pids = (await _roleModulePermissionServices.Query(d => d.IsDeleted == false && roleIds.Contains(d.RoleId))).Select(d => d.PermissionId.ObjToInt()).Distinct();
+ var pids = (await _roleModulePermissionServices.Query(d => d.IsDeleted == false && roleIds.Contains(d.RoleId))).Select(d => d.PermissionId.ObjToLong()).Distinct();
if (pids.Any())
{
var rolePermissionMoudles = (await _permissionServices.Query(d => pids.Contains(d.Id))).OrderBy(c => c.OrderSort);
@@ -445,12 +445,12 @@ orderby child.Id
///
///
[HttpGet]
- public async Task>> GetNavigationBarPro(int uid)
+ public async Task>> GetNavigationBarPro(long uid)
{
var data = new MessageModel>();
var uidInHttpcontext1 = 0;
- var roleIds = new List();
+ var roleIds = new List();
// ids4和jwt切换
if (Permissions.IsUseIds4)
{
@@ -460,13 +460,13 @@ public async Task>> GetNavigationBarPro(int
select item.Value).FirstOrDefault().ObjToInt();
roleIds = (from item in _httpContext.HttpContext.User.Claims
where item.Type == "role"
- select item.Value.ObjToInt()).ToList();
+ select item.Value.ObjToLong()).ToList();
}
else
{
// jwt
uidInHttpcontext1 = ((JwtHelper.SerializeJwt(_httpContext.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "")))?.Uid).ObjToInt();
- roleIds = (await _userRoleServices.Query(d => d.IsDeleted == false && d.UserId == uid)).Select(d => d.RoleId.ObjToInt()).Distinct().ToList();
+ roleIds = (await _userRoleServices.Query(d => d.IsDeleted == false && d.UserId == uid)).Select(d => d.RoleId.ObjToLong()).Distinct().ToList();
}
if (uid > 0 && uid == uidInHttpcontext1)
@@ -474,7 +474,7 @@ public async Task>> GetNavigationBarPro(int
if (roleIds.Any())
{
var pids = (await _roleModulePermissionServices.Query(d => d.IsDeleted == false && roleIds.Contains(d.RoleId)))
- .Select(d => d.PermissionId.ObjToInt()).Distinct();
+ .Select(d => d.PermissionId.ObjToLong()).Distinct();
if (pids.Any())
{
var rolePermissionMoudles = (await _permissionServices.Query(d => pids.Contains(d.Id) && d.IsButton == false)).OrderBy(c => c.OrderSort);
diff --git a/Blog.Core.Api/Controllers/UserController.cs b/Blog.Core.Api/Controllers/UserController.cs
index 43f7f610..27989821 100644
--- a/Blog.Core.Api/Controllers/UserController.cs
+++ b/Blog.Core.Api/Controllers/UserController.cs
@@ -103,15 +103,15 @@ public async Task>> Get(int page = 1, str
return Success(data.ConvertTo(_mapper));
}
- private (string, List) GetFullDepartmentName(List departments, int departmentId)
+ private (string, List) GetFullDepartmentName(List departments, int departmentId)
{
var departmentModel = departments.FirstOrDefault(d => d.Id == departmentId);
if (departmentModel == null)
{
- return ("", new List());
+ return ("", new List());
}
- var pids = departmentModel.CodeRelationship?.TrimEnd(',').Split(',').Select(d => d.ObjToInt()).ToList();
+ var pids = departmentModel.CodeRelationship?.TrimEnd(',').Split(',').Select(d => d.ObjToLong()).ToList();
pids.Add(departmentModel.Id);
var pnams = departments.Where(d => pids.Contains(d.Id)).ToList().Select(d => d.Name).ToArray();
var fullName = string.Join("/", pnams);
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
index d1a5c3f8..c026f01e 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/Permission.tsv
@@ -2323,28 +2323,28 @@
"Pid": 94,
"Mid": 63
},
- {
- "Id": 114,
- "Code": " ",
- "Name": "推送文字消息",
- "IsButton": 1,
- "IsHide": 0,
- "IskeepAlive": 0,
- "Func": null,
- "OrderSort": 0,
- "Icon": null,
- "Description": null,
- "Enabled": 1,
- "CreateId": 8,
- "CreateBy": "test",
- "CreateTime": "2020-04-23 16:22:11",
- "ModifyId": null,
- "ModifyBy": null,
- "ModifyTime": "2021-09-29 00:00:00",
- "IsDeleted": 0,
- "Pid": 95,
- "Mid": 0
- },
+ //{
+ // "Id": 114,
+ // "Code": " ",
+ // "Name": "推送文字消息",
+ // "IsButton": 1,
+ // "IsHide": 0,
+ // "IskeepAlive": 0,
+ // "Func": null,
+ // "OrderSort": 0,
+ // "Icon": null,
+ // "Description": null,
+ // "Enabled": 1,
+ // "CreateId": 8,
+ // "CreateBy": "test",
+ // "CreateTime": "2020-04-23 16:22:11",
+ // "ModifyId": null,
+ // "ModifyBy": null,
+ // "ModifyTime": "2021-09-29 00:00:00",
+ // "IsDeleted": 0,
+ // "Pid": 95,
+ // "Mid": 0
+ //},
{
"Code": "-",
"Name": "部门权限管理",
diff --git a/Blog.Core.Api/wwwroot/BlogCore.Data.json/RoleModulePermission.tsv b/Blog.Core.Api/wwwroot/BlogCore.Data.json/RoleModulePermission.tsv
index b7923ab4..eb727383 100644
--- a/Blog.Core.Api/wwwroot/BlogCore.Data.json/RoleModulePermission.tsv
+++ b/Blog.Core.Api/wwwroot/BlogCore.Data.json/RoleModulePermission.tsv
@@ -1647,7 +1647,7 @@
"ModifyId": null,
"ModifyBy": null,
"ModifyTime": "\/Date(1546272000000+0800)\/",
- "Id": 128
+ "Id": 228
},
{
"IsDeleted": false,
@@ -1658,7 +1658,7 @@
"RoleId": 6,
"ModuleId": 0,
"PermissionId": 114,
- "Id": 129
+ "Id": 229
},
{
"IsDeleted": false,
@@ -1669,7 +1669,7 @@
"RoleId": 6,
"ModuleId": 66,
"PermissionId": 115,
- "Id": 130
+ "Id": 230
},
{
"IsDeleted": false,
@@ -1680,7 +1680,7 @@
"RoleId": 6,
"ModuleId": 70,
"PermissionId": 120,
- "Id": 131
+ "Id": 231
},
{
"IsDeleted": false,
@@ -1691,7 +1691,7 @@
"RoleId": 6,
"ModuleId": 66,
"PermissionId": 116,
- "Id": 132
+ "Id": 232
},
{
"IsDeleted": false,
@@ -1702,6 +1702,6 @@
"RoleId": 4,
"ModuleId": 72,
"PermissionId": 122,
- "Id": 133
+ "Id": 233
}
]
diff --git a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
index 3d83b002..c1417a5a 100644
--- a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
+++ b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
@@ -1,4 +1,5 @@
-using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Model;
+using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Model.Tenants;
using SqlSugar;
using System;
@@ -16,6 +17,13 @@ public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
root.Id = SnowFlakeSingle.Instance.NextId();
}
}
+ if (entityInfo.EntityValue is RootEntityTkey rootEntity)
+ {
+ if (rootEntity.Id == 0)
+ {
+ rootEntity.Id = SnowFlakeSingle.Instance.NextId();
+ }
+ }
if (entityInfo.EntityValue is BaseEntity baseEntity)
{
diff --git a/Blog.Core.Common/Helper/RecursionHelper.cs b/Blog.Core.Common/Helper/RecursionHelper.cs
index 9b27a37d..f6f21a38 100644
--- a/Blog.Core.Common/Helper/RecursionHelper.cs
+++ b/Blog.Core.Common/Helper/RecursionHelper.cs
@@ -117,8 +117,8 @@ public static void LoopToAppendChildrenT(List all, T curItem, string paren
public class PermissionTree
{
- public int value { get; set; }
- public int Pid { get; set; }
+ public long value { get; set; }
+ public long Pid { get; set; }
public string label { get; set; }
public int order { get; set; }
public bool isbtn { get; set; }
@@ -139,8 +139,8 @@ public class DepartmentTree
public class NavigationBar
{
- public int id { get; set; }
- public int pid { get; set; }
+ public long id { get; set; }
+ public long pid { get; set; }
public int order { get; set; }
public string name { get; set; }
public bool IsHide { get; set; } = false;
@@ -165,8 +165,8 @@ public class NavigationBarMeta
public class NavigationBarPro
{
- public int id { get; set; }
- public int parentId { get; set; }
+ public long id { get; set; }
+ public long parentId { get; set; }
public int order { get; set; }
public string name { get; set; }
public bool IsHide { get; set; } = false;
diff --git a/Blog.Core.Common/Seed/DBSeed.cs b/Blog.Core.Common/Seed/DBSeed.cs
index 7b594109..94893c38 100644
--- a/Blog.Core.Common/Seed/DBSeed.cs
+++ b/Blog.Core.Common/Seed/DBSeed.cs
@@ -175,7 +175,11 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Permission"), Encoding.UTF8), setting);
- myContext.GetEntityDB().InsertRange(data);
+ foreach (var item in data)
+ {
+ Console.WriteLine($"{item.Name}:{item.Id}");
+ myContext.GetEntityDB().Insert(item);
+ }
Console.WriteLine("Table:Permission created success!");
}
else
@@ -190,10 +194,10 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
if (!await myContext.Db.Queryable().AnyAsync())
{
- //var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Role"), Encoding.UTF8), setting);
- using var stream = new FileStream(Path.Combine(WebRootPath, "BlogCore.Data.excel", "Role.xlsx"), FileMode.Open);
- var result = await importer.Import(stream);
- var data = result.Data.ToList();
+ var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "Role"), Encoding.UTF8), setting);
+ //using var stream = new FileStream(Path.Combine(WebRootPath, "BlogCore.Data.excel", "Role.xlsx"), FileMode.Open);
+ //var result = await importer.Import(stream);
+ //var data = result.Data.ToList();
myContext.GetEntityDB().InsertRange(data);
Console.WriteLine("Table:Role created success!");
@@ -212,7 +216,11 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
{
var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "RoleModulePermission"), Encoding.UTF8), setting);
- myContext.GetEntityDB().InsertRange(data);
+ foreach (var item in data)
+ {
+ Console.WriteLine($"{item.Id}");
+ myContext.GetEntityDB().Insert(item);
+ }
Console.WriteLine("Table:RoleModulePermission created success!");
}
else
@@ -261,10 +269,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
if (!await myContext.Db.Queryable().AnyAsync())
{
- //var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "UserRole"), Encoding.UTF8), setting);
- using var stream = new FileStream(Path.Combine(WebRootPath, "BlogCore.Data.excel", "UserRole.xlsx"), FileMode.Open);
- var result = await importer.Import(stream);
- var data = result.Data.ToList();
+ var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "UserRole"), Encoding.UTF8), setting);
myContext.GetEntityDB().InsertRange(data);
Console.WriteLine("Table:UserRole created success!");
@@ -281,10 +286,7 @@ public static async Task SeedAsync(MyContext myContext, string WebRootPath)
if (!await myContext.Db.Queryable().AnyAsync())
{
- //var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "sysUserInfo"), Encoding.UTF8), setting);
- using var stream = new FileStream(Path.Combine(WebRootPath, "BlogCore.Data.excel", "SysUserInfo.xlsx"), FileMode.Open);
- var result = await importer.Import(stream);
- var data = result.Data.ToList();
+ var data = JsonConvert.DeserializeObject>(FileHelper.ReadFile(string.Format(SeedDataFolder, "sysUserInfo"), Encoding.UTF8), setting);
myContext.GetEntityDB().InsertRange(data);
Console.WriteLine("Table:sysUserInfo created success!");
diff --git a/Blog.Core.IServices/IRoleModulePermissionServices.cs b/Blog.Core.IServices/IRoleModulePermissionServices.cs
index 22532479..2a5c7345 100644
--- a/Blog.Core.IServices/IRoleModulePermissionServices.cs
+++ b/Blog.Core.IServices/IRoleModulePermissionServices.cs
@@ -21,6 +21,6 @@ public interface IRoleModulePermissionServices :IBaseServices˵
/// ӿ
///
- Task UpdateModuleId(int permissionId, int moduleId);
+ Task UpdateModuleId(long permissionId, long moduleId);
}
}
diff --git a/Blog.Core.Model/Models/AccessTrendLog.cs b/Blog.Core.Model/Models/AccessTrendLog.cs
index 4a87b13e..fd6dbae7 100644
--- a/Blog.Core.Model/Models/AccessTrendLog.cs
+++ b/Blog.Core.Model/Models/AccessTrendLog.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Model.Models
///
/// 用户访问趋势日志
///
- public class AccessTrendLog : RootEntityTkey
+ public class AccessTrendLog : RootEntityTkey
{
///
/// 用户
diff --git a/Blog.Core.Model/Models/Advertisement.cs b/Blog.Core.Model/Models/Advertisement.cs
index c2babd74..3b11b21f 100644
--- a/Blog.Core.Model/Models/Advertisement.cs
+++ b/Blog.Core.Model/Models/Advertisement.cs
@@ -3,7 +3,7 @@
namespace Blog.Core.Model.Models
{
- public class Advertisement : RootEntityTkey
+ public class Advertisement : RootEntityTkey
{
///
diff --git a/Blog.Core.Model/Models/BlogArticle.cs b/Blog.Core.Model/Models/BlogArticle.cs
index 66f05bdf..8b75c8df 100644
--- a/Blog.Core.Model/Models/BlogArticle.cs
+++ b/Blog.Core.Model/Models/BlogArticle.cs
@@ -13,8 +13,8 @@ public class BlogArticle
/// 主键
///
/// 这里之所以没用RootEntity,是想保持和之前的数据库一致,主键是bID,不是Id
- [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
- public int bID { get; set; }
+ [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = false)]
+ public long bID { get; set; }
///
/// 创建人
diff --git a/Blog.Core.Model/Models/BlogArticleComment.cs b/Blog.Core.Model/Models/BlogArticleComment.cs
index 08010863..519fb003 100644
--- a/Blog.Core.Model/Models/BlogArticleComment.cs
+++ b/Blog.Core.Model/Models/BlogArticleComment.cs
@@ -7,7 +7,7 @@ namespace Blog.Core.Model.Models;
///
public class BlogArticleComment : RootEntityTkey
{
- public int bID { get; set; }
+ public long bID { get; set; }
public string Comment { get; set; }
diff --git a/Blog.Core.Model/Models/Department.cs b/Blog.Core.Model/Models/Department.cs
index 3583bcff..424bcf44 100644
--- a/Blog.Core.Model/Models/Department.cs
+++ b/Blog.Core.Model/Models/Department.cs
@@ -7,7 +7,7 @@ namespace Blog.Core.Model.Models
///
/// 部门表
///
- public class Department : DepartmentRoot
+ public class Department : DepartmentRoot
{
///
/// Desc:部门关系编码
diff --git a/Blog.Core.Model/Models/GblLogAudit.cs b/Blog.Core.Model/Models/GblLogAudit.cs
index 4b1bd9cd..2cecce8b 100644
--- a/Blog.Core.Model/Models/GblLogAudit.cs
+++ b/Blog.Core.Model/Models/GblLogAudit.cs
@@ -12,8 +12,8 @@ public class GblLogAudit
///
///ID
///
- [SugarColumn(ColumnDescription = "ID", IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
- public int Id { get; set; }
+ [SugarColumn(ColumnDescription = "ID", IsNullable = false, IsPrimaryKey = true, IsIdentity = false)]
+ public long Id { get; set; }
///
///HttpContext.TraceIdentifier 事件链路ID(获取或设置一个唯一标识符,用于在跟踪日志中表示此请求。)
diff --git a/Blog.Core.Model/Models/Guestbook.cs b/Blog.Core.Model/Models/Guestbook.cs
index d1f671c0..0cd5dcef 100644
--- a/Blog.Core.Model/Models/Guestbook.cs
+++ b/Blog.Core.Model/Models/Guestbook.cs
@@ -3,13 +3,13 @@
namespace Blog.Core.Model.Models
{
- public class Guestbook:RootEntityTkey
+ public class Guestbook : RootEntityTkey
{
-
+
/// 博客ID
///
///
- public int? blogId { get; set; }
+ public long? blogId { get; set; }
/// 创建时间
///
///
diff --git a/Blog.Core.Model/Models/Modules.cs b/Blog.Core.Model/Models/Modules.cs
index b62c0a47..6e41aaac 100644
--- a/Blog.Core.Model/Models/Modules.cs
+++ b/Blog.Core.Model/Models/Modules.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Model.Models
///
/// 接口API地址信息表
///
- public class Modules : ModulesRoot
+ public class Modules : ModulesRoot
{
public Modules()
{
diff --git a/Blog.Core.Model/Models/OperateLog.cs b/Blog.Core.Model/Models/OperateLog.cs
index 4086781c..3c2fb54c 100644
--- a/Blog.Core.Model/Models/OperateLog.cs
+++ b/Blog.Core.Model/Models/OperateLog.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Model.Models
///
/// 日志记录
///
- public class OperateLog : RootEntityTkey
+ public class OperateLog : RootEntityTkey
{
///
diff --git a/Blog.Core.Model/Models/PasswordLib.cs b/Blog.Core.Model/Models/PasswordLib.cs
index 2b43c265..b8b633d6 100644
--- a/Blog.Core.Model/Models/PasswordLib.cs
+++ b/Blog.Core.Model/Models/PasswordLib.cs
@@ -7,11 +7,11 @@ namespace Blog.Core.Model.Models
/// 密码库表
///
[SugarTable("PasswordLib", "密码库表")]//('数据库表名','数据库表备注')
- [TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库,名字是appsettings.json 的 ConnId')
+ [Tenant("WMBLOG_MYSQL_2")] //('代表是哪个数据库,名字是appsettings.json 的 ConnId')
public class PasswordLib
{
- [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
- public int PLID { get; set; }
+ [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = false)]
+ public long PLID { get; set; }
///
///获取或设置是否禁用,逻辑上的删除,非物理删除
diff --git a/Blog.Core.Model/Models/Permission.cs b/Blog.Core.Model/Models/Permission.cs
index c650cb5e..deece0c0 100644
--- a/Blog.Core.Model/Models/Permission.cs
+++ b/Blog.Core.Model/Models/Permission.cs
@@ -7,7 +7,7 @@ namespace Blog.Core.Model.Models
///
/// 路由菜单表
///
- public class Permission : PermissionRoot
+ public class Permission : PermissionRoot
{
public Permission()
{
diff --git a/Blog.Core.Model/Models/Role.cs b/Blog.Core.Model/Models/Role.cs
index e34ccdd9..1357afb0 100644
--- a/Blog.Core.Model/Models/Role.cs
+++ b/Blog.Core.Model/Models/Role.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Model.Models
///
/// 角色表
///
- public class Role : RootEntityTkey
+ public class Role : RootEntityTkey
{
public Role()
{
diff --git a/Blog.Core.Model/Models/RoleModulePermission.cs b/Blog.Core.Model/Models/RoleModulePermission.cs
index 13d82a80..482b9b4e 100644
--- a/Blog.Core.Model/Models/RoleModulePermission.cs
+++ b/Blog.Core.Model/Models/RoleModulePermission.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Model.Models
///
/// 按钮跟权限关联表
///
- public class RoleModulePermission : RoleModulePermissionRoot
+ public class RoleModulePermission : RoleModulePermissionRoot
{
public RoleModulePermission()
{
diff --git a/Blog.Core.Model/Models/RootEntity.cs b/Blog.Core.Model/Models/RootEntity.cs
deleted file mode 100644
index d3874bb4..00000000
--- a/Blog.Core.Model/Models/RootEntity.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using SqlSugar;
-
-namespace Blog.Core.Model
-{
- public class RootEntity
- {
- ///
- /// ID
- ///
- [SugarColumn(IsNullable = false, IsPrimaryKey = true)]
- public int Id { get; set; }
-
-
- }
-}
\ No newline at end of file
diff --git a/Blog.Core.Model/Models/TasksLog.cs b/Blog.Core.Model/Models/TasksLog.cs
index b4317c95..c79e8077 100644
--- a/Blog.Core.Model/Models/TasksLog.cs
+++ b/Blog.Core.Model/Models/TasksLog.cs
@@ -6,12 +6,12 @@ namespace Blog.Core.Model.Models
///
/// 任务日志表
///
- public class TasksLog : RootEntityTkey
+ public class TasksLog : RootEntityTkey
{
///
/// 任务ID
///
- public int JobId { get; set; }
+ public long JobId { get; set; }
///
/// 任务耗时
///
diff --git a/Blog.Core.Model/Models/TasksQz.cs b/Blog.Core.Model/Models/TasksQz.cs
index 1c07b60e..b029a995 100644
--- a/Blog.Core.Model/Models/TasksQz.cs
+++ b/Blog.Core.Model/Models/TasksQz.cs
@@ -8,7 +8,7 @@ namespace Blog.Core.Model.Models
///
/// 任务计划表
///
- public class TasksQz : RootEntityTkey
+ public class TasksQz : RootEntityTkey
{
///
/// 任务名称
diff --git a/Blog.Core.Model/Models/TestModels.cs b/Blog.Core.Model/Models/TestModels.cs
index f5fa7dc7..8a8d123c 100644
--- a/Blog.Core.Model/Models/TestModels.cs
+++ b/Blog.Core.Model/Models/TestModels.cs
@@ -5,9 +5,9 @@ public class TestMuchTableResult
{
public string moduleName { get; set; }
public string permName { get; set; }
- public int rid { get; set; }
- public int mid { get; set; }
- public int? pid { get; set; }
+ public long rid { get; set; }
+ public long mid { get; set; }
+ public long? pid { get; set; }
}
}
diff --git a/Blog.Core.Model/Models/Topic.cs b/Blog.Core.Model/Models/Topic.cs
index 16bf7dad..e57bd561 100644
--- a/Blog.Core.Model/Models/Topic.cs
+++ b/Blog.Core.Model/Models/Topic.cs
@@ -7,7 +7,7 @@ namespace Blog.Core.Model.Models
///
/// Tibug 类别
///
- public class Topic : RootEntityTkey
+ public class Topic : RootEntityTkey
{
public Topic()
{
diff --git a/Blog.Core.Model/Models/TopicDetail.cs b/Blog.Core.Model/Models/TopicDetail.cs
index 87e16ebf..1a98f3af 100644
--- a/Blog.Core.Model/Models/TopicDetail.cs
+++ b/Blog.Core.Model/Models/TopicDetail.cs
@@ -6,7 +6,7 @@ namespace Blog.Core.Model.Models
///
/// Tibug 博文
///
- public class TopicDetail : TopicDetailRoot
+ public class TopicDetail : TopicDetailRoot
{
public TopicDetail()
{
diff --git a/Blog.Core.Model/Models/UserRole.cs b/Blog.Core.Model/Models/UserRole.cs
index 996eea2c..7ed9c6be 100644
--- a/Blog.Core.Model/Models/UserRole.cs
+++ b/Blog.Core.Model/Models/UserRole.cs
@@ -6,11 +6,11 @@ namespace Blog.Core.Model.Models
///
/// 用户跟角色关联表
///
- public class UserRole : UserRoleRoot
+ public class UserRole : UserRoleRoot
{
public UserRole() { }
- public UserRole(int uid, int rid)
+ public UserRole(long uid, long rid)
{
UserId = uid;
RoleId = rid;
@@ -31,7 +31,7 @@ public UserRole(int uid, int rid)
/// 创建ID
///
[SugarColumn(IsNullable = true)]
- public int? CreateId { get; set; }
+ public long? CreateId { get; set; }
///
/// 创建者
///
diff --git a/Blog.Core.Model/Models/sysUserInfo.cs b/Blog.Core.Model/Models/sysUserInfo.cs
index 366b2291..2a417a16 100644
--- a/Blog.Core.Model/Models/sysUserInfo.cs
+++ b/Blog.Core.Model/Models/sysUserInfo.cs
@@ -9,7 +9,7 @@ namespace Blog.Core.Model.Models
///
//[SugarTable("SysUserInfo")]
[SugarTable("SysUserInfo", "用户表")] //('数据库表名','数据库表备注')
- public class SysUserInfo : SysUserInfoRoot
+ public class SysUserInfo : SysUserInfoRoot
{
public SysUserInfo()
{
@@ -133,7 +133,7 @@ public SysUserInfo(string loginName, string loginPWD)
public List RoleNames { get; set; }
[SugarColumn(IsIgnore = true)]
- public List Dids { get; set; }
+ public List Dids { get; set; }
[SugarColumn(IsIgnore = true)]
public string DepartmentName { get; set; }
diff --git a/Blog.Core.Model/ViewModels/BlogViewModels.cs b/Blog.Core.Model/ViewModels/BlogViewModels.cs
index f959270c..411a8ef7 100644
--- a/Blog.Core.Model/ViewModels/BlogViewModels.cs
+++ b/Blog.Core.Model/ViewModels/BlogViewModels.cs
@@ -34,7 +34,7 @@ public class BlogViewModels
///
/// 上一篇id
///
- public int previousID { get; set; }
+ public long previousID { get; set; }
///
/// 下一篇
@@ -44,7 +44,7 @@ public class BlogViewModels
///
/// 下一篇id
///
- public int nextID { get; set; }
+ public long nextID { get; set; }
/// 类别
///
diff --git a/Blog.Core.Repository/IRoleModulePermissionRepository.cs b/Blog.Core.Repository/IRoleModulePermissionRepository.cs
index c66448f0..9ba3d4ed 100644
--- a/Blog.Core.Repository/IRoleModulePermissionRepository.cs
+++ b/Blog.Core.Repository/IRoleModulePermissionRepository.cs
@@ -19,6 +19,6 @@ public interface IRoleModulePermissionRepository : IBaseRepository菜单主键
/// 接口主键
///
- Task UpdateModuleId(int permissionId, int moduleId);
+ Task UpdateModuleId(long permissionId, long moduleId);
}
}
diff --git a/Blog.Core.Repository/RoleModulePermissionRepository.cs b/Blog.Core.Repository/RoleModulePermissionRepository.cs
index 1cb21ebf..9438ff50 100644
--- a/Blog.Core.Repository/RoleModulePermissionRepository.cs
+++ b/Blog.Core.Repository/RoleModulePermissionRepository.cs
@@ -99,7 +99,7 @@ public async Task> GetRMPMapsPage()
/// 菜单主键
/// 接口主键
///
- public async Task UpdateModuleId(int permissionId, int moduleId)
+ public async Task UpdateModuleId(long permissionId, long moduleId)
{
await Db.Updateable(it => it.ModuleId == moduleId).Where(
it => it.PermissionId == permissionId).ExecuteCommandAsync();
diff --git a/Blog.Core.Services/RoleModulePermissionServices.cs b/Blog.Core.Services/RoleModulePermissionServices.cs
index c0248e17..d3834f89 100644
--- a/Blog.Core.Services/RoleModulePermissionServices.cs
+++ b/Blog.Core.Services/RoleModulePermissionServices.cs
@@ -83,7 +83,7 @@ public async Task> GetRMPMaps()
/// 菜单主键
/// 接口主键
///
- public async Task UpdateModuleId(int permissionId, int moduleId)
+ public async Task UpdateModuleId(long permissionId, long moduleId)
{
await _dal.UpdateModuleId(permissionId, moduleId);
}
From 0ed67675a6bbab5a1b997ed9ea002f60aa3fde32 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Fri, 31 Mar 2023 22:02:30 +0800
Subject: [PATCH 047/190] =?UTF-8?q?=E6=9D=83=E9=99=90=E5=88=86=E9=85=8D?=
=?UTF-8?q?=E4=BF=9D=E5=AD=98=E9=80=BB=E8=BE=91=E4=BC=98=E5=8C=96=20sqlsug?=
=?UTF-8?q?arAop=E9=80=BB=E8=BE=91=E5=AE=8C=E5=96=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.xml | 3 +-
.../Controllers/PermissionController.cs | 79 +++++++++----------
Blog.Core.Common/DB/Aop/SqlsugarAop.cs | 41 ++++++++++
3 files changed, 81 insertions(+), 42 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index c0b52222..79325e37 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -361,7 +361,7 @@
菜单管理
-
+
构造函数
@@ -369,6 +369,7 @@
+
diff --git a/Blog.Core.Api/Controllers/PermissionController.cs b/Blog.Core.Api/Controllers/PermissionController.cs
index 9277a36b..f4889c73 100644
--- a/Blog.Core.Api/Controllers/PermissionController.cs
+++ b/Blog.Core.Api/Controllers/PermissionController.cs
@@ -6,6 +6,8 @@
using Blog.Core.IServices;
using Blog.Core.Model;
using Blog.Core.Model.Models;
+using Blog.Core.Repository.UnitOfWorks;
+using Blog.Core.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
@@ -21,6 +23,7 @@ namespace Blog.Core.Controllers
[Authorize(Permissions.Name)]
public class PermissionController : BaseApiController
{
+ readonly IUnitOfWorkManage _unitOfWorkManage;
readonly IPermissionServices _permissionServices;
readonly IModuleServices _moduleServices;
readonly IRoleModulePermissionServices _roleModulePermissionServices;
@@ -37,16 +40,19 @@ public class PermissionController : BaseApiController
///
///
///
+ ///
///
///
///
///
public PermissionController(IPermissionServices permissionServices, IModuleServices moduleServices,
IRoleModulePermissionServices roleModulePermissionServices, IUserRoleServices userRoleServices,
+ IUnitOfWorkManage unitOfWorkManage,
IHttpClientFactory httpClientFactory,
IHttpContextAccessor httpContext, IUser user, PermissionRequirement requirement)
{
_permissionServices = permissionServices;
+ _unitOfWorkManage = unitOfWorkManage;
_moduleServices = moduleServices;
_roleModulePermissionServices = roleModulePermissionServices;
_userRoleServices = userRoleServices;
@@ -239,25 +245,24 @@ public async Task> Post([FromBody] Permission permission)
///
[HttpPost]
public async Task> Assign([FromBody] AssignView assignView)
- {
- var data = new MessageModel();
-
-
+ {
if (assignView.rid > 0)
{
- data.success = true;
-
- var roleModulePermissions = await _roleModulePermissionServices.Query(d => d.RoleId == assignView.rid);
+ //开启事务
+ try
+ {
+ var old_rmps = await _roleModulePermissionServices.Query(d => d.RoleId == assignView.rid);
- var remove = roleModulePermissions.Where(d => !assignView.pids.Contains(d.PermissionId.ObjToInt())).Select(c => (object)c.Id);
- data.success &= remove.Any() ? await _roleModulePermissionServices.DeleteByIds(remove.ToArray()) : true;
+ _unitOfWorkManage.BeginTran();
+ await _permissionServices.Db.Deleteable(t => t.RoleId == assignView.rid).ExecuteCommandAsync();
+ var permissions = await _permissionServices.Query(d => d.IsDeleted == false);
- foreach (var item in assignView.pids)
- {
- var rmpitem = roleModulePermissions.Where(d => d.PermissionId == item);
- var moduleid = (await _permissionServices.Query(p => p.Id == item)).FirstOrDefault()?.Mid;
- if (!rmpitem.Any())
+ List new_rmps = new List();
+ var nowTime = _permissionServices.Db.GetDate();
+ foreach (var item in assignView.pids)
{
+ var moduleid = permissions.Find(p => p.Id == item)?.Mid;
+ var find_old_rmps = old_rmps.Find(p => p.PermissionId == item);
RoleModulePermission roleModulePermission = new RoleModulePermission()
{
@@ -265,39 +270,31 @@ public async Task> Assign([FromBody] AssignView assignView)
RoleId = assignView.rid,
ModuleId = moduleid.ObjToInt(),
PermissionId = item,
- };
-
+ CreateId = find_old_rmps == null ? _user.ID : find_old_rmps.CreateId,
+ CreateBy = find_old_rmps == null ? _user.Name : find_old_rmps.CreateBy,
+ CreateTime = find_old_rmps == null ? nowTime : find_old_rmps.CreateTime,
+ ModifyId = _user.ID,
+ ModifyBy = _user.Name,
+ ModifyTime = nowTime
- roleModulePermission.CreateId = _user.ID;
- roleModulePermission.CreateBy = _user.Name;
-
- data.success &= (await _roleModulePermissionServices.Add(roleModulePermission)) > 0;
-
- }
- else
- {
- foreach (var role in rmpitem)
- {
- if (!role.ModuleId.Equals(moduleid))
- {
- role.ModuleId = moduleid.Value;
- await _roleModulePermissionServices.Update(role, new List { "ModuleId" });
- }
- }
+ };
+ new_rmps.Add(roleModulePermission);
}
+ if(new_rmps.Count>0) await _roleModulePermissionServices.Add(new_rmps);
+ _unitOfWorkManage.CommitTran();
}
-
- if (data.success)
+ catch (Exception)
{
- _requirement.Permissions.Clear();
- data.response = "";
- data.msg = "保存成功";
+ _unitOfWorkManage.RollbackTran();
+ throw;
}
-
+ _requirement.Permissions.Clear();
+ return Success("保存成功");
}
-
-
- return data;
+ else
+ {
+ return Failed("请选择要操作的角色");
+ }
}
diff --git a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
index c1417a5a..c70d9283 100644
--- a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
+++ b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
@@ -1,6 +1,7 @@
using Blog.Core.Model;
using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Model.Tenants;
+using NetTaste;
using SqlSugar;
using System;
@@ -69,6 +70,46 @@ public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
}
}
}
+ else
+ {
+ //兼容以前的表
+ var getType = entityInfo.EntityValue.GetType();
+
+
+ switch (entityInfo.OperationType)
+ {
+
+ case DataFilterType.InsertByObject:
+ var dyCreateBy = getType.GetProperty("CreateBy");
+ var dyCreateId = getType.GetProperty("CreateId");
+ var dyCreateTime = getType.GetProperty("CreateTime");
+
+ if (App.User?.ID > 0 && dyCreateBy != null && dyCreateBy.GetValue(entityInfo.EntityValue) == null)
+ dyCreateBy.SetValue(entityInfo.EntityValue, App.User.Name);
+
+ if (App.User?.ID > 0 && dyCreateId != null && dyCreateId.GetValue(entityInfo.EntityValue) == null)
+ dyCreateId.SetValue(entityInfo.EntityValue, App.User.ID);
+
+ if (dyCreateTime != null && (DateTime)dyCreateTime.GetValue(entityInfo.EntityValue) == DateTime.MinValue)
+ dyCreateTime.SetValue(entityInfo.EntityValue, DateTime.Now);
+
+ break;
+ case DataFilterType.UpdateByObject:
+ var dyModifyBy = getType.GetProperty("ModifyBy");
+ var dyModifyId = getType.GetProperty("ModifyId");
+ var dyModifyTime = getType.GetProperty("ModifyTime");
+
+ if (App.User?.ID > 0 && dyModifyBy != null)
+ dyModifyBy.SetValue(entityInfo.EntityValue, App.User.Name);
+
+ if (App.User?.ID > 0 && dyModifyId != null)
+ dyModifyId.SetValue(entityInfo.EntityValue, App.User.ID);
+
+ if (dyModifyTime != null)
+ dyModifyTime.SetValue(entityInfo.EntityValue, DateTime.Now);
+ break;
+ }
+ }
}
private static string GetWholeSql(SugarParameter[] paramArr, string sql)
From 3c0d9f977cc03da275ba7d32a4f27e083b947ce3 Mon Sep 17 00:00:00 2001
From: hudingwen <765472804@qq.com>
Date: Sat, 1 Apr 2023 21:09:47 +0800
Subject: [PATCH 048/190] =?UTF-8?q?=E6=B7=BB=E5=8A=A0update=20list?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.IServices/BASE/IBaseServices.cs | 1 +
Blog.Core.Repository/BASE/BaseRepository.cs | 9 +++++++++
Blog.Core.Repository/BASE/IBaseRepository.cs | 6 ++++++
Blog.Core.Services/BASE/BaseServices.cs | 9 +++++++++
4 files changed, 25 insertions(+)
diff --git a/Blog.Core.IServices/BASE/IBaseServices.cs b/Blog.Core.IServices/BASE/IBaseServices.cs
index 4091b978..b491614f 100644
--- a/Blog.Core.IServices/BASE/IBaseServices.cs
+++ b/Blog.Core.IServices/BASE/IBaseServices.cs
@@ -27,6 +27,7 @@ public interface IBaseServices where TEntity : class
Task DeleteByIds(object[] ids);
Task Update(TEntity model);
+ Task Update(List model);
Task Update(TEntity entity, string where);
Task Update(object operateAnonymousObjects);
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index 3048baa8..9ef11ecd 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -170,6 +170,15 @@ public async Task Update(TEntity entity)
//这种方式会以主键为条件
return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
}
+ ///
+ /// 更新实体数据
+ ///
+ /// 博文实体类
+ ///
+ public async Task Update(List entity)
+ {
+ return await _db.Updateable(entity).ExecuteCommandHasChangeAsync();
+ }
public async Task Update(TEntity entity, string where)
{
diff --git a/Blog.Core.Repository/BASE/IBaseRepository.cs b/Blog.Core.Repository/BASE/IBaseRepository.cs
index 5f70a4be..8ef05c1e 100644
--- a/Blog.Core.Repository/BASE/IBaseRepository.cs
+++ b/Blog.Core.Repository/BASE/IBaseRepository.cs
@@ -69,6 +69,12 @@ public interface IBaseRepository where TEntity : class
///
///
Task Update(TEntity model);
+ ///
+ /// 更新model
+ ///
+ ///
+ ///
+ Task Update(List model);
///
/// 根据model,更新,带where条件
diff --git a/Blog.Core.Services/BASE/BaseServices.cs b/Blog.Core.Services/BASE/BaseServices.cs
index 7ee55eb1..14f69636 100644
--- a/Blog.Core.Services/BASE/BaseServices.cs
+++ b/Blog.Core.Services/BASE/BaseServices.cs
@@ -80,6 +80,15 @@ public async Task Update(TEntity entity)
{
return await BaseDal.Update(entity);
}
+ ///
+ /// 更新实体数据
+ ///
+ /// 博文实体类
+ ///
+ public async Task Update(List entity)
+ {
+ return await BaseDal.Update(entity);
+ }
public async Task Update(TEntity entity, string where)
{
From f785d507704275c104a61e8793548644084983ed Mon Sep 17 00:00:00 2001
From: "Lemon.NoCry" <773596523@qq.com>
Date: Sat, 1 Apr 2023 21:29:34 +0800
Subject: [PATCH 049/190] =?UTF-8?q?=F0=9F=8E=A8=20=E4=BC=98=E5=8C=96?=
=?UTF-8?q?=E9=9B=AA=E8=8A=B1id=E4=BD=BF=E7=94=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Blog.Core.Api/Blog.Core.Model.xml | 5 ----
.../Controllers/PermissionController.cs | 4 +--
Blog.Core.Common/DB/Aop/SqlsugarAop.cs | 15 ++++------
Blog.Core.IServices/BASE/IBaseServices.cs | 4 +--
Blog.Core.Model/Models/RootTkey/BaseEntity.cs | 8 +-----
Blog.Core.Repository/BASE/BaseRepository.cs | 28 +++++++++++--------
Blog.Core.Repository/BASE/IBaseRepository.cs | 4 +--
Blog.Core.Services/BASE/BaseServices.cs | 11 ++++++--
8 files changed, 37 insertions(+), 42 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.Model.xml b/Blog.Core.Api/Blog.Core.Model.xml
index fe62d8e2..79666d28 100644
--- a/Blog.Core.Api/Blog.Core.Model.xml
+++ b/Blog.Core.Api/Blog.Core.Model.xml
@@ -832,11 +832,6 @@
修改时间
-
-
- 雪花Id
-
-
状态
diff --git a/Blog.Core.Api/Controllers/PermissionController.cs b/Blog.Core.Api/Controllers/PermissionController.cs
index f4889c73..059e9b18 100644
--- a/Blog.Core.Api/Controllers/PermissionController.cs
+++ b/Blog.Core.Api/Controllers/PermissionController.cs
@@ -754,11 +754,11 @@ public async Task>> MigratePermission(string actio
List modules = await _moduleServices.Query(d => d.LinkUrl != null && d.LinkUrl.ToLower() == item.Module.LinkUrl);
if (!modules.Any())
{
- int mid = await _moduleServices.Add(item.Module);
+ var mid = await _moduleServices.Add(item.Module);
if (mid > 0)
{
item.Mid = mid;
- int permissionid = await _permissionServices.Add(item);
+ var permissionid = await _permissionServices.Add(item);
}
}
diff --git a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
index c70d9283..9ab494a4 100644
--- a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
+++ b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
@@ -1,7 +1,6 @@
using Blog.Core.Model;
using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Model.Tenants;
-using NetTaste;
using SqlSugar;
using System;
@@ -11,13 +10,6 @@ public static class SqlSugarAop
{
public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
{
- if (entityInfo.EntityValue is BaseEntity root)
- {
- if (root.Id == 0)
- {
- root.Id = SnowFlakeSingle.Instance.NextId();
- }
- }
if (entityInfo.EntityValue is RootEntityTkey rootEntity)
{
if (rootEntity.Id == 0)
@@ -73,12 +65,15 @@ public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
else
{
//兼容以前的表
- var getType = entityInfo.EntityValue.GetType();
+ //这里要小心 在AOP里用反射 数据量多性能就会有问题
+ //要么都统一使用基类
+ //要么考虑老的表没必要兼容老的表
+ //
+ var getType = entityInfo.EntityValue.GetType();
switch (entityInfo.OperationType)
{
-
case DataFilterType.InsertByObject:
var dyCreateBy = getType.GetProperty("CreateBy");
var dyCreateId = getType.GetProperty("CreateId");
diff --git a/Blog.Core.IServices/BASE/IBaseServices.cs b/Blog.Core.IServices/BASE/IBaseServices.cs
index 4091b978..21f1afb4 100644
--- a/Blog.Core.IServices/BASE/IBaseServices.cs
+++ b/Blog.Core.IServices/BASE/IBaseServices.cs
@@ -16,9 +16,9 @@ public interface IBaseServices where TEntity : class
Task QueryById(object objId, bool blnUseCache = false);
Task> QueryByIDs(object[] lstIds);
- Task Add(TEntity model);
+ Task Add(TEntity model);
- Task Add(List listEntity);
+ Task> Add(List listEntity);
Task DeleteById(object id);
diff --git a/Blog.Core.Model/Models/RootTkey/BaseEntity.cs b/Blog.Core.Model/Models/RootTkey/BaseEntity.cs
index efbde8fd..b6dabe54 100644
--- a/Blog.Core.Model/Models/RootTkey/BaseEntity.cs
+++ b/Blog.Core.Model/Models/RootTkey/BaseEntity.cs
@@ -4,14 +4,8 @@
namespace Blog.Core.Model.Models.RootTkey;
-public class BaseEntity : IDeleteFilter
+public class BaseEntity : RootEntityTkey, IDeleteFilter
{
- ///
- /// 雪花Id
- ///
- [SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = false)]
- public long Id { get; set; }
-
#region 数据状态管理
///
diff --git a/Blog.Core.Repository/BASE/BaseRepository.cs b/Blog.Core.Repository/BASE/BaseRepository.cs
index 3048baa8..e808690d 100644
--- a/Blog.Core.Repository/BASE/BaseRepository.cs
+++ b/Blog.Core.Repository/BASE/BaseRepository.cs
@@ -114,7 +114,7 @@ public async Task> QueryByIDs(object[] lstIds)
///
/// 博文实体类
///
- public async Task Add(TEntity entity)
+ public async Task Add(TEntity entity)
{
//var i = await Task.Run(() => _db.Insertable(entity).ExecuteReturnBigIdentity());
////返回的i是long类型,这里你可以根据你的业务需要进行处理
@@ -125,7 +125,7 @@ public async Task Add(TEntity entity)
//这里你可以返回TEntity,这样的话就可以获取id值,无论主键是什么类型
//var return3 = await insert.ExecuteReturnEntityAsync();
- return await insert.ExecuteReturnIdentityAsync();
+ return await insert.ExecuteReturnSnowflakeIdAsync();
}
///
@@ -134,16 +134,16 @@ public async Task Add(TEntity entity)
/// 实体类
/// 指定只插入列
/// 返回自增量列
- public async Task Add(TEntity entity, Expression> insertColumns = null)
+ public async Task Add(TEntity entity, Expression> insertColumns = null)
{
var insert = _db.Insertable(entity);
if (insertColumns == null)
{
- return await insert.ExecuteReturnIdentityAsync();
+ return await insert.ExecuteReturnSnowflakeIdAsync();
}
else
{
- return await insert.InsertColumns(insertColumns).ExecuteReturnIdentityAsync();
+ return await insert.InsertColumns(insertColumns).ExecuteReturnSnowflakeIdAsync();
}
}
@@ -152,9 +152,9 @@ public async Task Add(TEntity entity, Expression> ins
///
/// 实体集合
/// 影响行数
- public async Task Add(List listEntity)
+ public async Task> Add(List listEntity)
{
- return await _db.Insertable(listEntity.ToArray()).ExecuteCommandAsync();
+ return await _db.Insertable(listEntity.ToArray()).ExecuteReturnSnowflakeIdListAsync();
}
///
@@ -557,7 +557,9 @@ public async Task> QueryTabsPage(
// groupName = s.groupName,
// jobName = s.jobName
// }, exp, s => new { s.uID, s.uRealName, s.groupName, s.jobName }, model.currentPage, model.pageSize, model.orderField + " " + model.orderType);
+
#region Split分表基础接口 (基础CRUD)
+
///
/// 分页查询[使用版本,其他分页未测试]
///
@@ -573,9 +575,10 @@ public async Task> QueryPageSplit(Expression(pageIndex, totalCount, pageSize, list);
+ var data = new PageModel(pageIndex, totalCount, pageSize, list);
return data;
}
+
///
/// 写入实体数据
///
@@ -599,24 +602,26 @@ public async Task UpdateSplit(TEntity entity, DateTime dateTime)
//return await _db.Updateable(entity).SplitTable().ExecuteCommandAsync();//,SplitTable不能少
//精准找单个表
- var tableName = _db.SplitHelper().GetTableName(dateTime);//根据时间获取表名
+ var tableName = _db.SplitHelper().GetTableName(dateTime); //根据时间获取表名
return await _db.Updateable(entity).AS(tableName).ExecuteCommandHasChangeAsync();
}
+
///
/// 删除数据
///
///
///
///
- public async Task DeleteSplit(TEntity entity,DateTime dateTime)
+ public async Task DeleteSplit(TEntity entity, DateTime dateTime)
{
////直接根据实体集合删除 (全自动 找表插入),返回受影响数
//return await _db.Deleteable(entity).SplitTable().ExecuteCommandAsync();//,SplitTable不能少
//精准找单个表
- var tableName = _db.SplitHelper().GetTableName(dateTime);//根据时间获取表名
+ var tableName = _db.SplitHelper().GetTableName(dateTime); //根据时间获取表名
return await _db.Deleteable().AS(tableName).Where(entity).ExecuteCommandHasChangeAsync();
}
+
///
/// 根据ID查找数据
///
@@ -626,6 +631,7 @@ public async Task QueryByIdSplit(object objId)
{
return await _db.Queryable().In(objId).SplitTable(tabs => tabs).SingleAsync();
}
+
#endregion
}
}
\ No newline at end of file
diff --git a/Blog.Core.Repository/BASE/IBaseRepository.cs b/Blog.Core.Repository/BASE/IBaseRepository.cs
index 5f70a4be..e3e6553b 100644
--- a/Blog.Core.Repository/BASE/IBaseRepository.cs
+++ b/Blog.Core.Repository/BASE/IBaseRepository.cs
@@ -33,14 +33,14 @@ public interface IBaseRepository where TEntity : class
///
///
///
- Task Add(TEntity model);
+ Task Add(TEntity model);
///
/// 批量添加
///
///
///
- Task Add(List listEntity);
+ Task> Add(List listEntity);
///
/// 根据id 删除某一实体
diff --git a/Blog.Core.Services/BASE/BaseServices.cs b/Blog.Core.Services/BASE/BaseServices.cs
index 7ee55eb1..809890fb 100644
--- a/Blog.Core.Services/BASE/BaseServices.cs
+++ b/Blog.Core.Services/BASE/BaseServices.cs
@@ -56,7 +56,7 @@ public async Task> QueryByIDs(object[] lstIds)
///
/// 博文实体类
///
- public async Task Add(TEntity entity)
+ public async Task Add(TEntity entity)
{
return await BaseDal.Add(entity);
}
@@ -66,7 +66,7 @@ public async Task Add(TEntity entity)
///
/// 实体集合
/// 影响行数
- public async Task Add(List listEntity)
+ public async Task> Add(List listEntity)
{
return await BaseDal.Add(listEntity);
}
@@ -332,11 +332,14 @@ public async Task> QueryPage(PaginationModel pagination)
var express = DynamicLinqFactory.CreateLambda(pagination.Conditions);
return await QueryPage(express, pagination.PageIndex, pagination.PageSize, pagination.OrderByFileds);
}
+
#region 分表
+
public async Task> AddSplit(TEntity entity)
{
return await BaseDal.AddSplit(entity);
}
+
public async Task UpdateSplit(TEntity entity, DateTime dateTime)
{
return await BaseDal.UpdateSplit(entity, dateTime);
@@ -356,12 +359,14 @@ public async Task QueryByIdSplit(object objId)
{
return await BaseDal.QueryByIdSplit(objId);
}
- public async Task> QueryPageSplit(Expression> whereExpression, DateTime beginTime, DateTime endTime,
+
+ public async Task> QueryPageSplit(Expression> whereExpression, DateTime beginTime, DateTime endTime,
int pageIndex = 1, int pageSize = 20, string orderByFields = null)
{
return await BaseDal.QueryPageSplit(whereExpression, beginTime, endTime,
pageIndex, pageSize, orderByFields);
}
+
#endregion
}
}
\ No newline at end of file
From 0d2a95e0e94553140f550fc4606ef88c8efab824 Mon Sep 17 00:00:00 2001
From: LemonNoCry <773596523@qq.com>
Date: Sat, 1 Apr 2023 23:25:56 +0800
Subject: [PATCH 050/190] =?UTF-8?q?=E2=9C=A8=20=E5=88=9D=E6=AD=A5=E8=B0=83?=
=?UTF-8?q?=E6=95=B4Serilog?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 2 +
Blog.Core.Api/Blog.Core.Api.csproj | 6 +-
Blog.Core.Api/Blog.Core.xml | 2 +-
Blog.Core.Api/Controllers/ValuesController.cs | 2 +-
Blog.Core.Api/Filter/GlobalExceptionFilter.cs | 6 +-
Blog.Core.Api/Log4net.config | 364 -----------
Blog.Core.Api/Program.cs | 112 ++--
Blog.Core.Api/Startup.cs | 1 -
Blog.Core.Api/appsettings.json | 601 +++++++++---------
Blog.Core.Api/skyapm.json | 2 +-
Blog.Core.Common/App.cs | 63 +-
Blog.Core.Common/Blog.Core.Common.csproj | 14 +-
Blog.Core.Common/Const/SqlSugarConst.cs | 9 +
Blog.Core.Common/Core/InternalApp.cs | 25 +-
Blog.Core.Common/DB/Aop/SqlsugarAop.cs | 30 +-
Blog.Core.Common/DB/BaseDBConfig.cs | 3 +-
Blog.Core.Common/Helper/RecursionHelper.cs | 67 +-
.../{ => Https}/HttpPolly/HttpPollyHelper.cs | 20 +-
.../{ => Https}/HttpPolly/IHttpPollyHelper.cs | 2 +-
Blog.Core.Common/Https/RequestIpUtility.cs | 83 +++
Blog.Core.Common/Hubs/ChatHub.cs | 3 +-
.../LogHelper/LogContextExtension.cs | 42 ++
.../LogHelper/LogContextStatic.cs | 42 ++
Blog.Core.Common/LogHelper/LogLock.cs | 170 ++---
.../Blog.Core.Extensions.csproj | 3 +-
.../Middlewares/ExceptionHandlerMiddleware.cs | 9 +-
.../Middlewares/IpLimitMiddleware.cs | 7 +-
.../Middlewares/IpLogMiddleware.cs | 7 +-
.../Middlewares/MiniProfilerMiddleware.cs | 7 +-
.../Middlewares/SignalRSendMiddleware.cs | 1 +
.../Middlewares/SwaggerMiddleware.cs | 21 +-
.../ServiceExtensions/AppConfigSetup.cs | 38 +-
.../AutofacModuleRegister.cs | 20 +-
.../ServiceExtensions/HttpPollySetup.cs | 2 +-
.../ServiceExtensions/SerilogSetup.cs | 37 ++
.../ServiceExtensions/SqlsugarSetup.cs | 45 +-
.../ServiceExtensions/SwaggerSetup.cs | 26 +-
.../Blog.Core.Serilog.Es.csproj | 2 +-
Blog.Core.Serilog/Blog.Core.Serilog.csproj | 13 +
.../LoggerConfigurationExtensions.cs | 121 ++++
.../Utility/SerilogRequestUtility.cs | 34 +
.../Jobs/Job_AccessTrendLog_Quartz.cs | 4 +-
.../QuartzNet/Jobs/Job_OperateLog_Quartz.cs | 17 +-
.../DependencyInjection/DI_Test.cs | 1 -
Blog.Core.sln | 6 +
45 files changed, 1137 insertions(+), 955 deletions(-)
delete mode 100644 Blog.Core.Api/Log4net.config
create mode 100644 Blog.Core.Common/Const/SqlSugarConst.cs
rename Blog.Core.Common/{ => Https}/HttpPolly/HttpPollyHelper.cs (98%)
rename Blog.Core.Common/{ => Https}/HttpPolly/IHttpPollyHelper.cs (96%)
create mode 100644 Blog.Core.Common/Https/RequestIpUtility.cs
create mode 100644 Blog.Core.Common/LogHelper/LogContextExtension.cs
create mode 100644 Blog.Core.Common/LogHelper/LogContextStatic.cs
create mode 100644 Blog.Core.Extensions/ServiceExtensions/SerilogSetup.cs
create mode 100644 Blog.Core.Serilog/Blog.Core.Serilog.csproj
create mode 100644 Blog.Core.Serilog/Extensions/LoggerConfigurationExtensions.cs
create mode 100644 Blog.Core.Serilog/Utility/SerilogRequestUtility.cs
diff --git a/.gitignore b/.gitignore
index b7645c45..4f554bea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -356,3 +356,5 @@ Blog.Core/Blog.Core*.xml
Blog.Core.Api/WMBlog.db
Blog.Core.Api/wwwroot/ui/
*.db
+/Blog.Core.Api/WMBlog.db-journal
+Logs
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 77d681f1..3bf64399 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -26,21 +26,25 @@
+
+
+
+
@@ -51,8 +55,6 @@
-
-
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 89cb3213..488903a0 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -760,7 +760,7 @@
Values控制器
-
+
ValuesController
diff --git a/Blog.Core.Api/Controllers/ValuesController.cs b/Blog.Core.Api/Controllers/ValuesController.cs
index 1347ca16..677eb138 100644
--- a/Blog.Core.Api/Controllers/ValuesController.cs
+++ b/Blog.Core.Api/Controllers/ValuesController.cs
@@ -1,7 +1,7 @@
using AutoMapper;
using Blog.Core.Common;
using Blog.Core.Common.HttpContextUser;
-using Blog.Core.Common.HttpPolly;
+using Blog.Core.Common.Https.HttpPolly;
using Blog.Core.Common.WebApiClients.HttpApis;
using Blog.Core.EventBus;
using Blog.Core.EventBus.EventHandling;
diff --git a/Blog.Core.Api/Filter/GlobalExceptionFilter.cs b/Blog.Core.Api/Filter/GlobalExceptionFilter.cs
index da119a6e..44c6124c 100644
--- a/Blog.Core.Api/Filter/GlobalExceptionFilter.cs
+++ b/Blog.Core.Api/Filter/GlobalExceptionFilter.cs
@@ -3,14 +3,10 @@
using Blog.Core.Common.LogHelper;
using Blog.Core.Hubs;
using Blog.Core.Model;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.SignalR;
-using Microsoft.Extensions.Logging;
using StackExchange.Profiling;
-using System;
namespace Blog.Core.Filter
{
@@ -54,7 +50,7 @@ public void OnException(ExceptionContext context)
MiniProfiler.Current.CustomTiming("Errors:", json.msg);
- //采用log4net 进行错误日志记录
+ //进行错误日志记录
_loggerHelper.LogError(json.msg + WriteLog(json.msg, context.Exception));
if (AppSettings.app(new string[] { "Middleware", "SignalRSendLog", "Enabled" }).ObjToBool())
{
diff --git a/Blog.Core.Api/Log4net.config b/Blog.Core.Api/Log4net.config
deleted file mode 100644
index 61bd3739..00000000
--- a/Blog.Core.Api/Log4net.config
+++ /dev/null
@@ -1,364 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Blog.Core.Api/Program.cs b/Blog.Core.Api/Program.cs
index f5223beb..f7790a8c 100644
--- a/Blog.Core.Api/Program.cs
+++ b/Blog.Core.Api/Program.cs
@@ -1,20 +1,16 @@
// 以下为asp.net 6.0的写法,如果用5.0,请看Program.five.cs文件
-using System.IdentityModel.Tokens.Jwt;
-using System.Reflection;
-using System.Text;
+
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Blog.Core;
using Blog.Core.Common;
using Blog.Core.Common.Core;
-using Blog.Core.Common.LogHelper;
using Blog.Core.Extensions;
using Blog.Core.Extensions.Apollo;
using Blog.Core.Extensions.Middlewares;
+using Blog.Core.Extensions.ServiceExtensions;
using Blog.Core.Filter;
using Blog.Core.Hubs;
-using Blog.Core.IServices;
-using Blog.Core.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Server.Kestrel.Core;
@@ -22,34 +18,38 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
+using Serilog;
+using System.IdentityModel.Tokens.Jwt;
+using System.Reflection;
+using System.Text;
+using Blog.Core.Common.Https;
+using Blog.Core.Serilog.Utility;
var builder = WebApplication.CreateBuilder(args);
+
+
// 1、配置host与容器
builder.Host
-.UseServiceProviderFactory(new AutofacServiceProviderFactory())
-.ConfigureContainer(builder =>
-{
- builder.RegisterModule(new AutofacModuleRegister());
- builder.RegisterModule();
-})
-.ConfigureLogging((hostingContext, builder) =>
-{
- builder.AddFilter("System", LogLevel.Error);
- builder.AddFilter("Microsoft", LogLevel.Error);
- builder.SetMinimumLevel(LogLevel.Error);
- builder.AddLog4Net(Path.Combine(Directory.GetCurrentDirectory(), "Log4net.config"));
-})
-.ConfigureAppConfiguration((hostingContext, config) =>
-{
- config.Sources.Clear();
- config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
- config.AddConfigurationApollo("appsettings.apollo.json");
-});
+ .UseServiceProviderFactory(new AutofacServiceProviderFactory())
+ .ConfigureContainer(builder =>
+ {
+ builder.RegisterModule(new AutofacModuleRegister());
+ builder.RegisterModule();
+ })
+ .ConfigureAppConfiguration((hostingContext, config) =>
+ {
+ config.Sources.Clear();
+ config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: false);
+ config.AddConfigurationApollo("appsettings.apollo.json");
+ });
+builder.ConfigureApplication();
// 2、配置服务
builder.Services.AddSingleton(new AppSettings(builder.Configuration));
-builder.Services.AddSingleton(new LogLock(builder.Environment.ContentRootPath));
+
+
+
builder.Services.AddUiFilesZipSetup(builder.Environment);
Permissions.IsUseIds4 = AppSettings.app(new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool();
@@ -62,6 +62,9 @@
builder.Services.AddRedisCacheSetup();
builder.Services.AddSqlsugarSetup();
builder.Services.AddDbSetup();
+
+builder.Host.AddSerilogSetup();
+
builder.Services.AddAutoMapperSetup();
builder.Services.AddCorsSetup();
builder.Services.AddMiniProfilerSetup();
@@ -92,34 +95,34 @@
builder.Services.AddSignalR().AddNewtonsoftJsonProtocol();
builder.Services.AddScoped();
builder.Services.Configure(x => x.AllowSynchronousIO = true)
- .Configure(x => x.AllowSynchronousIO = true);
+ .Configure(x => x.AllowSynchronousIO = true);
builder.Services.AddDistributedMemoryCache();
builder.Services.AddSession();
builder.Services.AddHttpPollySetup();
builder.Services.AddControllers(o =>
-{
- o.Filters.Add(typeof(GlobalExceptionsFilter));
- //o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
- o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
-})
-.AddNewtonsoftJson(options =>
-{
- options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
- options.SerializerSettings.ContractResolver = new DefaultContractResolver();
- options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
- //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
- options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
- options.SerializerSettings.Converters.Add(new StringEnumConverter());
-})
-//.AddFluentValidation(config =>
-//{
-// //程序集方式添加验证
-// config.RegisterValidatorsFromAssemblyContaining(typeof(UserRegisterVoValidator));
-// //是否与MvcValidation共存
-// config.DisableDataAnnotationsValidation = true;
-//})
-;
+ {
+ o.Filters.Add(typeof(GlobalExceptionsFilter));
+ //o.Conventions.Insert(0, new GlobalRouteAuthorizeConvention());
+ o.Conventions.Insert(0, new GlobalRoutePrefixFilter(new RouteAttribute(RoutePrefix.Name)));
+ })
+ .AddNewtonsoftJson(options =>
+ {
+ options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+ options.SerializerSettings.ContractResolver = new DefaultContractResolver();
+ options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
+ //options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
+ options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
+ options.SerializerSettings.Converters.Add(new StringEnumConverter());
+ })
+ //.AddFluentValidation(config =>
+ //{
+ // //程序集方式添加验证
+ // config.RegisterValidatorsFromAssemblyContaining(typeof(UserRegisterVoValidator));
+ // //是否与MvcValidation共存
+ // config.DisableDataAnnotationsValidation = true;
+ //})
+ ;
builder.Services.AddEndpointsApiExplorer();
@@ -159,12 +162,23 @@
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseStatusCodePages();
+app.UseSerilogRequestLogging(options =>
+{
+ options.GetLevel = SerilogRequestUtility.GetRequestLevel;
+ options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
+ {
+ diagnosticContext.Set("RequestHost", httpContext.Request.Host.Value);
+ diagnosticContext.Set("RequestScheme", httpContext.Request.Scheme);
+ diagnosticContext.Set("RequestIp", httpContext.GetRequestIp());
+ };
+});
app.UseRouting();
if (builder.Configuration.GetValue("AppSettings:UseLoadTest"))
{
app.UseMiddleware();
}
+
app.UseAuthentication();
app.UseAuthorization();
app.UseMiniProfilerMiddleware();
diff --git a/Blog.Core.Api/Startup.cs b/Blog.Core.Api/Startup.cs
index bc1630f1..1364d6a0 100644
--- a/Blog.Core.Api/Startup.cs
+++ b/Blog.Core.Api/Startup.cs
@@ -39,7 +39,6 @@ public void ConfigureServices(IServiceCollection services)
{
// 以下code可能与文章中不一样,对代码做了封装,具体查看右侧 Extensions 文件夹.
services.AddSingleton(new AppSettings(Configuration));
- services.AddSingleton(new LogLock(Env.ContentRootPath));
services.AddUiFilesZipSetup(Env);
Permissions.IsUseIds4 = AppSettings.app(new string[] { "Startup", "IdentityServer4", "Enabled" }).ObjToBool();
diff --git a/Blog.Core.Api/appsettings.json b/Blog.Core.Api/appsettings.json
index 3c117375..c712054c 100644
--- a/Blog.Core.Api/appsettings.json
+++ b/Blog.Core.Api/appsettings.json
@@ -1,98 +1,92 @@
{
- "urls": "http://*:9291", //web服务端口,如果用IIS部署,把这个去掉
- "Logging": {
- "LogLevel": {
- "Default": "Information", //加入Default否则log4net本地写入不了日志
- "Blog.Core.AuthHelper.ApiResponseHandler": "Error"
- },
- "Debug": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Warning"
- }
- },
- "Console": {
- "IncludeScopes": false,
- "LogLevel": {
- "Default": "Warning",
- "Microsoft.Hosting.Lifetime": "Debug"
- }
- },
- "Log4Net": {
- "Name": "Blog.Core"
- }
- },
- "AllowedHosts": "*",
- "Redis": {
- "ConnectionString": "127.0.0.1:6319,password=admin"
+ "urls": "http://*:9291", //web服务端口,如果用IIS部署,把这个去掉
+ "Serilog": {
+ "MinimumLevel": {
+ "Default": "Debug",
+ "Override": {
+ "Microsoft": "Information",
+ "Microsoft.AspNetCore": "Warning",
+ "System": "Warning",
+ "System.Net.Http.HttpClient": "Warning",
+ "Hangfire": "Information",
+ "Magicodes": "Warning",
+ "DotNetCore.CAP": "Information",
+ "Savorboard.CAP": "Information",
+ "Quartz": "Information"
+ }
+ }
+ },
+ "AllowedHosts": "*",
+ "Redis": {
+ "ConnectionString": "127.0.0.1:6319,password=admin"
+ },
+ "RabbitMQ": {
+ "Enabled": false,
+ "Connection": "118.25.251.13",
+ "UserName": "",
+ "Password": "!",
+ "RetryCount": 3
+ },
+ "Kafka": {
+ "Enabled": false,
+ "Servers": "localhost:9092",
+ "Topic": "blog",
+ "GroupId": "blog-consumer",
+ "NumPartitions": 3 //主题分区数量
+ },
+ "EventBus": {
+ "Enabled": false,
+ "SubscriptionClientName": "Blog.Core"
+ },
+ "AppSettings": {
+ "RedisCachingAOP": {
+ "Enabled": false
},
- "RabbitMQ": {
- "Enabled": false,
- "Connection": "118.25.251.13",
- "UserName": "",
- "Password": "!",
- "RetryCount": 3
+ "MemoryCachingAOP": {
+ "Enabled": true
},
- "Kafka": {
- "Enabled": false,
- "Servers": "localhost:9092",
- "Topic": "blog",
- "GroupId": "blog-consumer",
- "NumPartitions": 3 //主题分区数量
+ "LogAOP": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ }
},
- "EventBus": {
- "Enabled": false,
- "SubscriptionClientName": "Blog.Core"
+ "TranAOP": {
+ "Enabled": true
},
- "AppSettings": {
- "RedisCachingAOP": {
- "Enabled": false
- },
- "MemoryCachingAOP": {
- "Enabled": true
- },
- "LogAOP": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- }
- },
- "TranAOP": {
- "Enabled": true
- },
- "SqlAOP": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": false
- },
- "LogToConsole": {
- "Enabled": true
- }
- },
- "Date": "2018-08-28",
- "SeedDBEnabled": true, //只生成表结构
- "SeedDBDataEnabled": true, //生成表,并初始化数据
- "Author": "Blog.Core",
- "SvcName": "", // /svc/blog
- "UseLoadTest": false
+ "SqlAOP": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": true
+ },
+ "LogToDB": {
+ "Enabled": false
+ },
+ "LogToConsole": {
+ "Enabled": true
+ }
},
+ "Date": "2018-08-28",
+ "SeedDBEnabled": true, //只生成表结构
+ "SeedDBDataEnabled": true, //生成表,并初始化数据
+ "Author": "Blog.Core",
+ "SvcName": "", // /svc/blog
+ "UseLoadTest": false
+ },
- // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
- // *** 单库操作,把 MutiDBEnabled 设为false ***;
- // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
- // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
-
- "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
- "MutiDBEnabled": false, //是否开启多库模式
- "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
- "DBS": [
- /*
+ // 请配置MainDB为你想要的主库的ConnId值,并设置对应的Enabled为true;
+ // *** 单库操作,把 MutiDBEnabled 设为false ***;
+ // *** 多库操作,把 MutiDBEnabled 设为true,其他的从库Enabled也为true **;
+ // 具体配置看视频:https://www.bilibili.com/video/BV1BJ411B7mn?p=6
+ //Log:日志库;
+ "MainDB": "WMBLOG_SQLITE", //当前项目的主库,所对应的连接字符串的Enabled必须为true
+ "MutiDBEnabled": true, //是否开启多库模式
+ "CQRSEnabled": false, //是否开启读写分离模式,必须是单库模式,且数据库类型一致,比如都是SqlServer
+ "DBS": [
+ /*
对应下边的 DBType
MySql = 0,
SqlServer = 1,
@@ -102,225 +96,232 @@
Dm = 5,//达梦
Kdbndp = 6,//人大金仓
*/
- {
- "ConnId": "WMBLOG_SQLITE",
- "DBType": 2,
- "Enabled": true,
- "HitRate": 50, // 值越大,优先级越高
- "Connection": "WMBlog.db" //sqlite只写数据库名就行
- },
- {
- "ConnId": "WMBLOG_MSSQL_1",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 40,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MSSQL_2",
- "DBType": 1,
- "Enabled": false,
- "HitRate": 30,
- "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
- "ProviderName": "System.Data.SqlClient"
- },
- {
- "ConnId": "WMBLOG_MYSQL",
- "DBType": 0,
- "Enabled": false,
- "HitRate": 20,
- "Connection": "server=localhost;Database=blog;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_MYSQL_2",
- "DBType": 0,
- "Enabled": false,
- "HitRate": 20,
- "Connection": "server=localhost;Database=blogcore001;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
- },
- {
- "ConnId": "WMBLOG_ORACLE",
- "DBType": 3,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
- },
- {
- "ConnId": "WMBLOG_DM",
- "DBType": 5,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
- },
- {
- "ConnId": "WMBLOG_KDBNDP",
- "DBType": 6,
- "Enabled": false,
- "HitRate": 10,
- "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
- }
- ],
- "Audience": {
- "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
- "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
- "Issuer": "Blog.Core",
- "Audience": "wr"
+ {
+ "ConnId": "WMBLOG_SQLITE",
+ "DBType": 2,
+ "Enabled": true,
+ "HitRate": 50, // 值越大,优先级越高
+ "Connection": "WMBlog.db" //sqlite只写数据库名就行
},
- "Mongo": {
- "ConnectionString": "mongodb://nosql.data",
- "Database": "BlogCoreDb"
+ {
+ "ConnId": "Log",
+ "DBType": 2,
+ "Enabled": true,
+ "HitRate": 50, // 值越大,优先级越高
+ "Connection": "WMBlogLog.db" //sqlite只写数据库名就行
},
- "Startup": {
- "Domain": "http://localhost:9291",
- "Cors": {
- "PolicyName": "CorsIpAccess", //策略名称
- "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
- // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
- // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
- "IPs": "http://127.0.0.1:2364,http://localhost:2364,http://127.0.0.1:6688,http://localhost:6688"
- },
- "AppConfigAlert": {
- "Enabled": true
- },
- "ApiName": "Blog.Core",
- "IdentityServer4": {
- "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
- "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
- "ApiName": "blog.core.api" // 资源服务器
- },
- "Authing": {
- "Enabled": false,
- "Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
- "Audience": "63d51c4205c2849803be5178",
- "JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
- },
- "RedisMq": {
- "Enabled": false //redis 消息队列
- },
- "MiniProfiler": {
- "Enabled": false //性能分析开启
- },
- "Nacos": {
- "Enabled": false //Nacos注册中心
- }
+ {
+ "ConnId": "WMBLOG_MSSQL_1",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 40,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_1;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
},
- "Middleware": {
- "RequestResponseLog": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- }
- },
- "IPLog": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- }
- },
- "RecordAccessLogs": {
- "Enabled": true,
- "LogToFile": {
- "Enabled": false
- },
- "LogToDB": {
- "Enabled": true
- },
- "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
- },
- "SignalR": {
- "Enabled": false
- },
- "SignalRSendLog": {
- "Enabled": false
- },
- "QuartzNetJob": {
- "Enabled": true
- },
- "Consul": {
- "Enabled": false
- },
- "IpRateLimit": {
- "Enabled": true
- }
+ {
+ "ConnId": "WMBLOG_MSSQL_2",
+ "DBType": 1,
+ "Enabled": false,
+ "HitRate": 30,
+ "Connection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=WMBLOG_MSSQL_2;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False",
+ "ProviderName": "System.Data.SqlClient"
},
- "IpRateLimiting": {
- "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
- "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
- "RealIpHeader": "X-Real-IP",
- "ClientIdHeader": "X-ClientId",
- "IpWhitelist": [], //白名单
- "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
- "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
- "QuotaExceededResponse": {
- "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
- "ContentType": "application/json",
- "StatusCode": 429
- },
- "HttpStatusCode": 429, //返回状态码
- "GeneralRules": [ //api规则,结尾一定要带*
- {
- "Endpoint": "*:/api/blog*",
- "Period": "1m",
- "Limit": 20
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1s",
- "Limit": 3
- },
- {
- "Endpoint": "*/api/*",
- "Period": "1m",
- "Limit": 30
- },
- {
- "Endpoint": "*/api/*",
- "Period": "12h",
- "Limit": 500
- }
- ]
-
+ {
+ "ConnId": "WMBLOG_MYSQL",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=localhost;Database=blog;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_MYSQL_2",
+ "DBType": 0,
+ "Enabled": false,
+ "HitRate": 20,
+ "Connection": "server=localhost;Database=blogcore001;Uid=root;Pwd=root;Port=3306;Allow User Variables=True;"
+ },
+ {
+ "ConnId": "WMBLOG_ORACLE",
+ "DBType": 3,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Data Source=127.0.0.1/ops;User ID=OPS;Password=123456;Persist Security Info=True;Connection Timeout=60;"
+ },
+ {
+ "ConnId": "WMBLOG_DM",
+ "DBType": 5,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "PORT=5236;DATABASE=DAMENG;HOST=localhost;PASSWORD=SYSDBA;USER ID=SYSDBA;"
+ },
+ {
+ "ConnId": "WMBLOG_KDBNDP",
+ "DBType": 6,
+ "Enabled": false,
+ "HitRate": 10,
+ "Connection": "Server=127.0.0.1;Port=54321;UID=SYSTEM;PWD=system;database=SQLSUGAR4XTEST1;"
+ }
+ ],
+ "Audience": {
+ "Secret": "sdfsdfsrty45634kkhllghtdgdfss345t678fs", //不要太短,16位+
+ "SecretFile": "C:\\my-file\\blog.core.audience.secret.txt", //安全。内容就是Secret
+ "Issuer": "Blog.Core",
+ "Audience": "wr"
+ },
+ "Mongo": {
+ "ConnectionString": "mongodb://nosql.data",
+ "Database": "BlogCoreDb"
+ },
+ "Startup": {
+ "Domain": "http://localhost:9291",
+ "Cors": {
+ "PolicyName": "CorsIpAccess", //策略名称
+ "EnableAllIPs": false, //当为true时,开放所有IP均可访问。
+ // 支持多个域名端口,注意端口号后不要带/斜杆:比如localhost:8000/,是错的
+ // 注意,http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
+ "IPs": "http://127.0.0.1:2364,http://localhost:2364,http://127.0.0.1:6688,http://localhost:6688"
+ },
+ "AppConfigAlert": {
+ "Enabled": true
+ },
+ "ApiName": "Blog.Core",
+ "IdentityServer4": {
+ "Enabled": false, // 这里默认是false,表示使用jwt,如果设置为true,则表示系统使用Ids4模式
+ "AuthorizationUrl": "http://localhost:5004", // 认证中心域名
+ "ApiName": "blog.core.api" // 资源服务器
},
- "ConsulSetting": {
- "ServiceName": "BlogCoreService",
- "ServiceIP": "localhost",
- "ServicePort": "9291",
- "ServiceHealthCheck": "/healthcheck",
- "ConsulAddress": "http://localhost:8500"
+ "Authing": {
+ "Enabled": false,
+ "Issuer": "https://uldr24esx31h-demo.authing.cn/oidc",
+ "Audience": "63d51c4205c2849803be5178",
+ "JwksUri": "https://uldr24esx31h-demo.authing.cn/oidc/.well-known/jwks.json"
},
- "PayInfo": { //建行聚合支付信息
- "MERCHANTID": "", //商户号
- "POSID": "", //柜台号
- "BRANCHID": "", //分行号
- "pubKey": "", //公钥
- "USER_ID": "", //操作员号
- "PASSWORD": "", //密码
- "OutAddress": "http://127.0.0.1:12345" //外联地址
+ "RedisMq": {
+ "Enabled": false //redis 消息队列
},
- "nacos": {
- "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
- "DefaultTimeOut": 15000, // 默认超时时间
- "Namespace": "public", // 命名空间
- "ListenInterval": 10000, // 监听的频率
- "ServiceName": "blog.Core.Api", // 服务名
- "Port": "9291", // 服务端口号
- "RegisterEnabled": true // 是否直接注册nacos
+ "MiniProfiler": {
+ "Enabled": false //性能分析开启
},
- "LogFiedOutPutConfigs": {
- "tcpAddressHost": "", // 输出elk的tcp连接地址
- "tcpAddressPort": 0, // 输出elk的tcp端口号
- "ConfigsInfo": [ // 配置的输出elk节点内容 常用语动态标识
- {
- "FiedName": "applicationName",
- "FiedValue": "Blog.Core.Api"
- }
- ]
+ "Nacos": {
+ "Enabled": false //Nacos注册中心
}
+ },
+ "Middleware": {
+ "RequestResponseLog": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ }
+ },
+ "IPLog": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ }
+ },
+ "RecordAccessLogs": {
+ "Enabled": true,
+ "LogToFile": {
+ "Enabled": false
+ },
+ "LogToDB": {
+ "Enabled": true
+ },
+ "IgnoreApis": "/api/permission/getnavigationbar,/api/monitor/getids4users,/api/monitor/getaccesslogs,/api/monitor/server,/api/monitor/getactiveusers,/api/monitor/server,"
+ },
+ "SignalR": {
+ "Enabled": false
+ },
+ "SignalRSendLog": {
+ "Enabled": false
+ },
+ "QuartzNetJob": {
+ "Enabled": true
+ },
+ "Consul": {
+ "Enabled": false
+ },
+ "IpRateLimit": {
+ "Enabled": true
+ }
+ },
+ "IpRateLimiting": {
+ "EnableEndpointRateLimiting": true, //False: globally executed, true: executed for each
+ "StackBlockedRequests": false, //False: Number of rejections should be recorded on another counter
+ "RealIpHeader": "X-Real-IP",
+ "ClientIdHeader": "X-ClientId",
+ "IpWhitelist": [], //白名单
+ "EndpointWhitelist": [ "get:/api/xxx", "*:/api/yyy" ],
+ "ClientWhitelist": [ "dev-client-1", "dev-client-2" ],
+ "QuotaExceededResponse": {
+ "Content": "{{\"status\":429,\"msg\":\"访问过于频繁,请稍后重试\",\"success\":false}}",
+ "ContentType": "application/json",
+ "StatusCode": 429
+ },
+ "HttpStatusCode": 429, //返回状态码
+ "GeneralRules": [ //api规则,结尾一定要带*
+ {
+ "Endpoint": "*:/api/blog*",
+ "Period": "1m",
+ "Limit": 20
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1s",
+ "Limit": 3
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "1m",
+ "Limit": 30
+ },
+ {
+ "Endpoint": "*/api/*",
+ "Period": "12h",
+ "Limit": 500
+ }
+ ]
+
+ },
+ "ConsulSetting": {
+ "ServiceName": "BlogCoreService",
+ "ServiceIP": "localhost",
+ "ServicePort": "9291",
+ "ServiceHealthCheck": "/healthcheck",
+ "ConsulAddress": "http://localhost:8500"
+ },
+ "PayInfo": { //建行聚合支付信息
+ "MERCHANTID": "", //商户号
+ "POSID": "", //柜台号
+ "BRANCHID": "", //分行号
+ "pubKey": "", //公钥
+ "USER_ID": "", //操作员号
+ "PASSWORD": "", //密码
+ "OutAddress": "http://127.0.0.1:12345" //外联地址
+ },
+ "nacos": {
+ "ServerAddresses": [ "http://localhost:8848" ], // nacos 连接地址
+ "DefaultTimeOut": 15000, // 默认超时时间
+ "Namespace": "public", // 命名空间
+ "ListenInterval": 10000, // 监听的频率
+ "ServiceName": "blog.Core.Api", // 服务名
+ "Port": "9291", // 服务端口号
+ "RegisterEnabled": true // 是否直接注册nacos
+ },
+ "LogFiedOutPutConfigs": {
+ "tcpAddressHost": "", // 输出elk的tcp连接地址
+ "tcpAddressPort": 0, // 输出elk的tcp端口号
+ "ConfigsInfo": [ // 配置的输出elk节点内容 常用语动态标识
+ {
+ "FiedName": "applicationName",
+ "FiedValue": "Blog.Core.Api"
+ }
+ ]
+ }
}
diff --git a/Blog.Core.Api/skyapm.json b/Blog.Core.Api/skyapm.json
index cd5ed0ee..cdb0e606 100644
--- a/Blog.Core.Api/skyapm.json
+++ b/Blog.Core.Api/skyapm.json
@@ -11,7 +11,7 @@
},
"Logging": {
"Level": "Information",
- "FilePath": "Log/skyapm-{Date}.log"
+ "FilePath": "Logs/Skyapm/skyapm-{Date}.log"
},
"Transport": {
"Interval": 3000,
diff --git a/Blog.Core.Common/App.cs b/Blog.Core.Common/App.cs
index 008aea5d..c2e2e706 100644
--- a/Blog.Core.Common/App.cs
+++ b/Blog.Core.Common/App.cs
@@ -1,14 +1,24 @@
using Blog.Core.Common.Core;
using Blog.Core.Common.HttpContextUser;
+using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Options;
using System;
+using System.Linq;
namespace Blog.Core.Common;
public class App
{
- public static IServiceProvider RootServices => InternalApp.RootServices ;
+ public static IServiceProvider RootServices => InternalApp.RootServices;
+
+ /// 获取Web主机环境,如,是否是开发环境,生产环境等
+ public static IWebHostEnvironment WebHostEnvironment => InternalApp.WebHostEnvironment;
+
+ /// 获取泛型主机环境,如,是否是开发环境,生产环境等
+ public static IHostEnvironment HostEnvironment => InternalApp.HostEnvironment;
///
/// 获取请求上下文
@@ -16,4 +26,55 @@ public class App
public static HttpContext HttpContext => RootServices?.GetService()?.HttpContext;
public static IUser User => HttpContext == null ? null : RootServices?.GetService();
+
+ /// 解析服务提供器
+ ///
+ ///
+ public static IServiceProvider GetServiceProvider(Type serviceType, bool mustBuild = false)
+ {
+ if (App.HostEnvironment == null || App.RootServices != null &&
+ InternalApp.InternalServices
+ .Where((u => u.ServiceType == (serviceType.IsGenericType ? serviceType.GetGenericTypeDefinition() : serviceType)))
+ .Any((u => u.Lifetime == ServiceLifetime.Singleton)))
+ return App.RootServices;
+ HttpContext httpContext = App.HttpContext;
+ if (httpContext?.RequestServices != null)
+ return httpContext.RequestServices;
+ if (App.RootServices != null)
+ {
+ IServiceScope scope = App.RootServices.CreateScope();
+ return scope.ServiceProvider;
+ }
+
+ if (mustBuild)
+ {
+ throw new ApplicationException("当前不可用,必须要等到 WebApplication Build后");
+ }
+
+ ServiceProvider serviceProvider = InternalApp.InternalServices.BuildServiceProvider();
+ return serviceProvider;
+ }
+
+
+ public static TService GetService(bool mustBuild = true) where TService : class => App.GetService(typeof(TService), null, mustBuild) as TService;
+
+ /// 获取请求生存周期的服务
+ ///
+ ///
+ ///
+ ///
+ public static TService GetService(IServiceProvider serviceProvider, bool mustBuild = true) where TService : class => App.GetService(typeof(TService), serviceProvider, mustBuild) as TService;
+
+ /// 获取请求生存周期的服务
+ ///
+ ///
+ ///
+ ///
+ public static object GetService(Type type, IServiceProvider serviceProvider = null, bool mustBuild = true) => (serviceProvider ?? App.GetServiceProvider(type, mustBuild)).GetService(type);
+
+ public static TOptions GetOptions(IServiceProvider serviceProvider = null) where TOptions : class, new()
+ {
+ IOptions service = App.GetService>(serviceProvider ?? App.RootServices, false);
+ return service?.Value;
+ }
}
\ No newline at end of file
diff --git a/Blog.Core.Common/Blog.Core.Common.csproj b/Blog.Core.Common/Blog.Core.Common.csproj
index fc0abb9d..0662bac5 100644
--- a/Blog.Core.Common/Blog.Core.Common.csproj
+++ b/Blog.Core.Common/Blog.Core.Common.csproj
@@ -18,20 +18,23 @@
-
+
-
+
+
+
+
+
-
-
-
+
+
@@ -45,6 +48,7 @@
+
diff --git a/Blog.Core.Common/Const/SqlSugarConst.cs b/Blog.Core.Common/Const/SqlSugarConst.cs
new file mode 100644
index 00000000..f5efd7e2
--- /dev/null
+++ b/Blog.Core.Common/Const/SqlSugarConst.cs
@@ -0,0 +1,9 @@
+namespace Blog.Core.Common.Const;
+
+public class SqlSugarConst
+{
+ ///
+ /// 默认Log数据库标识
+ ///
+ public const string LogConfigId = "Log";
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Core/InternalApp.cs b/Blog.Core.Common/Core/InternalApp.cs
index c1ae8dcd..62e04724 100644
--- a/Blog.Core.Common/Core/InternalApp.cs
+++ b/Blog.Core.Common/Core/InternalApp.cs
@@ -1,17 +1,34 @@
-using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
using System;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
namespace Blog.Core.Common.Core;
public static class InternalApp
{
+ public static IServiceCollection InternalServices;
+
/// 根服务
public static IServiceProvider RootServices;
- public static void ConfigureApplication(this WebApplication app)
+ /// 获取Web主机环境
+ public static IWebHostEnvironment WebHostEnvironment;
+
+ /// 获取泛型主机环境
+ public static IHostEnvironment HostEnvironment;
+
+ public static void ConfigureApplication(this WebApplicationBuilder wab)
{
- app.Lifetime.ApplicationStarted.Register(() => { InternalApp.RootServices = app.Services; });
+ HostEnvironment = wab.Environment;
+ WebHostEnvironment = wab.Environment;
+ InternalServices = wab.Services;
+ }
+
- app.Lifetime.ApplicationStopped.Register(() => { InternalApp.RootServices = null; });
+ public static void ConfigureApplication(this IHost app)
+ {
+ RootServices = app.Services;
}
}
\ No newline at end of file
diff --git a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
index 3d83b002..c3d374ae 100644
--- a/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
+++ b/Blog.Core.Common/DB/Aop/SqlsugarAop.cs
@@ -1,12 +1,40 @@
-using Blog.Core.Model.Models.RootTkey;
+using Blog.Core.Common.LogHelper;
+using Blog.Core.Model.Models.RootTkey;
using Blog.Core.Model.Tenants;
using SqlSugar;
+using StackExchange.Profiling;
using System;
+using Serilog;
namespace Blog.Core.Common.DB.Aop;
public static class SqlSugarAop
{
+ public static void OnLogExecuting(ISqlSugarClient sqlSugarScopeProvider, string sql, SugarParameter[] p, ConnectionConfig config)
+ {
+ try
+ {
+ MiniProfiler.Current.CustomTiming($"ConnId:[{config.ConfigId}] SQL:", GetParas(p) + "【SQL语句】:" + sql);
+
+ if (!AppSettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool()) return;
+
+ if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToConsole", "Enabled" }).ObjToBool() ||
+ AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToFile", "Enabled" }).ObjToBool() ||
+ AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToDB", "Enabled" }).ObjToBool())
+ {
+ using (LogContextExtension.Create.SqlAopPushProperty(sqlSugarScopeProvider))
+ {
+ Log.Information("------------------ \r\n ConnId:[{ConnId}]【SQL语句】: \r\n {Sql}",
+ config.ConfigId, UtilMethods.GetSqlString(config.DbType, sql, p));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Error("Error occured OnLogExcuting:" + e);
+ }
+ }
+
public static void DataExecuting(object oldValue, DataFilterModel entityInfo)
{
if (entityInfo.EntityValue is BaseEntity root)
diff --git a/Blog.Core.Common/DB/BaseDBConfig.cs b/Blog.Core.Common/DB/BaseDBConfig.cs
index 1d86369a..d8c3ee50 100644
--- a/Blog.Core.Common/DB/BaseDBConfig.cs
+++ b/Blog.Core.Common/DB/BaseDBConfig.cs
@@ -12,6 +12,7 @@ public class BaseDBConfig
* 目前是多库操作,默认加载的是appsettings.json设置为true的第一个db连接。
*/
public static (List allDbs, List slaveDbs) MutiConnectionString => MutiInitConn();
+ public static ConnectionConfig LogConfig; //日志库
private static string DifDBConnOfSecurity(params string[] conn)
{
@@ -107,8 +108,6 @@ private static MutiDBOperate SpecialDbString(MutiDBOperate mutiDBOperate)
return mutiDBOperate;
}
-
-
}
diff --git a/Blog.Core.Common/Helper/RecursionHelper.cs b/Blog.Core.Common/Helper/RecursionHelper.cs
index 9b27a37d..b4cbd682 100644
--- a/Blog.Core.Common/Helper/RecursionHelper.cs
+++ b/Blog.Core.Common/Helper/RecursionHelper.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Linq;
namespace Blog.Core.Common.Helper
@@ -8,9 +9,8 @@ namespace Blog.Core.Common.Helper
///
public static class RecursionHelper
{
- public static void LoopToAppendChildren(List all, PermissionTree curItem, int pid, bool needbtn)
+ public static void LoopToAppendChildren(List all, PermissionTree curItem, long pid, bool needbtn)
{
-
var subItems = all.Where(ee => ee.Pid == curItem.value).ToList();
var btnItems = subItems.Where(ss => ss.isbtn == true).ToList();
@@ -28,6 +28,7 @@ public static void LoopToAppendChildren(List all, PermissionTree
{
subItems = subItems.Where(ss => ss.isbtn == false).ToList();
}
+
if (subItems.Count > 0)
{
curItem.children = new List();
@@ -49,14 +50,15 @@ public static void LoopToAppendChildren(List all, PermissionTree
{
//subItem.disabled = true;//禁用当前节点
}
+
LoopToAppendChildren(all, subItem, pid, needbtn);
}
}
+
public static void LoopToAppendChildren(List all, DepartmentTree curItem, int pid)
{
-
var subItems = all.Where(ee => ee.Pid == curItem.value).ToList();
-
+
if (subItems.Count > 0)
{
curItem.children = new List();
@@ -73,15 +75,14 @@ public static void LoopToAppendChildren(List all, DepartmentTree
{
//subItem.disabled = true;//禁用当前节点
}
+
LoopToAppendChildren(all, subItem, pid);
}
}
-
public static void LoopNaviBarAppendChildren(List all, NavigationBar curItem)
{
-
var subItems = all.Where(ee => ee.pid == curItem.id).ToList();
if (subItems.Count > 0)
@@ -102,7 +103,6 @@ public static void LoopNaviBarAppendChildren(List all, Navigation
}
-
public static void LoopToAppendChildrenT(List all, T curItem, string parentIdName = "Pid", string idName = "value", string childrenName = "children")
{
var subItems = all.Where(ee => ee.GetType().GetProperty(parentIdName).GetValue(ee, null).ToString() == curItem.GetType().GetProperty(idName).GetValue(curItem, null).ToString()).ToList();
@@ -113,12 +113,47 @@ public static void LoopToAppendChildrenT(List all, T curItem, string paren
LoopToAppendChildrenT(all, subItem);
}
}
+
+ ///
+ /// 将父子级数据结构转换为普通list
+ ///
+ ///
+ ///
+ public static List TreeToList(List list, Action> action = null)
+ {
+ List results = new List();
+ foreach (var item in list)
+ {
+ results.Add(item);
+ OperationChildData(results, item, action);
+ }
+
+ return results;
+ }
+
+ ///
+ /// 递归子级数据
+ ///
+ /// 树形列表数据
+ /// Item
+ public static void OperationChildData(List allList, T item, Action> action)
+ {
+ dynamic dynItem = item;
+ if (dynItem.Children == null) return;
+ if (dynItem.Children.Count <= 0) return;
+ allList.AddRange(dynItem.Children);
+ foreach (var subItem in dynItem.Children)
+ {
+ action?.Invoke(item, subItem, allList);
+ OperationChildData(allList, subItem, action);
+ }
+ }
}
public class PermissionTree
{
- public int value { get; set; }
- public int Pid { get; set; }
+ public long value { get; set; }
+ public long Pid { get; set; }
public string label { get; set; }
public int order { get; set; }
public bool isbtn { get; set; }
@@ -139,8 +174,8 @@ public class DepartmentTree
public class NavigationBar
{
- public int id { get; set; }
- public int pid { get; set; }
+ public long id { get; set; }
+ public long pid { get; set; }
public int order { get; set; }
public string name { get; set; }
public bool IsHide { get; set; } = false;
@@ -158,15 +193,13 @@ public class NavigationBarMeta
public bool requireAuth { get; set; } = true;
public bool NoTabPage { get; set; } = false;
public bool keepAlive { get; set; } = false;
-
-
}
public class NavigationBarPro
{
- public int id { get; set; }
- public int parentId { get; set; }
+ public long id { get; set; }
+ public long parentId { get; set; }
public int order { get; set; }
public string name { get; set; }
public bool IsHide { get; set; } = false;
@@ -184,4 +217,4 @@ public class NavigationBarMetaPro
public string icon { get; set; }
public bool show { get; set; } = false;
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/HttpPolly/HttpPollyHelper.cs b/Blog.Core.Common/Https/HttpPolly/HttpPollyHelper.cs
similarity index 98%
rename from Blog.Core.Common/HttpPolly/HttpPollyHelper.cs
rename to Blog.Core.Common/Https/HttpPolly/HttpPollyHelper.cs
index f1a1e84c..1187d711 100644
--- a/Blog.Core.Common/HttpPolly/HttpPollyHelper.cs
+++ b/Blog.Core.Common/Https/HttpPolly/HttpPollyHelper.cs
@@ -6,7 +6,7 @@
using System.Text;
using System.Threading.Tasks;
-namespace Blog.Core.Common.HttpPolly
+namespace Blog.Core.Common.Https.HttpPolly
{
public class HttpPollyHelper : IHttpPollyHelper
{
@@ -35,7 +35,7 @@ public async Task PostAsync(HttpEnum httpEnum, string url, R request, D
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
-
+
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@@ -72,7 +72,7 @@ public async Task PostAsync(HttpEnum httpEnum, string url, string request,
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
-
+
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@@ -110,7 +110,7 @@ public async Task PostAsync(HttpEnum httpEnum, string url, R request,
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
-
+
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
@@ -146,7 +146,7 @@ public async Task PostAsync(HttpEnum httpEnum, string url, string reques
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, stringContent);
-
+
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
return await response.Content.ReadAsStringAsync();
@@ -182,7 +182,7 @@ public async Task GetAsync(HttpEnum httpEnum, string url, Dictionary GetAsync(HttpEnum httpEnum, string url, Dictionary PutAsync(HttpEnum httpEnum, string url, R request, Di
var stringContent = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, stringContent);
-
+
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@@ -294,7 +294,7 @@ public async Task PutAsync(HttpEnum httpEnum, string url, string request,
var stringContent = new StringContent(request, Encoding.UTF8, "application/json");
var response = await client.PutAsync(url, stringContent);
-
+
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string result = await response.Content.ReadAsStringAsync();
@@ -331,7 +331,7 @@ public async Task DeleteAsync(HttpEnum httpEnum, string url, Dictionary(context, "X-Forwarded-For")).FirstOrDefault();
+
+ if (string.IsNullOrWhiteSpace(ip))
+ ip = SplitCsv(GetHeaderValueAs(context, "X-Real-IP")).FirstOrDefault();
+
+ if (string.IsNullOrWhiteSpace(ip) && context.Connection?.RemoteIpAddress != null)
+ ip = context.Connection.RemoteIpAddress.ToString();
+
+ if (string.IsNullOrWhiteSpace(ip))
+ ip = GetHeaderValueAs(context, "REMOTE_ADDR");
+
+ return ip;
+ }
+
+ public static bool IsLocal(this HttpContext context)
+ {
+ return GetRequestIp(context) is "127.0.0.1" or "::1" || context.Request?.IsLocal() == true;
+ }
+
+
+ public static bool IsLocal(this HttpRequest req)
+ {
+ var connection = req.HttpContext.Connection;
+ if (connection.RemoteIpAddress != null)
+ {
+ if (connection.LocalIpAddress != null)
+ {
+ return connection.RemoteIpAddress.Equals(connection.LocalIpAddress);
+ }
+ else
+ {
+ return IPAddress.IsLoopback(connection.RemoteIpAddress);
+ }
+ }
+
+ // for in memory TestServer or when dealing with default connection info
+ if (connection.RemoteIpAddress == null && connection.LocalIpAddress == null)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+
+ private static T GetHeaderValueAs(HttpContext context, string headerName)
+ {
+ if (context.Request?.Headers?.TryGetValue(headerName, out var values) ?? false)
+ {
+ string rawValues = values.ToString();
+
+ if (!string.IsNullOrWhiteSpace(rawValues))
+ return (T) Convert.ChangeType(values.ToString(), typeof(T));
+ }
+
+ return default;
+ }
+
+ private static List SplitCsv(string csvList)
+ {
+ if (string.IsNullOrWhiteSpace(csvList))
+ return new List();
+
+ return csvList
+ .TrimEnd(',')
+ .Split(',')
+ .AsEnumerable()
+ .Select(s => s.Trim())
+ .ToList();
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/Hubs/ChatHub.cs b/Blog.Core.Common/Hubs/ChatHub.cs
index ff15c97f..1c58c8a0 100644
--- a/Blog.Core.Common/Hubs/ChatHub.cs
+++ b/Blog.Core.Common/Hubs/ChatHub.cs
@@ -83,7 +83,8 @@ public async Task GetLatestCount(string random)
//2、服务端主动向客户端发送数据,名字千万不能错
if (AppSettings.app(new string[] { "Middleware", "SignalRSendLog", "Enabled" }).ObjToBool())
{
- await Clients.All.ReceiveUpdate(LogLock.GetLogData());
+ //TODO 主动发送错误消息
+ //await Clients.All.ReceiveUpdate(LogLock.GetLogData());
}
diff --git a/Blog.Core.Common/LogHelper/LogContextExtension.cs b/Blog.Core.Common/LogHelper/LogContextExtension.cs
new file mode 100644
index 00000000..bce80cbb
--- /dev/null
+++ b/Blog.Core.Common/LogHelper/LogContextExtension.cs
@@ -0,0 +1,42 @@
+using Serilog.Context;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+
+namespace Blog.Core.Common.LogHelper;
+
+public class LogContextExtension : IDisposable
+{
+ private readonly Stack _disposableStack = new Stack();
+
+ public static LogContextExtension Create => new();
+
+ public void AddStock(IDisposable disposable)
+ {
+ _disposableStack.Push(disposable);
+ }
+
+ public IDisposable SqlAopPushProperty(ISqlSugarClient db)
+ {
+ AddStock(LogContext.PushProperty(LogContextStatic.LogSource, LogContextStatic.AopSql));
+ AddStock(LogContext.PushProperty(LogContextStatic.SqlOutToConsole,
+ AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToConsole", "Enabled" }).ObjToBool()));
+ AddStock(LogContext.PushProperty(LogContextStatic.SqlOutToFile,
+ AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToFile", "Enabled" }).ObjToBool()));
+ AddStock(LogContext.PushProperty(LogContextStatic.OutToDb,
+ AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToDb", "Enabled" }).ObjToBool()));
+
+ AddStock(LogContext.PushProperty(LogContextStatic.SugarActionType, db.SugarActionType));
+
+ return this;
+ }
+
+
+ public void Dispose()
+ {
+ while (_disposableStack.Count > 0)
+ {
+ _disposableStack.Pop().Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/LogHelper/LogContextStatic.cs b/Blog.Core.Common/LogHelper/LogContextStatic.cs
new file mode 100644
index 00000000..52a8167d
--- /dev/null
+++ b/Blog.Core.Common/LogHelper/LogContextStatic.cs
@@ -0,0 +1,42 @@
+using System.IO;
+
+namespace Blog.Core.Common.LogHelper;
+
+public class LogContextStatic
+{
+ static LogContextStatic()
+ {
+ if (!Directory.Exists(BaseLogs))
+ {
+ Directory.CreateDirectory(BaseLogs);
+ }
+ }
+
+ public static readonly string BaseLogs = "Logs";
+ public static readonly string BasePathLogs = @"Logs";
+
+ public static readonly string LogSource = "LogSource";
+ public static readonly string AopSql = "AopSql";
+ public static readonly string SqlOutToConsole = "OutToConsole";
+ public static readonly string SqlOutToFile = "SqlOutToFile";
+ public static readonly string OutToDb = "OutToDb";
+ public static readonly string SugarActionType = "SugarActionType";
+
+ public static readonly string FileMessageTemplate = "{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + new string('-', 100);
+
+
+ public static string Combine(string path1)
+ {
+ return Path.Combine(BaseLogs, path1);
+ }
+
+ public static string Combine(string path1, string path2)
+ {
+ return Path.Combine(BaseLogs, path1, path2);
+ }
+
+ public static string Combine(string path1, string path2, string path3)
+ {
+ return Path.Combine(BaseLogs, path1, path2, path3);
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Common/LogHelper/LogLock.cs b/Blog.Core.Common/LogHelper/LogLock.cs
index 70c5f7f2..2c9be9a9 100644
--- a/Blog.Core.Common/LogHelper/LogLock.cs
+++ b/Blog.Core.Common/LogHelper/LogLock.cs
@@ -1,5 +1,4 @@
using Blog.Core.Common.Helper;
-using log4net;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -7,12 +6,12 @@
using System.Linq;
using System.Text;
using System.Threading;
+using Serilog;
namespace Blog.Core.Common.LogHelper
{
public class LogLock
{
- private static readonly ILog log = LogManager.GetLogger(typeof(LogLock));
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
static int WritedCount = 0;
static int FailedCount = 0;
@@ -53,12 +52,14 @@ public static void OutLogAOP(string prefix, string traceId, string[] dataParas,
default:
break;
}
+
if (AppSettings.app(new string[] { AppSetingNodeName, AppSetingName, "Enabled" }).ObjToBool())
{
if (AppSettings.app(new string[] { AppSetingNodeName, AppSetingName, "LogToDB", "Enabled" }).ObjToBool())
{
OutSql2LogToDB(prefix, traceId, dataParas, IsHeader);
}
+
if (AppSettings.app(new string[] { AppSetingNodeName, AppSetingName, "LogToFile", "Enabled" }).ObjToBool())
{
OutSql2LogToFile(prefix, traceId, dataParas, IsHeader);
@@ -90,6 +91,7 @@ public static void OutSql2LogToFile(string prefix, string traceId, string[] data
{
Directory.CreateDirectory(folderPath);
}
+
//string logFilePath = Path.Combine(path, $@"{filename}.log");
var logFilePath = FileHelper.GetAvailableFileWithPrefixOrderSize(folderPath, prefix);
switch (prefix)
@@ -98,47 +100,48 @@ public static void OutSql2LogToFile(string prefix, string traceId, string[] data
AOPLogInfo apiLogAopInfo = JsonConvert.DeserializeObject(dataParas[1]);
//记录被拦截方法信息的日志信息
var dataIntercept = "" +
- $"【操作时间】:{apiLogAopInfo.RequestTime}\r\n" +
- $"【当前操作用户】:{ apiLogAopInfo.OpUserName} \r\n" +
- $"【当前执行方法】:{ apiLogAopInfo.RequestMethodName} \r\n" +
- $"【携带的参数有】: {apiLogAopInfo.RequestParamsName} \r\n" +
- $"【携带的参数JSON】: {apiLogAopInfo.RequestParamsData} \r\n" +
- $"【响应时间】:{apiLogAopInfo.ResponseIntervalTime}\r\n" +
- $"【执行完成时间】:{apiLogAopInfo.ResponseTime}\r\n" +
- $"【执行完成结果】:{apiLogAopInfo.ResponseJsonData}\r\n";
+ $"【操作时间】:{apiLogAopInfo.RequestTime}\r\n" +
+ $"【当前操作用户】:{apiLogAopInfo.OpUserName} \r\n" +
+ $"【当前执行方法】:{apiLogAopInfo.RequestMethodName} \r\n" +
+ $"【携带的参数有】: {apiLogAopInfo.RequestParamsName} \r\n" +
+ $"【携带的参数JSON】: {apiLogAopInfo.RequestParamsData} \r\n" +
+ $"【响应时间】:{apiLogAopInfo.ResponseIntervalTime}\r\n" +
+ $"【执行完成时间】:{apiLogAopInfo.ResponseTime}\r\n" +
+ $"【执行完成结果】:{apiLogAopInfo.ResponseJsonData}\r\n";
dataParas = new string[] { dataIntercept };
break;
case "AOPLogEx":
AOPLogExInfo apiLogAopExInfo = JsonConvert.DeserializeObject(dataParas[1]);
var dataInterceptEx = "" +
- $"【操作时间】:{apiLogAopExInfo.ApiLogAopInfo.RequestTime}\r\n" +
- $"【当前操作用户】:{ apiLogAopExInfo.ApiLogAopInfo.OpUserName} \r\n" +
- $"【当前执行方法】:{ apiLogAopExInfo.ApiLogAopInfo.RequestMethodName} \r\n" +
- $"【携带的参数有】: {apiLogAopExInfo.ApiLogAopInfo.RequestParamsName} \r\n" +
- $"【携带的参数JSON】: {apiLogAopExInfo.ApiLogAopInfo.RequestParamsData} \r\n" +
- $"【响应时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseIntervalTime}\r\n" +
- $"【执行完成时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseTime}\r\n" +
- $"【执行完成结果】:{apiLogAopExInfo.ApiLogAopInfo.ResponseJsonData}\r\n" +
- $"【执行完成异常信息】:方法中出现异常:{apiLogAopExInfo.ExMessage}\r\n" +
- $"【执行完成异常】:方法中出现异常:{apiLogAopExInfo.InnerException}\r\n";
+ $"【操作时间】:{apiLogAopExInfo.ApiLogAopInfo.RequestTime}\r\n" +
+ $"【当前操作用户】:{apiLogAopExInfo.ApiLogAopInfo.OpUserName} \r\n" +
+ $"【当前执行方法】:{apiLogAopExInfo.ApiLogAopInfo.RequestMethodName} \r\n" +
+ $"【携带的参数有】: {apiLogAopExInfo.ApiLogAopInfo.RequestParamsName} \r\n" +
+ $"【携带的参数JSON】: {apiLogAopExInfo.ApiLogAopInfo.RequestParamsData} \r\n" +
+ $"【响应时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseIntervalTime}\r\n" +
+ $"【执行完成时间】:{apiLogAopExInfo.ApiLogAopInfo.ResponseTime}\r\n" +
+ $"【执行完成结果】:{apiLogAopExInfo.ApiLogAopInfo.ResponseJsonData}\r\n" +
+ $"【执行完成异常信息】:方法中出现异常:{apiLogAopExInfo.ExMessage}\r\n" +
+ $"【执行完成异常】:方法中出现异常:{apiLogAopExInfo.InnerException}\r\n";
dataParas = new string[] { dataInterceptEx };
break;
}
+
var now = DateTime.Now;
string logContent = String.Join("\r\n", dataParas);
if (IsHeader)
{
logContent = (
- "--------------------------------\r\n" +
- DateTime.Now + "|\r\n" +
- String.Join("\r\n", dataParas) + "\r\n"
- );
+ "--------------------------------\r\n" +
+ DateTime.Now + "|\r\n" +
+ String.Join("\r\n", dataParas) + "\r\n"
+ );
}
else
{
logContent = (
- dataParas[1] + ",\r\n"
- );
+ dataParas[1] + ",\r\n"
+ );
}
//if (logContent.IsNotEmptyOrNull() && logContent.Length > 500)
@@ -148,12 +151,12 @@ public static void OutSql2LogToFile(string prefix, string traceId, string[] data
if (isWrt)
{
File.WriteAllText(logFilePath, logContent);
-
}
else
{
File.AppendAllText(logFilePath, logContent);
}
+
WritedCount++;
}
catch (Exception e)
@@ -170,14 +173,15 @@ public static void OutSql2LogToFile(string prefix, string traceId, string[] data
LogWriteLock.ExitWriteLock();
}
}
+
public static void OutSql2LogToDB(string prefix, string traceId, string[] dataParas, bool IsHeader = true)
{
- log4net.LogicalThreadContext.Properties["LogType"] = prefix;
- log4net.LogicalThreadContext.Properties["TraceId"] = traceId;
- if (dataParas.Length >= 2)
- {
- log4net.LogicalThreadContext.Properties["DataType"] = dataParas[0];
- }
+ //log4net.LogicalThreadContext.Properties["LogType"] = prefix;
+ //log4net.LogicalThreadContext.Properties["TraceId"] = traceId;
+ //if (dataParas.Length >= 2)
+ //{
+ // log4net.LogicalThreadContext.Properties["DataType"] = dataParas[0];
+ //}
dataParas = dataParas.Skip(1).ToArray();
@@ -186,32 +190,37 @@ public static void OutSql2LogToDB(string prefix, string traceId, string[] dataPa
{
logContent = (String.Join("", dataParas));
}
+
switch (prefix)
{
//DEBUG | INFO | WARN | ERROR | FATAL
case "AOPLog":
- log.Info(logContent);
+ //TODO 是否需要输出?
+ //Log.Information(logContent);
break;
case "AOPLogEx":
- log.Error(logContent);
+ Log.Error(logContent);
break;
case "RequestIpInfoLog":
- log.Debug(logContent);
+ //TODO 是否需要Debug输出?
+ //Log.Debug(logContent);
break;
case "RecordAccessLogs":
- log.Debug(logContent);
+ //TODO 是否需要Debug输出?
+ //Log.Debug(logContent);
break;
case "SqlLog":
- log.Info(logContent);
+ Log.Information(logContent);
break;
case "RequestResponseLog":
- log.Debug(logContent);
+ //TODO 是否需要Debug输出?
+ //Log.Debug(logContent);
break;
default:
break;
}
-
}
+
///
/// 读取文件内容
///
@@ -287,6 +296,7 @@ public static string ReadLog(string folderPath, string fileName, Encoding encode
{
LogWriteLock.ExitReadLock();
}
+
return s;
}
@@ -315,7 +325,6 @@ private static List GetRequestInfo(ReadType readType)
}
}
}
-
}
return requestInfos;
@@ -336,16 +345,18 @@ public static List GetLogData()
if (!string.IsNullOrEmpty(aoplogContent))
{
aopLogs = aoplogContent.Split("--------------------------------")
- .Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
- .Select(d => new LogInfo
- {
- Datetime = d.Split("|")[0].ObjToDate(),
- Content = d.Split("|")[1]?.Replace("\r\n", "
"),
- LogColor = "AOP",
- }).ToList();
+ .Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
+ .Select(d => new LogInfo
+ {
+ Datetime = d.Split("|")[0].ObjToDate(),
+ Content = d.Split("|")[1]?.Replace("\r\n", "
"),
+ LogColor = "AOP",
+ }).ToList();
}
}
- catch (Exception) { }
+ catch (Exception)
+ {
+ }
try
{
@@ -354,17 +365,19 @@ public static List GetLogData()
if (!string.IsNullOrEmpty(exclogContent))
{
excLogs = exclogContent.Split("--------------------------------")
- .Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
- .Select(d => new LogInfo
- {
- Datetime = (d.Split("|")[0]).Split(',')[0].ObjToDate(),
- Content = d.Split("|")[1]?.Replace("\r\n", "
"),
- LogColor = "EXC",
- Import = 9,
- }).ToList();
+ .Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
+ .Select(d => new LogInfo
+ {
+ Datetime = (d.Split("|")[0]).Split(',')[0].ObjToDate(),
+ Content = d.Split("|")[1]?.Replace("\r\n", "
"),
+ LogColor = "EXC",
+ Import = 9,
+ }).ToList();
}
}
- catch (Exception) { }
+ catch (Exception)
+ {
+ }
try
@@ -374,16 +387,18 @@ public static List GetLogData()
if (!string.IsNullOrEmpty(sqllogContent))
{
sqlLogs = sqllogContent.Split("--------------------------------")
- .Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
- .Select(d => new LogInfo
- {
- Datetime = d.Split("|")[0].ObjToDate(),
- Content = d.Split("|")[1]?.Replace("\r\n", "
"),
- LogColor = "SQL",
- }).ToList();
+ .Where(d => !string.IsNullOrEmpty(d) && d != "\n" && d != "\r\n")
+ .Select(d => new LogInfo
+ {
+ Datetime = d.Split("|")[0].ObjToDate(),
+ Content = d.Split("|")[1]?.Replace("\r\n", "
"),
+ LogColor = "SQL",
+ }).ToList();
}
}
- catch (Exception) { }
+ catch (Exception)
+ {
+ }
//try
//{
@@ -422,14 +437,17 @@ public static List GetLogData()
{
aopLogs.AddRange(excLogs);
}
+
if (sqlLogs != null)
{
aopLogs.AddRange(sqlLogs);
}
+
if (reqresLogs != null)
{
aopLogs.AddRange(reqresLogs);
}
+
aopLogs = aopLogs.OrderByDescending(d => d.Import).ThenByDescending(d => d.Datetime).Take(100).ToList();
return aopLogs;
@@ -450,7 +468,8 @@ public static RequestApiWeekView RequestApiinfoByWeek()
Logs = GetRequestInfo(ReadType.Prefix);
apiWeeks = (from n in Logs
- group n by new { n.Week, n.Url } into g
+ group n by new { n.Week, n.Url }
+ into g
select new ApiWeek
{
week = g.Key.Week,
@@ -459,7 +478,6 @@ public static RequestApiWeekView RequestApiinfoByWeek()
}).ToList();
//apiWeeks = apiWeeks.OrderByDescending(d => d.count).Take(8).ToList();
-
}
catch (Exception)
{
@@ -489,10 +507,12 @@ public static RequestApiWeekView RequestApiinfoByWeek()
jsonBuilder.Append(item.count);
jsonBuilder.Append("\",");
}
+
if (apiweeksCurrentWeek.Count > 0)
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
+
jsonBuilder.Append("},");
}
@@ -500,6 +520,7 @@ public static RequestApiWeekView RequestApiinfoByWeek()
{
jsonBuilder.Remove(jsonBuilder.Length - 1, 1);
}
+
jsonBuilder.Append("]");
//columns.AddRange(apiWeeks.OrderByDescending(d => d.count).Take(8).Select(d => d.url).ToList());
@@ -521,7 +542,8 @@ public static AccessApiDateView AccessApiByDate()
Logs = GetRequestInfo(ReadType.Prefix);
apiDates = (from n in Logs
- group n by new { n.Date } into g
+ group n by new { n.Date }
+ into g
select new ApiDate
{
date = g.Key.Date,
@@ -529,7 +551,6 @@ public static AccessApiDateView AccessApiByDate()
}).ToList();
apiDates = apiDates.OrderByDescending(d => d.date).Take(7).ToList();
-
}
catch (Exception)
{
@@ -552,7 +573,8 @@ public static AccessApiDateView AccessApiByHour()
apiDates = (from n in Logs
where n.Datetime.ObjToDate() >= DateTime.Today
- group n by new { hour = n.Datetime.ObjToDate().Hour } into g
+ group n by new { hour = n.Datetime.ObjToDate().Hour }
+ into g
select new ApiDate
{
date = g.Key.hour.ToString("00"),
@@ -560,7 +582,6 @@ where n.Datetime.ObjToDate() >= DateTime.Today
}).ToList();
apiDates = apiDates.OrderBy(d => d.date).Take(24).ToList();
-
}
catch (Exception)
{
@@ -580,14 +601,15 @@ public enum ReadType
/// 精确查找一个
///
Accurate,
+
///
/// 指定前缀,模糊查找全部
///
Prefix,
+
///
/// 指定前缀,最新一个文件
///
PrefixLatest
}
-
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/Blog.Core.Extensions.csproj b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
index 451d24f1..9eae3d92 100644
--- a/Blog.Core.Extensions/Blog.Core.Extensions.csproj
+++ b/Blog.Core.Extensions/Blog.Core.Extensions.csproj
@@ -18,10 +18,10 @@
-
+
@@ -35,6 +35,7 @@
+
diff --git a/Blog.Core.Extensions/Middlewares/ExceptionHandlerMiddleware.cs b/Blog.Core.Extensions/Middlewares/ExceptionHandlerMiddleware.cs
index 85d96e9b..aed57769 100644
--- a/Blog.Core.Extensions/Middlewares/ExceptionHandlerMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/ExceptionHandlerMiddleware.cs
@@ -4,14 +4,13 @@
using Blog.Core.Model;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
+using Serilog;
namespace Blog.Core.Extensions.Middlewares
{
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
- private static readonly log4net.ILog Log =
- log4net.LogManager.GetLogger(typeof(ExceptionHandlerMiddleware));
public ExceptionHandlerMiddleware(RequestDelegate next)
{
@@ -48,7 +47,9 @@ private static async Task WriteExceptionAsync(HttpContext context, Exception e)
context.Response.ContentType = "application/json";
- await context.Response.WriteAsync(JsonConvert.SerializeObject((new ApiResponse(StatusCode.CODE500, e.Message)).MessageModel)).ConfigureAwait(false);
+ await context.Response
+ .WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE500, e.Message).MessageModel))
+ .ConfigureAwait(false);
}
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/Middlewares/IpLimitMiddleware.cs b/Blog.Core.Extensions/Middlewares/IpLimitMiddleware.cs
index 958d6ff3..7fe68fc4 100644
--- a/Blog.Core.Extensions/Middlewares/IpLimitMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/IpLimitMiddleware.cs
@@ -1,8 +1,8 @@
-using System;
-using AspNetCoreRateLimit;
+using AspNetCoreRateLimit;
using Blog.Core.Common;
-using log4net;
using Microsoft.AspNetCore.Builder;
+using System;
+using Serilog;
namespace Blog.Core.Extensions.Middlewares
{
@@ -11,7 +11,6 @@ namespace Blog.Core.Extensions.Middlewares
///
public static class IpLimitMiddleware
{
- private static readonly ILog Log = LogManager.GetLogger(typeof(IpLimitMiddleware));
public static void UseIpLimitMiddle(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
diff --git a/Blog.Core.Extensions/Middlewares/IpLogMiddleware.cs b/Blog.Core.Extensions/Middlewares/IpLogMiddleware.cs
index b6b91bd5..ccd0d7af 100644
--- a/Blog.Core.Extensions/Middlewares/IpLogMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/IpLogMiddleware.cs
@@ -1,10 +1,10 @@
-using System;
-using System.Threading.Tasks;
-using Blog.Core.Common;
+using Blog.Core.Common;
using Blog.Core.Common.LogHelper;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
+using System;
+using System.Threading.Tasks;
namespace Blog.Core.Extensions.Middlewares
{
@@ -19,7 +19,6 @@ public class IpLogMiddleware
///
private readonly RequestDelegate _next;
private readonly IWebHostEnvironment _environment;
- private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(IpLogMiddleware));
///
///
diff --git a/Blog.Core.Extensions/Middlewares/MiniProfilerMiddleware.cs b/Blog.Core.Extensions/Middlewares/MiniProfilerMiddleware.cs
index 068c4a0d..49e3b70d 100644
--- a/Blog.Core.Extensions/Middlewares/MiniProfilerMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/MiniProfilerMiddleware.cs
@@ -1,7 +1,7 @@
-using System;
-using Blog.Core.Common;
-using log4net;
+using Blog.Core.Common;
using Microsoft.AspNetCore.Builder;
+using System;
+using Serilog;
namespace Blog.Core.Extensions.Middlewares
{
@@ -10,7 +10,6 @@ namespace Blog.Core.Extensions.Middlewares
///
public static class MiniProfilerMiddleware
{
- private static readonly ILog Log = LogManager.GetLogger(typeof(MiniProfilerMiddleware));
public static void UseMiniProfilerMiddleware(this IApplicationBuilder app)
{
if (app == null) throw new ArgumentNullException(nameof(app));
diff --git a/Blog.Core.Extensions/Middlewares/SignalRSendMiddleware.cs b/Blog.Core.Extensions/Middlewares/SignalRSendMiddleware.cs
index 1909c08f..f15df7b4 100644
--- a/Blog.Core.Extensions/Middlewares/SignalRSendMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/SignalRSendMiddleware.cs
@@ -36,6 +36,7 @@ public async Task InvokeAsync(HttpContext context)
{
if (AppSettings.app("Middleware", "SignalR", "Enabled").ObjToBool())
{
+ //TODO 主动发送错误消息
await _hubContext.Clients.All.SendAsync("ReceiveUpdate", LogLock.GetLogData());
}
await _next(context);
diff --git a/Blog.Core.Extensions/Middlewares/SwaggerMiddleware.cs b/Blog.Core.Extensions/Middlewares/SwaggerMiddleware.cs
index 099b2576..73af77d2 100644
--- a/Blog.Core.Extensions/Middlewares/SwaggerMiddleware.cs
+++ b/Blog.Core.Extensions/Middlewares/SwaggerMiddleware.cs
@@ -1,10 +1,10 @@
-using System;
-using System.IO;
-using System.Linq;
-using Blog.Core.Common;
-using log4net;
+using Blog.Core.Common;
using Microsoft.AspNetCore.Builder;
using Swashbuckle.AspNetCore.SwaggerUI;
+using System;
+using System.IO;
+using System.Linq;
+using Serilog;
using static Blog.Core.Extensions.CustomApiVersion;
namespace Blog.Core.Extensions.Middlewares
@@ -14,7 +14,6 @@ namespace Blog.Core.Extensions.Middlewares
///
public static class SwaggerMiddleware
{
- private static readonly ILog Log = LogManager.GetLogger(typeof(SwaggerMiddleware));
public static void UseSwaggerMiddle(this IApplicationBuilder app, Func streamHtml)
{
if (app == null) throw new ArgumentNullException(nameof(app));
@@ -24,10 +23,7 @@ public static void UseSwaggerMiddle(this IApplicationBuilder app, Func s
{
//根据版本名称倒序 遍历展示
var apiName = AppSettings.app(new string[] { "Startup", "ApiName" });
- typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version =>
- {
- c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{apiName} {version}");
- });
+ typeof(ApiVersions).GetEnumNames().OrderByDescending(e => e).ToList().ForEach(version => { c.SwaggerEndpoint($"/swagger/{version}/swagger.json", $"{apiName} {version}"); });
c.SwaggerEndpoint($"https://petstore.swagger.io/v2/swagger.json", $"{apiName} pet");
@@ -38,12 +34,13 @@ public static void UseSwaggerMiddle(this IApplicationBuilder app, Func s
Log.Error(msg);
throw new Exception(msg);
}
+
c.IndexStream = streamHtml;
c.DocExpansion(DocExpansion.None); //->修改界面打开时自动折叠
if (Permissions.IsUseIds4)
{
- c.OAuthClientId("blogadminjs");
+ c.OAuthClientId("blogadminjs");
}
@@ -52,4 +49,4 @@ public static void UseSwaggerMiddle(this IApplicationBuilder app, Func s
});
}
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs b/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
index 0622e766..0336567f 100644
--- a/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/AppConfigSetup.cs
@@ -76,10 +76,10 @@ public static void AddAppConfigSetup(this IServiceCollection services, IHostEnvi
var ipLogOpen = AppSettings.app(new string[] { "Middleware", "IPLog", "Enabled" }).ObjToBool();
var recordAccessLogsOpen = AppSettings.app(new string[] { "Middleware", "RecordAccessLogs", "Enabled" }).ObjToBool();
ConsoleHelper.WriteSuccessLine($"OPEN Log: " +
- (requestResponseLogOpen ? "RequestResponseLog √," : "") +
- (ipLogOpen ? "IPLog √," : "") +
- (recordAccessLogsOpen ? "RecordAccessLogs √," : "")
- );
+ (requestResponseLogOpen ? "RequestResponseLog √," : "") +
+ (ipLogOpen ? "IPLog √," : "") +
+ (recordAccessLogsOpen ? "RecordAccessLogs √," : "")
+ );
// 事务AOP
if (!AppSettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
@@ -213,7 +213,6 @@ public static void AddAppConfigSetup(this IServiceCollection services, IHostEnvi
Console.WriteLine();
}
-
}
public static void AddAppTableConfigSetup(this IServiceCollection services, IHostEnvironment env)
@@ -222,7 +221,6 @@ public static void AddAppTableConfigSetup(this IServiceCollection services, IHos
if (AppSettings.app(new string[] { "Startup", "AppConfigAlert", "Enabled" }).ObjToBool())
{
-
if (env.IsDevelopment())
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
@@ -230,6 +228,7 @@ public static void AddAppTableConfigSetup(this IServiceCollection services, IHos
}
#region 程序配置
+
List configInfos = new()
{
new string[] { "当前环境", Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") },
@@ -238,7 +237,7 @@ public static void AddAppTableConfigSetup(this IServiceCollection services, IHos
new string[] { "RabbitMQ消息列队", AppSettings.app("RabbitMQ", "Enabled") },
new string[] { "事件总线(必须开启消息列队)", AppSettings.app("EventBus", "Enabled") },
new string[] { "redis消息队列", AppSettings.app("Startup", "RedisMq", "Enabled") },
- new string[] { "是否多库", AppSettings.app("MutiDBEnabled" ) },
+ new string[] { "是否多库", AppSettings.app("MutiDBEnabled") },
new string[] { "读写分离", AppSettings.app("CQRSEnabled") },
};
@@ -253,17 +252,19 @@ public static void AddAppTableConfigSetup(this IServiceCollection services, IHos
TableStyle = TableStyle.Alternative
}.Writer(ConsoleColor.Blue);
Console.WriteLine();
+
#endregion 程序配置
#region AOP
+
List aopInfos = new()
-{
+ {
new string[] { "Redis缓存AOP", AppSettings.app("AppSettings", "RedisCachingAOP", "Enabled") },
new string[] { "内存缓存AOP", AppSettings.app("AppSettings", "MemoryCachingAOP", "Enabled") },
- new string[] { "服务日志AOP", AppSettings.app("AppSettings", "LogAOP", "Enabled" ) },
- new string[] { "事务AOP", AppSettings.app("AppSettings", "TranAOP", "Enabled" ) },
- new string[] { "Sql执行AOP", AppSettings.app("AppSettings", "SqlAOP", "OutToLogFile", "Enabled" ) },
- new string[] { "Sql执行AOP控制台输出", AppSettings.app("AppSettings", "SqlAOP", "OutToConsole", "Enabled" ) },
+ new string[] { "服务日志AOP", AppSettings.app("AppSettings", "LogAOP", "Enabled") },
+ new string[] { "事务AOP", AppSettings.app("AppSettings", "TranAOP", "Enabled") },
+ new string[] { "Sql执行AOP", AppSettings.app("AppSettings", "SqlAOP", "Enabled") },
+ new string[] { "Sql执行AOP控制台输出", AppSettings.app("AppSettings", "SqlAOP", "LogToConsole", "Enabled") },
};
new ConsoleTable
@@ -277,15 +278,17 @@ public static void AddAppTableConfigSetup(this IServiceCollection services, IHos
TableStyle = TableStyle.Alternative
}.Writer(ConsoleColor.Blue);
Console.WriteLine();
+
#endregion AOP
#region 中间件
+
List MiddlewareInfos = new()
{
new string[] { "请求纪录中间件", AppSettings.app("Middleware", "RecordAccessLogs", "Enabled") },
- new string[] { "IP记录中间件", AppSettings.app("Middleware", "IPLog", "Enabled" ) },
- new string[] { "请求响应日志中间件", AppSettings.app("Middleware", "RequestResponseLog", "Enabled" ) },
- new string[] { "SingnalR实时发送请求数据中间件", AppSettings.app("Middleware", "SignalR", "Enabled" ) },
+ new string[] { "IP记录中间件", AppSettings.app("Middleware", "IPLog", "Enabled") },
+ new string[] { "请求响应日志中间件", AppSettings.app("Middleware", "RequestResponseLog", "Enabled") },
+ new string[] { "SingnalR实时发送请求数据中间件", AppSettings.app("Middleware", "SignalR", "Enabled") },
new string[] { "IP限流中间件", AppSettings.app("Middleware", "IpRateLimit", "Enabled") },
new string[] { "性能分析中间件", AppSettings.app("Startup", "MiniProfiler", "Enabled") },
new string[] { "Consul注册服务", AppSettings.app("Middleware", "Consul", "Enabled") },
@@ -302,10 +305,9 @@ public static void AddAppTableConfigSetup(this IServiceCollection services, IHos
TableStyle = TableStyle.Alternative
}.Writer(ConsoleColor.Blue);
Console.WriteLine();
- #endregion 中间件
+ #endregion 中间件
}
-
}
}
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs b/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs
index 7f2997bd..4351962b 100644
--- a/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/AutofacModuleRegister.cs
@@ -6,20 +6,18 @@
using Blog.Core.IServices.BASE;
using Blog.Core.Model;
using Blog.Core.Repository.Base;
+using Blog.Core.Repository.UnitOfWorks;
using Blog.Core.Services.BASE;
-using log4net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
-using Blog.Core.Repository.UnitOfWorks;
+using Serilog;
namespace Blog.Core.Extensions
{
public class AutofacModuleRegister : Autofac.Module
{
- private static readonly ILog log = LogManager.GetLogger(typeof(AutofacModuleRegister));
-
protected override void Load(ContainerBuilder builder)
{
var basePath = AppContext.BaseDirectory;
@@ -34,39 +32,39 @@ protected override void Load(ContainerBuilder builder)
if (!(File.Exists(servicesDllFile) && File.Exists(repositoryDllFile)))
{
var msg = "Repository.dll和service.dll 丢失,因为项目解耦了,所以需要先F6编译,再F5运行,请检查 bin 文件夹,并拷贝。";
- log.Error(msg);
+ Log.Error(msg);
throw new Exception(msg);
}
// AOP 开关,如果想要打开指定的功能,只需要在 appsettigns.json 对应对应 true 就行。
var cacheType = new List();
- if (AppSettings.app(new string[] {"AppSettings", "RedisCachingAOP", "Enabled"}).ObjToBool())
+ if (AppSettings.app(new string[] { "AppSettings", "RedisCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType();
cacheType.Add(typeof(BlogRedisCacheAOP));
}
- if (AppSettings.app(new string[] {"AppSettings", "MemoryCachingAOP", "Enabled"}).ObjToBool())
+ if (AppSettings.app(new string[] { "AppSettings", "MemoryCachingAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType();
cacheType.Add(typeof(BlogCacheAOP));
}
- if (AppSettings.app(new string[] {"AppSettings", "TranAOP", "Enabled"}).ObjToBool())
+ if (AppSettings.app(new string[] { "AppSettings", "TranAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType();
cacheType.Add(typeof(BlogTranAOP));
}
- if (AppSettings.app(new string[] {"AppSettings", "LogAOP", "Enabled"}).ObjToBool())
+ if (AppSettings.app(new string[] { "AppSettings", "LogAOP", "Enabled" }).ObjToBool())
{
builder.RegisterType();
cacheType.Add(typeof(BlogLogAOP));
}
- builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency();//注册仓储
- builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerDependency();//注册服务
+ builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerDependency(); //注册仓储
+ builder.RegisterGeneric(typeof(BaseServices<>)).As(typeof(IBaseServices<>)).InstancePerDependency(); //注册服务
// 获取 Service.dll 程序集服务,并注册
var assemblysServices = Assembly.LoadFrom(servicesDllFile);
diff --git a/Blog.Core.Extensions/ServiceExtensions/HttpPollySetup.cs b/Blog.Core.Extensions/ServiceExtensions/HttpPollySetup.cs
index e8e3929f..b3147ca8 100644
--- a/Blog.Core.Extensions/ServiceExtensions/HttpPollySetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/HttpPollySetup.cs
@@ -1,4 +1,4 @@
-using Blog.Core.Common.HttpPolly;
+using Blog.Core.Common.Https.HttpPolly;
using Blog.Core.Model;
using Microsoft.Extensions.DependencyInjection;
using Polly;
diff --git a/Blog.Core.Extensions/ServiceExtensions/SerilogSetup.cs b/Blog.Core.Extensions/ServiceExtensions/SerilogSetup.cs
new file mode 100644
index 00000000..a112409c
--- /dev/null
+++ b/Blog.Core.Extensions/ServiceExtensions/SerilogSetup.cs
@@ -0,0 +1,37 @@
+using Blog.Core.Common;
+using Blog.Core.Common.LogHelper;
+using Blog.Core.Serilog.Extensions;
+using Microsoft.Extensions.Hosting;
+using Serilog;
+using Serilog.Debugging;
+using System;
+using System.IO;
+
+namespace Blog.Core.Extensions.ServiceExtensions;
+
+public static class SerilogSetup
+{
+ public static IHostBuilder AddSerilogSetup(this IHostBuilder host)
+ {
+ if (host == null) throw new ArgumentNullException(nameof(host));
+
+ var loggerConfiguration = new LoggerConfiguration()
+ .ReadFrom.Configuration(AppSettings.Configuration)
+ .Enrich.FromLogContext()
+ //输出到控制台
+ .WriteToConsole()
+ //将日志保存到文件中
+ .WriteToFile();
+ //配置日志库
+ //.WriteToLogBatching();
+
+ Log.Logger = loggerConfiguration.CreateLogger();
+
+ //Serilog 内部日志
+ var file = File.CreateText(LogContextStatic.Combine($"SerilogDebug{DateTime.Now:yyyyMMdd}.txt"));
+ SelfLog.Enable(TextWriter.Synchronized(file));
+
+ host.UseSerilog();
+ return host;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs b/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
index 3ecf224a..3440b8af 100644
--- a/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/SqlsugarSetup.cs
@@ -1,6 +1,7 @@
using Blog.Core.Common;
+using Blog.Core.Common.Const;
using Blog.Core.Common.DB;
-using Blog.Core.Common.Helper;
+using Blog.Core.Common.DB.Aop;
using Blog.Core.Common.LogHelper;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
@@ -9,7 +10,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Blog.Core.Common.DB.Aop;
namespace Blog.Core.Extensions
{
@@ -48,7 +48,7 @@ public static void AddSqlsugarSetup(this IServiceCollection services)
BaseDBConfig.MutiConnectionString.allDbs.ForEach(m =>
{
- listConfig.Add(new ConnectionConfig()
+ var config = new ConnectionConfig()
{
ConfigId = m.ConnId.ObjToString().ToLower(),
ConnectionString = m.Connection,
@@ -56,29 +56,6 @@ public static void AddSqlsugarSetup(this IServiceCollection services)
IsAutoCloseConnection = true,
// Check out more information: https://github.com/anjoy8/Blog.Core/issues/122
//IsShardSameThread = false,
- AopEvents = new AopEvents
- {
- OnLogExecuting = (sql, p) =>
- {
- if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "Enabled" }).ObjToBool())
- {
- if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToFile", "Enabled" }).ObjToBool())
- {
- Parallel.For(0, 1, e =>
- {
- MiniProfiler.Current.CustomTiming("SQL:", GetParas(p) + "【SQL语句】:" + sql);
- //LogLock.OutSql2Log("SqlLog", new string[] { GetParas(p), "【SQL语句】:" + sql });
- LogLock.OutLogAOP("SqlLog", "", new string[] { sql.GetType().ToString(), GetParas(p), "【SQL语句】:" + sql });
-
- });
- }
- if (AppSettings.app(new string[] { "AppSettings", "SqlAOP", "LogToConsole", "Enabled" }).ObjToBool())
- {
- ConsoleHelper.WriteColorLine(string.Join("\r\n", new string[] { "--------", $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")} :" + GetWholeSql(p, sql) }), ConsoleColor.DarkCyan);
- }
- }
- },
- },
MoreSettings = new ConnMoreSettings()
{
//IsWithNoLockQuery = true,
@@ -99,15 +76,29 @@ public static void AddSqlsugarSetup(this IServiceCollection services)
}
},
InitKeyType = InitKeyType.Attribute
+ };
+ if (SqlSugarConst.LogConfigId.Equals(m.ConnId))
+ {
+ BaseDBConfig.LogConfig = config;
}
- );
+
+ listConfig.Add(config);
});
+
+ if (BaseDBConfig.LogConfig is null)
+ {
+ throw new ApplicationException("未配置Log库连接");
+ }
+
return new SqlSugarScope(listConfig, db =>
{
listConfig.ForEach(config =>
{
var dbProvider = db.GetConnectionScope((string)config.ConfigId);
+ // 打印SQL语句
+ dbProvider.Aop.OnLogExecuting = (s, parameters) => SqlSugarAop.OnLogExecuting(dbProvider,s, parameters, config);
+
// 数据审计
dbProvider.Aop.DataExecuting = SqlSugarAop.DataExecuting;
diff --git a/Blog.Core.Extensions/ServiceExtensions/SwaggerSetup.cs b/Blog.Core.Extensions/ServiceExtensions/SwaggerSetup.cs
index 449b6a4d..85dff620 100644
--- a/Blog.Core.Extensions/ServiceExtensions/SwaggerSetup.cs
+++ b/Blog.Core.Extensions/ServiceExtensions/SwaggerSetup.cs
@@ -1,7 +1,7 @@
using Blog.Core.Common;
-using log4net;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
+using Serilog;
using Swashbuckle.AspNetCore.Filters;
using System;
using System.Collections.Generic;
@@ -17,10 +17,6 @@ namespace Blog.Core.Extensions
///
public static class SwaggerSetup
{
-
- private static readonly ILog log =
- LogManager.GetLogger(typeof(SwaggerSetup));
-
public static void AddSwaggerSetup(this IServiceCollection services)
{
if (services == null) throw new ArgumentNullException(nameof(services));
@@ -59,7 +55,7 @@ public static void AddSwaggerSetup(this IServiceCollection services)
}
catch (Exception ex)
{
- log.Error("Blog.Core.xml和Blog.Core.Model.xml 丢失,请检查并拷贝。\n" + ex.Message);
+ Log.Error("Blog.Core.xml和Blog.Core.Model.xml 丢失,请检查并拷贝。\n" + ex.Message);
}
// 开启加权小锁
@@ -82,12 +78,13 @@ public static void AddSwaggerSetup(this IServiceCollection services)
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri($"{AppSettings.app(new string[] { "Startup", "IdentityServer4", "AuthorizationUrl" })}/connect/authorize"),
- Scopes = new Dictionary {
+ Scopes = new Dictionary
{
- "blog.core.api","ApiResource id"
+ {
+ "blog.core.api", "ApiResource id"
+ }
}
}
- }
}
});
}
@@ -97,14 +94,11 @@ public static void AddSwaggerSetup(this IServiceCollection services)
c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 直接在下框中输入Bearer {token}(注意两者之间是一个空格)\"",
- Name = "Authorization",//jwt默认的参数名称
- In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
+ Name = "Authorization", //jwt默认的参数名称
+ In = ParameterLocation.Header, //jwt默认存放Authorization信息的位置(请求头中)
Type = SecuritySchemeType.ApiKey
});
}
-
-
-
});
services.AddSwaggerGenNewtonsoftSupport();
}
@@ -124,11 +118,11 @@ public enum ApiVersions
/// V1 版本
///
V1 = 1,
+
///
/// V2 版本
///
V2 = 2,
}
}
-
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
index 5cf82020..398aab48 100644
--- a/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
+++ b/Blog.Core.Serilog.Es/Blog.Core.Serilog.Es.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/Blog.Core.Serilog/Blog.Core.Serilog.csproj b/Blog.Core.Serilog/Blog.Core.Serilog.csproj
new file mode 100644
index 00000000..07fa26f3
--- /dev/null
+++ b/Blog.Core.Serilog/Blog.Core.Serilog.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/Blog.Core.Serilog/Extensions/LoggerConfigurationExtensions.cs b/Blog.Core.Serilog/Extensions/LoggerConfigurationExtensions.cs
new file mode 100644
index 00000000..2736aa1f
--- /dev/null
+++ b/Blog.Core.Serilog/Extensions/LoggerConfigurationExtensions.cs
@@ -0,0 +1,121 @@
+using Blog.Core.Common;
+using Blog.Core.Common.LogHelper;
+using Serilog;
+using Serilog.Events;
+using Serilog.Filters;
+using SqlSugar;
+
+namespace Blog.Core.Serilog.Extensions;
+
+public static class LoggerConfigurationExtensions
+{
+ public static LoggerConfiguration WriteToSqlServer(this LoggerConfiguration loggerConfiguration)
+ {
+ var logConnectionStrings = AppSettings.app("LogConnectionStrings");
+ if (logConnectionStrings.IsNullOrEmpty()) return loggerConfiguration;
+
+ //输出SQL
+ //loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ // lg.FilterSqlLog().WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
+ // {
+ // TableName = "SqlLog",
+ // AutoCreateSqlTable = true
+ // }));
+
+ //输出普通日志
+ //loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ // lg.FilterRemoveSqlLog().Filter.ByIncludingOnly(p => p.Level >= LogEventLevel.Error)
+ // .WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
+ // {
+ // TableName = "ErrorLog",
+ // AutoCreateSqlTable = true
+ // }));
+ //loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ // lg.FilterRemoveSqlLog().Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning)
+ // .WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
+ // {
+ // TableName = "WarningLog",
+ // AutoCreateSqlTable = true
+ // }));
+ //loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ // lg.FilterRemoveSqlLog().Filter.ByIncludingOnly(p => p.Level <= LogEventLevel.Information)
+ // .WriteTo.MSSqlServer(logConnectionStrings, new MSSqlServerSinkOptions()
+ // {
+ // TableName = "InformationLog",
+ // AutoCreateSqlTable = true
+ // }));
+
+ return loggerConfiguration;
+ }
+
+ public static LoggerConfiguration WriteToConsole(this LoggerConfiguration loggerConfiguration)
+ {
+ //输出普通日志
+ loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ lg.FilterRemoveSqlLog().WriteTo.Console());
+
+ //输出SQL
+ loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ lg.FilterSqlLog().Filter.ByIncludingOnly(Matching.WithProperty(LogContextStatic.SqlOutToConsole, s => s))
+ .WriteTo.Console());
+
+ return loggerConfiguration;
+ }
+
+ public static LoggerConfiguration WriteToFile(this LoggerConfiguration loggerConfiguration)
+ {
+ //输出SQL
+ loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ lg.FilterSqlLog().Filter.ByIncludingOnly(Matching.WithProperty(LogContextStatic.SqlOutToFile, s => s))
+ .WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.AopSql, @"AopSql.txt"), rollingInterval: RollingInterval.Day,
+ outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));
+ //输出普通日志
+ loggerConfiguration = loggerConfiguration.WriteTo.Logger(lg =>
+ lg.FilterRemoveSqlLog().WriteTo.Async(s => s.File(LogContextStatic.Combine(LogContextStatic.BasePathLogs, @"Log.txt"), rollingInterval: RollingInterval.Day,
+ outputTemplate: LogContextStatic.FileMessageTemplate, retainedFileCountLimit: 31)));
+ return loggerConfiguration;
+ }
+
+ public static LoggerConfiguration FilterSqlLog(this LoggerConfiguration lc)
+ {
+ lc = lc.Filter.ByIncludingOnly(Matching.WithProperty(LogContextStatic.LogSource, s => LogContextStatic.AopSql.Equals(s)));
+ return lc;
+ }
+
+ public static IEnumerable FilterSqlLog(this IEnumerable batch)
+ {
+ return batch.Where(s => s.WithProperty(LogContextStatic.LogSource, q => LogContextStatic.AopSql.Equals(q)))
+ .Where(s => s.WithProperty(LogContextStatic.SugarActionType,
+ q => !new[] { SugarActionType.UnKnown, SugarActionType.Query }.Contains(q)));
+ }
+
+ public static LoggerConfiguration FilterRemoveSqlLog(this LoggerConfiguration lc)
+ {
+ lc = lc.Filter.ByIncludingOnly(WithProperty(LogContextStatic.LogSource, s => !LogContextStatic.AopSql.Equals(s)));
+ return lc;
+ }
+
+ public static IEnumerable FilterRemoveOtherLog(this IEnumerable batch)
+ {
+ return batch.Where(s => WithProperty(LogContextStatic.LogSource,
+ q => !LogContextStatic.AopSql.Equals(q))(s));
+ }
+
+ public static Func WithProperty(string propertyName, Func predicate)
+ {
+ //如果不包含属性 也认为是true
+ return e =>
+ {
+ if (!e.Properties.TryGetValue(propertyName, out var propertyValue)) return true;
+
+ return propertyValue is ScalarValue { Value: T value } && predicate(value);
+ };
+ }
+
+ public static bool WithProperty(this LogEvent e, string key, Func predicate)
+ {
+ if (!e.Properties.TryGetValue(key, out var propertyValue)) return false;
+
+ return propertyValue is ScalarValue { Value: T value } && predicate(value);
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Serilog/Utility/SerilogRequestUtility.cs b/Blog.Core.Serilog/Utility/SerilogRequestUtility.cs
new file mode 100644
index 00000000..cab7ae55
--- /dev/null
+++ b/Blog.Core.Serilog/Utility/SerilogRequestUtility.cs
@@ -0,0 +1,34 @@
+using Microsoft.AspNetCore.Http;
+using Serilog.Events;
+
+namespace Blog.Core.Serilog.Utility;
+
+public class SerilogRequestUtility
+{
+ private static readonly List _ignoreUrl = new()
+ {
+ "/job",
+ };
+
+ private static LogEventLevel DefaultGetLevel(
+ HttpContext ctx,
+ double _,
+ Exception? ex)
+ {
+ return ex is null && ctx.Response.StatusCode <= 499 ? LogEventLevel.Information : LogEventLevel.Error;
+ }
+
+ public static LogEventLevel GetRequestLevel(HttpContext ctx, double _, Exception? ex) =>
+ ex is null && ctx.Response.StatusCode <= 499 ? IgnoreRequest(ctx) : LogEventLevel.Error;
+
+ private static LogEventLevel IgnoreRequest(HttpContext ctx)
+ {
+ var path = ctx.Request.Path.Value;
+ if (path.IsNullOrEmpty())
+ {
+ return LogEventLevel.Information;
+ }
+
+ return _ignoreUrl.Any(s => path.StartsWith(s)) ? LogEventLevel.Verbose : LogEventLevel.Information;
+ }
+}
\ No newline at end of file
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
index 1dcc57ed..1d501c34 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_AccessTrendLog_Quartz.cs
@@ -34,7 +34,7 @@ public async Task Execute(IJobExecutionContext context)
}
public async Task Run(IJobExecutionContext context)
{
-
+
// 可以直接获取 JobDetail 的值
var jobKey = context.JobDetail.Key;
var jobId = jobKey.Name;
@@ -94,7 +94,7 @@ await _accessTrendLogServices.Add(new AccessTrendLog()
Parallel.For(0, 1, e =>
{
- LogLock.OutLogAOP("ACCESSTRENDLOG","",new string[] { activeUserVMs.GetType().ToString(), JsonConvert.SerializeObject(activeUserVMs) }, false);
+ LogLock.OutLogAOP("ACCESSTRENDLOG", "", new string[] { activeUserVMs.GetType().ToString(), JsonConvert.SerializeObject(activeUserVMs) }, false);
});
}
diff --git a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
index 18c4c298..abcd81ea 100644
--- a/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
+++ b/Blog.Core.Tasks/QuartzNet/Jobs/Job_OperateLog_Quartz.cs
@@ -17,19 +17,21 @@ namespace Blog.Core.Tasks
{
public class Job_OperateLog_Quartz : JobBase, IJob
{
- private readonly IOperateLogServices _operateLogServices;
+ private readonly IOperateLogServices _operateLogServices;
private readonly IWebHostEnvironment _environment;
- public Job_OperateLog_Quartz(IOperateLogServices operateLogServices,IWebHostEnvironment environment, ITasksQzServices tasksQzServices,ITasksLogServices tasksLogServices)
- :base(tasksQzServices, tasksLogServices)
+ public Job_OperateLog_Quartz(IOperateLogServices operateLogServices, IWebHostEnvironment environment, ITasksQzServices tasksQzServices, ITasksLogServices tasksLogServices)
+ : base(tasksQzServices, tasksLogServices)
{
- _operateLogServices = operateLogServices;
- _environment = environment;
+ _operateLogServices = operateLogServices;
+ _environment = environment;
}
+
public async Task Execute(IJobExecutionContext context)
{
var executeLog = await ExecuteJob(context, async () => await Run(context));
}
+
public async Task Run(IJobExecutionContext context)
{
@@ -78,7 +80,4 @@ public async Task Run(IJobExecutionContext context)
}
}
}
-
-
-
-}
+}
\ No newline at end of file
diff --git a/Blog.Core.Tests/DependencyInjection/DI_Test.cs b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
index ff2c74cd..d425fa01 100644
--- a/Blog.Core.Tests/DependencyInjection/DI_Test.cs
+++ b/Blog.Core.Tests/DependencyInjection/DI_Test.cs
@@ -59,7 +59,6 @@ public IContainer DICollections()
services.AddAutoMapper(typeof(Startup));
services.AddSingleton(new AppSettings(basePath));
- services.AddSingleton(new LogLock(basePath));
services.AddScoped();
services.AddScoped();
diff --git a/Blog.Core.sln b/Blog.Core.sln
index c8f61505..bf4f65cb 100644
--- a/Blog.Core.sln
+++ b/Blog.Core.sln
@@ -57,6 +57,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Blog.Core.Serilog.Es", "Blo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ocelot.Provider.Nacos", "Ocelot.Provider.Nacos\Ocelot.Provider.Nacos.csproj", "{6463FB13-5F01-4A1D-8B62-A454FB3812EB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Blog.Core.Serilog", "Blog.Core.Serilog\Blog.Core.Serilog.csproj", "{7F9057F0-ED8D-4694-B590-7D75C012DF00}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -119,6 +121,10 @@ Global
{6463FB13-5F01-4A1D-8B62-A454FB3812EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6463FB13-5F01-4A1D-8B62-A454FB3812EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6463FB13-5F01-4A1D-8B62-A454FB3812EB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7F9057F0-ED8D-4694-B590-7D75C012DF00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F9057F0-ED8D-4694-B590-7D75C012DF00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F9057F0-ED8D-4694-B590-7D75C012DF00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F9057F0-ED8D-4694-B590-7D75C012DF00}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
From 070e441bc02ef0a1e410d176cf953e6549824721 Mon Sep 17 00:00:00 2001
From: anjoy8 <3143422472@qq.com>
Date: Sun, 2 Apr 2023 15:16:37 +0800
Subject: [PATCH 051/190] feat: :accept: change api param
---
Blog.Core.Api/Blog.Core.xml | 50 ++++++++---------
Blog.Core.Api/Controllers/BlogController.cs | 10 ++--
.../Controllers/DepartmentController.cs | 4 +-
Blog.Core.Api/Controllers/ModuleController.cs | 2 +-
.../Controllers/PermissionController.cs | 55 +++++++------------
Blog.Core.Api/Controllers/RoleController.cs | 2 +-
.../Controllers/TasksQzController.cs | 18 +++---
Blog.Core.Api/Controllers/TopicController.cs | 6 +-
.../Controllers/TopicDetailController.cs | 8 +--
.../Controllers/TransactionController.cs | 6 +-
Blog.Core.Api/Controllers/UserController.cs | 4 +-
.../Controllers/UserRoleController.cs | 2 +-
Blog.Core.Common/Helper/RecursionHelper.cs | 4 +-
Blog.Core.IServices/IBlogArticleServices.cs | 2 +-
Blog.Core.IServices/ITasksLogServices.cs | 4 +-
Blog.Core.IServices/IUserRoleServices.cs | 4 +-
Blog.Core.Model/ViewModels/BlogViewModels.cs | 2 +-
Blog.Core.Model/ViewModels/SysUserInfoDto.cs | 6 +-
Blog.Core.Services/BlogArticleServices.cs | 2 +-
Blog.Core.Services/TasksLogServices.cs | 4 +-
Blog.Core.Services/UserRoleServices.cs | 4 +-
.../Controller_Test/BlogController_Should.cs | 2 +-
22 files changed, 93 insertions(+), 108 deletions(-)
diff --git a/Blog.Core.Api/Blog.Core.xml b/Blog.Core.Api/Blog.Core.xml
index 79325e37..19f0ad64 100644
--- a/Blog.Core.Api/Blog.Core.xml
+++ b/Blog.Core.Api/Blog.Core.xml
@@ -26,14 +26,14 @@
-
+
获取博客详情
-
+
获取详情【无权限】
@@ -67,7 +67,7 @@
-
+
删除博客
@@ -276,7 +276,7 @@
-
+
删除一条接口
@@ -384,7 +384,7 @@
-
+
查询树形 Table
@@ -406,7 +406,7 @@
-
+
获取菜单树
@@ -428,7 +428,7 @@
-
+
通过角色获取菜单
@@ -442,7 +442,7 @@
-
+
删除菜单
@@ -456,7 +456,7 @@
-
+
系统接口菜单同步接口
@@ -493,7 +493,7 @@
-
+
删除角色
@@ -522,42 +522,42 @@
-
+
删除一个任务
-
+
启动计划任务
-
+
停止一个计划任务
-
+
暂停一个计划任务
-
+
恢复一个计划任务
-
+
重启一个计划任务
@@ -570,20 +570,20 @@
-
+
立即执行任务
-
+
获取任务运行日志
-
+
任务概况
@@ -629,7 +629,7 @@
-
+
获取详情【无权限】
@@ -650,14 +650,14 @@
-
+
删除 bug
-
+
测试事务在AOP中的使用
@@ -712,7 +712,7 @@
-
+
删除用户
@@ -748,7 +748,7 @@
-
+
新建用户角色关系
@@ -1203,7 +1203,7 @@
关键字
-
+
获取部门树
diff --git a/Blog.Core.Api/Controllers/BlogController.cs b/Blog.Core.Api/Controllers/BlogController.cs
index 83fad967..fbc67e12 100644
--- a/Blog.Core.Api/Controllers/BlogController.cs
+++ b/Blog.Core.Api/Controllers/BlogController.cs
@@ -83,7 +83,7 @@ public async Task>> Get(int id, int page = 1
[HttpGet("{id}")]
//[Authorize(Policy = "Scope_BlogModule_Policy")]
[Authorize]
- public async Task> Get(int id)
+ public async Task> Get(long id)
{
return Success(await _blogArticleServices.GetBlogDetails(id));
}
@@ -96,7 +96,7 @@ public async Task> Get(int id)
///
[HttpGet]
[Route("DetailNuxtNoPer")]
- public async Task> DetailNuxtNoPer(int id)
+ public async Task> DetailNuxtNoPer(long id)
{
_logger.LogInformation("xxxxxxxxxxxxxxxxxxx");
return Success(await _blogArticleServices.GetBlogDetails(id));
@@ -104,7 +104,7 @@ public async Task> DetailNuxtNoPer(int id)
[HttpGet]
[Route("GoUrl")]
- public async Task GoUrl(int id = 0)
+ public async Task GoUrl(long id = 0)
{
var response = await _blogArticleServices.QueryById(id);
if (response != null && response.bsubmitter.IsNotEmptyOrNull())
@@ -136,7 +136,7 @@ public async Task>> GetBlogsByTypesForMVP(string
[HttpGet]
[Route("GetBlogByIdForMVP")]
- public async Task> GetBlogByIdForMVP(int id = 0)
+ public async Task> GetBlogByIdForMVP(long id = 0)
{
if (id > 0)
{
@@ -247,7 +247,7 @@ public async Task> Put([FromBody] BlogArticle BlogArticle)
[HttpDelete]
[Authorize(Permissions.Name)]
[Route("Delete")]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
if (id > 0)
{
diff --git a/Blog.Core.Api/Controllers/DepartmentController.cs b/Blog.Core.Api/Controllers/DepartmentController.cs
index b8174e90..faf1f850 100644
--- a/Blog.Core.Api/Controllers/DepartmentController.cs
+++ b/Blog.Core.Api/Controllers/DepartmentController.cs
@@ -109,7 +109,7 @@ public async Task>> GetTreeTable(long f = 0, strin
///
///
[HttpGet]
- public async Task> GetDepartmentTree(int pid = 0)
+ public async Task> GetDepartmentTree(long pid = 0)
{
var departments = await _departmentServices.Query(d => d.IsDeleted == false);
var departmentTrees = (from child in departments
@@ -168,7 +168,7 @@ public async Task> Put([FromBody] Department request)
}
[HttpDelete]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
var data = new MessageModel();
var model = await _departmentServices.QueryById(id);
diff --git a/Blog.Core.Api/Controllers/ModuleController.cs b/Blog.Core.Api/Controllers/ModuleController.cs
index 2da284ba..27e6f4db 100644
--- a/Blog.Core.Api/Controllers/ModuleController.cs
+++ b/Blog.Core.Api/Controllers/ModuleController.cs
@@ -119,7 +119,7 @@ public async Task> Put([FromBody] Modules module)
///
// DELETE: api/ApiWithActions/5
[HttpDelete]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
if (id <= 0)
return Failed("缺少参数");
diff --git a/Blog.Core.Api/Controllers/PermissionController.cs b/Blog.Core.Api/Controllers/PermissionController.cs
index 059e9b18..7346cc21 100644
--- a/Blog.Core.Api/Controllers/PermissionController.cs
+++ b/Blog.Core.Api/Controllers/PermissionController.cs
@@ -79,21 +79,6 @@ public async Task>> Get(int page = 1, string
key = "";
}
- #region 舍弃
- //var permissions = await _permissionServices.Query(a => a.IsDeleted != true);
- //if (!string.IsNullOrEmpty(key))
- //{
- // permissions = permissions.Where(t => (t.Name != null && t.Name.Contains(key))).ToList();
- //}
- ////筛选后的数据总数
- //totalCount = permissions.Count;
- ////筛选后的总页数
- //pageCount = (Math.Ceiling(totalCount.ObjToDecimal() / intTotalCount.ObjToDecimal())).ObjToInt();
- //permissions = permissions.OrderByDescending(d => d.Id).Skip((page - 1) * intTotalCount).Take(intTotalCount).ToList();
- #endregion
-
-
-
permissions = await _permissionServices.QueryPage(a => a.IsDeleted != true && (a.Name != null && a.Name.Contains(key)), page, pageSize, " Id desc ");
@@ -162,7 +147,7 @@ public async Task>> Get(int page = 1, string
///
[HttpGet]
[AllowAnonymous]
- public async Task>> GetTreeTable(int f = 0, string key = "")
+ public async Task>> GetTreeTable(long f = 0, string key = "")
{
List permissions = new List();
var apiList = await _moduleServices.Query(d => d.IsDeleted == false);
@@ -245,7 +230,7 @@ public async Task> Post([FromBody] Permission permission)
///
[HttpPost]
public async Task> Assign([FromBody] AssignView assignView)
- {
+ {
if (assignView.rid > 0)
{
//开启事务
@@ -258,7 +243,7 @@ public async Task> Assign([FromBody] AssignView assignView)
var permissions = await _permissionServices.Query(d => d.IsDeleted == false);
List new_rmps = new List();
- var nowTime = _permissionServices.Db.GetDate();
+ var nowTime = _permissionServices.Db.GetDate();
foreach (var item in assignView.pids)
{
var moduleid = permissions.Find(p => p.Id == item)?.Mid;
@@ -268,7 +253,7 @@ public async Task> Assign([FromBody] AssignView assignView)
{
IsDeleted = false,
RoleId = assignView.rid,
- ModuleId = moduleid.ObjToInt(),
+ ModuleId = moduleid.ObjToLong(),
PermissionId = item,
CreateId = find_old_rmps == null ? _user.ID : find_old_rmps.CreateId,
CreateBy = find_old_rmps == null ? _user.Name : find_old_rmps.CreateBy,
@@ -280,7 +265,7 @@ public async Task> Assign([FromBody] AssignView assignView)
};
new_rmps.Add(roleModulePermission);
}
- if(new_rmps.Count>0) await _roleModulePermissionServices.Add(new_rmps);
+ if (new_rmps.Count > 0) await _roleModulePermissionServices.Add(new_rmps);
_unitOfWorkManage.CommitTran();
}
catch (Exception)
@@ -294,7 +279,7 @@ public async Task> Assign([FromBody] AssignView assignView)
else
{
return Failed("请选择要操作的角色");
- }
+ }
}
@@ -305,7 +290,7 @@ public async Task> Assign([FromBody] AssignView assignView)
///
///
[HttpGet]
- public async Task> GetPermissionTree(int pid = 0, bool needbtn = false)
+ public async Task> GetPermissionTree(long pid = 0, bool needbtn = false)
{
//var data = new MessageModel();
@@ -355,7 +340,7 @@ public async Task> GetNavigationBar(long uid)
var data = new MessageModel();
- var uidInHttpcontext1 = 0;
+ long uidInHttpcontext1 = 0;
var roleIds = new List();
// ids4和jwt切换
if (Permissions.IsUseIds4)
@@ -363,7 +348,7 @@ public async Task> GetNavigationBar(long uid)
// ids4
uidInHttpcontext1 = (from item in _httpContext.HttpContext.User.Claims
where item.Type == "sub"
- select item.Value).FirstOrDefault().ObjToInt();
+ select item.Value).FirstOrDefault().ObjToLong();
roleIds = (from item in _httpContext.HttpContext.User.Claims
where item.Type == "role"
select item.Value.ObjToLong()).ToList();
@@ -371,7 +356,7 @@ public async Task> GetNavigationBar(long uid)
else
{
// jwt
- uidInHttpcontext1 = ((JwtHelper.SerializeJwt(_httpContext.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "")))?.Uid).ObjToInt();
+ uidInHttpcontext1 = ((JwtHelper.SerializeJwt(_httpContext.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "")))?.Uid).ObjToLong();
roleIds = (await _userRoleServices.Query(d => d.IsDeleted == false && d.UserId == uid)).Select(d => d.RoleId.ObjToLong()).Distinct().ToList();
}
@@ -446,7 +431,7 @@ public async Task>> GetNavigationBarPro(long
{
var data = new MessageModel>();
- var uidInHttpcontext1 = 0;
+ long uidInHttpcontext1 = 0;
var roleIds = new List();
// ids4和jwt切换
if (Permissions.IsUseIds4)
@@ -454,7 +439,7 @@ public async Task>> GetNavigationBarPro(long
// ids4
uidInHttpcontext1 = (from item in _httpContext.HttpContext.User.Claims
where item.Type == "sub"
- select item.Value).FirstOrDefault().ObjToInt();
+ select item.Value).FirstOrDefault().ObjToLong();
roleIds = (from item in _httpContext.HttpContext.User.Claims
where item.Type == "role"
select item.Value.ObjToLong()).ToList();
@@ -462,7 +447,7 @@ public async Task>> GetNavigationBarPro(long
else
{
// jwt
- uidInHttpcontext1 = ((JwtHelper.SerializeJwt(_httpContext.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "")))?.Uid).ObjToInt();
+ uidInHttpcontext1 = ((JwtHelper.SerializeJwt(_httpContext.HttpContext.Request.Headers["Authorization"].ObjToString().Replace("Bearer ", "")))?.Uid).ObjToLong();
roleIds = (await _userRoleServices.Query(d => d.IsDeleted == false && d.UserId == uid)).Select(d => d.RoleId.ObjToLong()).Distinct().ToList();
}
@@ -519,14 +504,14 @@ orderby item.Id
///
[HttpGet]
[AllowAnonymous]
- public async Task> GetPermissionIdByRoleId(int rid = 0)
+ public async Task> GetPermissionIdByRoleId(long rid = 0)
{
//var data = new MessageModel();
var rmps = await _roleModulePermissionServices.Query(d => d.IsDeleted == false && d.RoleId == rid);
var permissionTrees = (from child in rmps
orderby child.Id
- select child.PermissionId.ObjToInt()).ToList();
+ select child.PermissionId.ObjToLong()).ToList();
var permissions = await _permissionServices.Query(d => d.IsDeleted == false);
List assignbtns = new List();
@@ -592,7 +577,7 @@ public async Task> Put([FromBody] Permission permission)
///
// DELETE: api/ApiWithActions/5
[HttpDelete]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
var data = new MessageModel();
if (id > 0)
@@ -654,7 +639,7 @@ public async Task> BatchPost([FromBody] List pe
/// 是否执行迁移到数据
///
[HttpGet]
- public async Task>> MigratePermission(string action = "", string controllerName = "", int pid = 0, bool isAction = false)
+ public async Task>> MigratePermission(string action = "", string controllerName = "", long pid = 0, bool isAction = false)
{
var data = new MessageModel>();
if (controllerName.IsNullOrEmpty())
@@ -776,12 +761,12 @@ public async Task>> MigratePermission(string actio
public class AssignView
{
- public List pids { get; set; }
- public int rid { get; set; }
+ public List pids { get; set; }
+ public long rid { get; set; }
}
public class AssignShow
{
- public List permissionids { get; set; }
+ public List permissionids { get; set; }
public List assignbtns { get; set; }
}
diff --git a/Blog.Core.Api/Controllers/RoleController.cs b/Blog.Core.Api/Controllers/RoleController.cs
index c96502c8..0b93e943 100644
--- a/Blog.Core.Api/Controllers/RoleController.cs
+++ b/Blog.Core.Api/Controllers/RoleController.cs
@@ -112,7 +112,7 @@ public async Task> Put([FromBody] Role role)
///
// DELETE: api/ApiWithActions/5
[HttpDelete]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
var data = new MessageModel();
diff --git a/Blog.Core.Api/Controllers/TasksQzController.cs b/Blog.Core.Api/Controllers/TasksQzController.cs
index ca9d37bc..887cfcfc 100644
--- a/Blog.Core.Api/Controllers/TasksQzController.cs
+++ b/Blog.Core.Api/Controllers/TasksQzController.cs
@@ -172,7 +172,7 @@ public async Task> Put([FromBody] TasksQz tasksQz)
///
///
[HttpDelete]
- public async Task> Delete(int jobId)
+ public async Task> Delete(long jobId)
{
var data = new MessageModel();
@@ -221,7 +221,7 @@ public async Task> Delete(int jobId)
///
///
[HttpGet]
- public async Task> StartJob(int jobId)
+ public async Task> StartJob(long jobId)
{
var data = new MessageModel();
@@ -278,7 +278,7 @@ public async Task> StartJob(int jobId)
///
///
[HttpGet]
- public async Task> StopJob(int jobId)
+ public async Task> StopJob(long jobId)
{
var data = new MessageModel();
@@ -318,7 +318,7 @@ public async Task> StopJob(int jobId)
///
///
[HttpGet]
- public async Task> PauseJob(int jobId)
+ public async Task> PauseJob(long jobId)
{
var data = new MessageModel();
var model = await _tasksQzServices.QueryById(jobId);
@@ -372,7 +372,7 @@ public async Task> PauseJob(int jobId)
///
///
[HttpGet]
- public async Task> ResumeJob(int jobId)
+ public async Task> ResumeJob(long jobId)
{
var data = new MessageModel();
@@ -428,7 +428,7 @@ public async Task> ResumeJob(int jobId)
///
///
[HttpGet]
- public async Task> ReCovery(int jobId)
+ public async Task> ReCovery(long jobId)
{
var data = new MessageModel();
var model = await _tasksQzServices.QueryById(jobId);
@@ -507,7 +507,7 @@ public MessageModel> GetTaskNameSpace()
///
///
[HttpGet]
- public async Task> ExecuteJob(int jobId)
+ public async Task> ExecuteJob(long jobId)
{
var data = new MessageModel();
@@ -527,7 +527,7 @@ public async Task> ExecuteJob(int jobId)
///
///
[HttpGet]
- public async Task>> GetTaskLogs(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null)
+ public async Task>> GetTaskLogs(long jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null)
{
var model = await _tasksLogServices.GetTaskLogs(jobId, page, pageSize, runTimeStart, runTimeEnd);
return MessageModel>.Message(model.dataCount >= 0, "获取成功", model);
@@ -537,7 +537,7 @@ public async Task>> GetTaskLogs(int jobId, int
///
///
[HttpGet]
- public async Task> GetTaskOverview(int jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null, string type = "month")
+ public async Task> GetTaskOverview(long jobId, int page = 1, int pageSize = 10, DateTime? runTimeStart = null, DateTime? runTimeEnd = null, string type = "month")
{
var model = await _tasksLogServices.GetTaskOverview(jobId, runTimeStart, runTimeEnd, type);
return MessageModel.Message(true, "获取成功", model);
diff --git a/Blog.Core.Api/Controllers/TopicController.cs b/Blog.Core.Api/Controllers/TopicController.cs
index 308ad082..253f54ff 100644
--- a/Blog.Core.Api/Controllers/TopicController.cs
+++ b/Blog.Core.Api/Controllers/TopicController.cs
@@ -44,7 +44,7 @@ public async Task>> Get()
// GET: api/Topic/5
[HttpGet("{id}")]
- public string Get(int id)
+ public string Get(long id)
{
return "value";
}
@@ -57,13 +57,13 @@ public void Post([FromBody] string value)
// PUT: api/Topic/5
[HttpPut("{id}")]
- public void Put(int id, [FromBody] string value)
+ public void Put(long id, [FromBody] string value)
{
}
// DELETE: api/ApiWithActions/5
[HttpDelete("{id}")]
- public void Delete(int id)
+ public void Delete(long id)
{
}
}
diff --git a/Blog.Core.Api/Controllers/TopicDetailController.cs b/Blog.Core.Api/Controllers/TopicDetailController.cs
index 55af1a75..374aca24 100644
--- a/Blog.Core.Api/Controllers/TopicDetailController.cs
+++ b/Blog.Core.Api/Controllers/TopicDetailController.cs
@@ -42,7 +42,7 @@ public TopicDetailController(ITopicServices topicServices, ITopicDetailServices
[AllowAnonymous]
public async Task>> Get(int page = 1, string tname = "", string key = "", int intPageSize = 12)
{
- int tid = 0;
+ long tid = 0;
if (string.IsNullOrEmpty(key) || string.IsNullOrWhiteSpace(key))
{
@@ -56,7 +56,7 @@ public async Task>> Get(int page = 1, string
if (!string.IsNullOrEmpty(tname))
{
- tid = ((await _topicServices.Query(ts => ts.tName == tname)).FirstOrDefault()?.Id).ObjToInt();
+ tid = ((await _topicServices.Query(ts => ts.tName == tname)).FirstOrDefault()?.Id).ObjToLong();
}
@@ -81,7 +81,7 @@ public async Task>> Get(int page = 1, string
// GET: api/TopicDetail/5
[HttpGet("{id}")]
[AllowAnonymous]
- public async Task> Get(int id)
+ public async Task> Get(long id)
{
var data = new MessageModel();
var response = id > 0 ? await _topicDetailServices.QueryById(id) : new TopicDetail();
@@ -154,7 +154,7 @@ public async Task> Update([FromBody] TopicDetail topicDetai
///
// DELETE: api/ApiWithActions/5
[HttpDelete]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
var data = new MessageModel();
if (id > 0)
diff --git a/Blog.Core.Api/Controllers/TransactionController.cs b/Blog.Core.Api/Controllers/TransactionController.cs
index 67ab576e..9853d985 100644
--- a/Blog.Core.Api/Controllers/TransactionController.cs
+++ b/Blog.Core.Api/Controllers/TransactionController.cs
@@ -95,7 +95,7 @@ public async Task>> Get()
// GET: api/Transaction/5
[HttpGet("{id}")]
- public async Task> Get(int id)
+ public async Task> Get(long id)
{
return await _guestbookServices.TestTranInRepository();
}
@@ -126,7 +126,7 @@ public void Post([FromBody] string value)
// PUT: api/Transaction/5
[HttpPut("{id}")]
- public void Put(int id, [FromBody] string value)
+ public void Put(long id, [FromBody] string value)
{
}
@@ -136,7 +136,7 @@ public void Put(int id, [FromBody] string value)
///
///
[HttpDelete("{id}")]
- public async Task Delete(int id)
+ public async Task Delete(long id)
{
return await _guestbookServices.TestTranInRepositoryAOP();
}
diff --git a/Blog.Core.Api/Controllers/UserController.cs b/Blog.Core.Api/Controllers/UserController.cs
index 27989821..95137c8e 100644
--- a/Blog.Core.Api/Controllers/UserController.cs
+++ b/Blog.Core.Api/Controllers/UserController.cs
@@ -103,7 +103,7 @@ public async Task>> Get(int page = 1, str
return Success(data.ConvertTo(_mapper));
}
- private (string, List) GetFullDepartmentName(List departments, int departmentId)
+ private (string, List) GetFullDepartmentName(List departments, long departmentId)
{
var departmentModel = departments.FirstOrDefault(d => d.Id == departmentId);
if (departmentModel == null)
@@ -265,7 +265,7 @@ public async Task> Put([FromBody] SysUserInfoDto sysUserInf
///
// DELETE: api/ApiWithActions/5
[HttpDelete]
- public async Task> Delete(int id)
+ public async Task> Delete(long id)
{
var data = new MessageModel();
if (id > 0)
diff --git a/Blog.Core.Api/Controllers/UserRoleController.cs b/Blog.Core.Api/Controllers/UserRoleController.cs
index c21ec6f4..693a68b8 100644
--- a/Blog.Core.Api/Controllers/UserRoleController.cs
+++ b/Blog.Core.Api/Controllers/UserRoleController.cs
@@ -80,7 +80,7 @@ public async Task> AddRole(string roleName)
///
///
[HttpGet]
- public async Task> AddUserRole(int uid, int rid)
+ public async Task> AddUserRole(long uid, long rid)
{
return new MessageModel()
{
diff --git a/Blog.Core.Common/Helper/RecursionHelper.cs b/Blog.Core.Common/Helper/RecursionHelper.cs
index f6f21a38..092a0678 100644
--- a/Blog.Core.Common/Helper/RecursionHelper.cs
+++ b/Blog.Core.Common/Helper/RecursionHelper.cs
@@ -8,7 +8,7 @@ namespace Blog.Core.Common.Helper
///
public static class RecursionHelper
{
- public static void LoopToAppendChildren(List all, PermissionTree curItem, int pid, bool needbtn)
+ public static void LoopToAppendChildren(List all, PermissionTree curItem, long pid, bool needbtn)
{
var subItems = all.Where(ee => ee.Pid == curItem.value).ToList();
@@ -52,7 +52,7 @@ public static void LoopToAppendChildren(List all, PermissionTree
LoopToAppendChildren(all, subItem, pid, needbtn);
}
}
- public static void LoopToAppendChildren(List all, DepartmentTree curItem, int pid)
+ public static void LoopToAppendChildren(List all, DepartmentTree curItem, long pid)
{
var subItems = all.Where(ee => ee.Pid == curItem.value).ToList();
diff --git a/Blog.Core.IServices/IBlogArticleServices.cs b/Blog.Core.IServices/IBlogArticleServices.cs
index 23e6081b..a38826fb 100644
--- a/Blog.Core.IServices/IBlogArticleServices.cs
+++ b/Blog.Core.IServices/IBlogArticleServices.cs
@@ -9,7 +9,7 @@ namespace Blog.Core.IServices
public interface IBlogArticleServices :IBaseServices
{
Task> GetBlogs();
- Task GetBlogDetails(int id);
+ Task GetBlogDetails(long id);
}
diff --git a/Blog.Core.IServices/ITasksLogServices.cs b/Blog.Core.IServices/ITasksLogServices.cs
index fb15c8dd..fb6ad8a7 100644
--- a/Blog.Core.IServices/ITasksLogServices.cs
+++ b/Blog.Core.IServices/ITasksLogServices.cs
@@ -12,8 +12,8 @@ namespace Blog.Core.IServices
///
public interface ITasksLogServices :IBaseServices
{
- public Task> GetTaskLogs(int jobId, int page, int intPageSize,DateTime? runTime,DateTime? endTime);
- public Task GetTaskOverview(int jobId, DateTime? runTime, DateTime? endTime, string type);
+ public Task> GetTaskLogs(long jobId, int page, int intPageSize,DateTime? runTime,DateTime? endTime);
+ public Task GetTaskOverview(long jobId, DateTime? runTime, DateTime? endTime, string type);
}
}
\ No newline at end of file
diff --git a/Blog.Core.IServices/IUserRoleServices.cs b/Blog.Core.IServices/IUserRoleServices.cs
index 9e7d3d29..91272a09 100644
--- a/Blog.Core.IServices/IUserRoleServices.cs
+++ b/Blog.Core.IServices/IUserRoleServices.cs
@@ -10,8 +10,8 @@ namespace Blog.Core.IServices
public interface IUserRoleServices :IBaseServices
{
- Task SaveUserRole(int uid, int rid);
- Task GetRoleIdByUid(int uid);
+ Task SaveUserRole(long uid, long rid);
+ Task GetRoleIdByUid(long uid);
}
}
diff --git a/Blog.Core.Model/ViewModels/BlogViewModels.cs b/Blog.Core.Model/ViewModels/BlogViewModels.cs
index 411a8ef7..86c16618 100644
--- a/Blog.Core.Model/ViewModels/BlogViewModels.cs
+++ b/Blog.Core.Model/ViewModels/BlogViewModels.cs
@@ -10,7 +10,7 @@ public class BlogViewModels
///
///
///
- public int bID { get; set; }
+ public long bID { get; set; }
/// 创建人
///
///
diff --git a/Blog.Core.Model/ViewModels/SysUserInfoDto.cs b/Blog.Core.Model/ViewModels/SysUserInfoDto.cs
index 33d84161..3b5451f0 100644
--- a/Blog.Core.Model/ViewModels/SysUserInfoDto.cs
+++ b/Blog.Core.Model/ViewModels/SysUserInfoDto.cs
@@ -3,13 +3,13 @@
namespace Blog.Core.Model.ViewModels
{
- public class SysUserInfoDto : SysUserInfoDtoRoot
+ public class SysUserInfoDto : SysUserInfoDtoRoot
{
public string uLoginName { get; set; }
public string uLoginPWD { get; set; }
public string uRealName { get; set; }
public int uStatus { get; set; }
- public int DepartmentId { get; set; }
+ public long DepartmentId { get; set; }
public string uRemark { get; set; }
public System.DateTime uCreateTime { get; set; } = DateTime.Now;
public System.DateTime uUpdateTime { get; set; } = DateTime.Now;
@@ -22,7 +22,7 @@ public class SysUserInfoDto : SysUserInfoDtoRoot
public string addr { get; set; }
public bool tdIsDelete { get; set; }
public List RoleNames { get; set; }
- public List Dids { get; set; }
+ public List Dids { get; set; }
public string DepartmentName { get; set; }
}
}
diff --git a/Blog.Core.Services/BlogArticleServices.cs b/Blog.Core.Services/BlogArticleServices.cs
index eeff04e3..67ea2b9e 100644
--- a/Blog.Core.Services/BlogArticleServices.cs
+++ b/Blog.Core.Services/BlogArticleServices.cs
@@ -23,7 +23,7 @@ public BlogArticleServices(IMapper mapper)
///
///
///
- public async Task GetBlogDetails(int id)
+ public async Task GetBlogDetails(long id)
{
// 此处想获取上一条下一条数据,因此将全部数据list出来,有好的想法请提出
//var bloglist = await base.Query(a => a.IsDeleted==false, a => a.bID);
diff --git a/Blog.Core.Services/TasksLogServices.cs b/Blog.Core.Services/TasksLogServices.cs
index 49393cd4..07d95f1f 100644
--- a/Blog.Core.Services/TasksLogServices.cs
+++ b/Blog.Core.Services/TasksLogServices.cs
@@ -14,7 +14,7 @@ namespace Blog.Core.Services
{
public partial class TasksLogServices : BaseServices, ITasksLogServices
{
- public async Task> GetTaskLogs(int jobId, int page, int intPageSize, DateTime? runTime, DateTime? endTime)
+ public async Task> GetTaskLogs(long jobId, int page, int intPageSize, DateTime? runTime, DateTime? endTime)
{
RefAsync totalCount = 0;
Expression> whereExpression = log => true;
@@ -41,7 +41,7 @@ public async Task> GetTaskLogs(int jobId, int page, int intP
.ToPageListAsync(page, intPageSize, totalCount);
return new PageModel(page, totalCount, intPageSize, data);
}
- public async Task GetTaskOverview(int jobId, DateTime? runTime, DateTime? endTime, string type)
+ public async Task GetTaskOverview(long jobId, DateTime? runTime, DateTime? endTime, string type)
{
//按年
if ("year".Equals(type))
diff --git a/Blog.Core.Services/UserRoleServices.cs b/Blog.Core.Services/UserRoleServices.cs
index 38f524da..26194837 100644
--- a/Blog.Core.Services/UserRoleServices.cs
+++ b/Blog.Core.Services/UserRoleServices.cs
@@ -19,7 +19,7 @@ public class UserRoleServices : BaseServices, IUserRoleServices
///
///
///
- public async Task SaveUserRole(int uid, int rid)
+ public async Task SaveUserRole(long uid, long rid)
{
UserRole userRole = new UserRole(uid, rid);
@@ -42,7 +42,7 @@ public async Task SaveUserRole(int uid, int rid)
[Caching(AbsoluteExpiration = 30)]
- public async Task GetRoleIdByUid(int uid)
+ public async Task GetRoleIdByUid(long uid)
{
return ((await base.Query(d => d.UserId == uid)).OrderByDescending(d => d.Id).LastOrDefault()?.RoleId).ObjToInt();
}
diff --git a/Blog.Core.Tests/Controller_Test/BlogController_Should.cs b/Blog.Core.Tests/Controller_Test/BlogController_Should.cs
index 3d1e3178..59d42ae0 100644
--- a/Blog.Core.Tests/Controller_Test/BlogController_Should.cs
+++ b/Blog.Core.Tests/Controller_Test/BlogController_Should.cs
@@ -53,7 +53,7 @@ public async void Get_Blog_Page_Test()
[Fact]
public async void Get_Blog_Test()
{
- MessageModel blogVo = await blogController.Get(1);
+ MessageModel blogVo = await blogController.Get(1.ObjToLong());
Assert.NotNull(blogVo);
}
From 5e84e11ca84f3bf245ef4307e17b48cd2c20b265 Mon Sep 17 00:00:00 2001
From: LemonNoCry <773596523@qq.com>
Date: Sun, 2 Apr 2023 15:56:20 +0800
Subject: [PATCH 052/190] =?UTF-8?q?=E2=9C=A8=20=E8=B0=83=E6=95=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 1 +
Blog.Core.Api/Blog.Core.Api.csproj | 1 +
Blog.Core.Model/Models/PasswordLib.cs | 2 +-
Blog.Core.Tests/WMBlog.db | Bin 200704 -> 0 bytes
4 files changed, 3 insertions(+), 1 deletion(-)
delete mode 100644 Blog.Core.Tests/WMBlog.db
diff --git a/.gitignore b/.gitignore
index 4f554bea..fa4a3448 100644
--- a/.gitignore
+++ b/.gitignore
@@ -358,3 +358,4 @@ Blog.Core.Api/wwwroot/ui/
*.db
/Blog.Core.Api/WMBlog.db-journal
Logs
+*.db
diff --git a/Blog.Core.Api/Blog.Core.Api.csproj b/Blog.Core.Api/Blog.Core.Api.csproj
index 3bf64399..0d32998e 100644
--- a/Blog.Core.Api/Blog.Core.Api.csproj
+++ b/Blog.Core.Api/Blog.Core.Api.csproj
@@ -52,6 +52,7 @@
+
diff --git a/Blog.Core.Model/Models/PasswordLib.cs b/Blog.Core.Model/Models/PasswordLib.cs
index 2b43c265..9eb9292f 100644
--- a/Blog.Core.Model/Models/PasswordLib.cs
+++ b/Blog.Core.Model/Models/PasswordLib.cs
@@ -7,7 +7,7 @@ namespace Blog.Core.Model.Models
/// 密码库表
///
[SugarTable("PasswordLib", "密码库表")]//('数据库表名','数据库表备注')
- [TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库,名字是appsettings.json 的 ConnId')
+ //[TenantAttribute("WMBLOG_MYSQL_2")] //('代表是哪个数据库,名字是appsettings.json 的 ConnId')
public class PasswordLib
{
[SugarColumn(IsNullable = false, IsPrimaryKey = true, IsIdentity = true)]
diff --git a/Blog.Core.Tests/WMBlog.db b/Blog.Core.Tests/WMBlog.db
deleted file mode 100644
index 4931b9674dbdfa61661ba06a34e3c55254029529..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 200704
zcmeIbc~o0hnlCDW&;ST|h%Jvn#&K+dF-Xita*D|g6%QEWOqIkX;22aEk|GHYsjez8
z1_L(6PCO6s5Mw*B4UXdk4A{K)x>mog*WK&Z>Z-S@*Q#D`z1O94ByM+Cs{iP^w^!ZQ
z^}c~*?ZtX@N&Y@SRmmwm@z
zkjZ2j@P8xxKlE7wUlgGq@LxISd#tY+vJLBNlHhKl?%z2BO=tLJ=8uBfdltE)29m6dO;
zGGuV>WUSLBXVh%1uFNpl9A2u4avQeqs55Ney>+XhrnY)pS?$|~*Q?$(lRxBc&CTT9t$7o$LU)bA
zyJZax&Q^zayS0Uiq>9q9%WL(vdN?K{bA#wrZnx82fs}~fe+}|ka{$Z^*$|~2rTCzg
z@_21d#}vsb+?3Tz)!C4xjquG2-*`FQ?LwEQNU+uF@q)QAQ+UA!Q3DK_9cgNne$^^@
zXA|r89WKfZSX-SUse{wPzdUXbsj?Jn1S2sy9Q`81EJ?;XIFrD;j*S{7{5Z
zKH<~U4iEyiy@$kA<9l4yg3RCqF(bLg>ZTmtXx)a)!|y3o`t)>pr-lvEEvS;KcRKfl
zzo__u8ooZmP_4H+n|OBc=xtytP*g{9D^OmNRw!`}VOzk94p+0&!3iCx%z3wW?u32No-No=j$g=^(X%4KzXTfiBSZ%RJHksC9l7?qq_
z%5Fs!pQo8;bU^{MygWMjHH0ZT!B)x&g^iPOHc2?>r!9)1hMDaW@SuhL1>Vi*!h~%L
z13yz~;+7bJ{B$M8Ce|84t=_Ro!S=4YD%b*34)I*(_Szck6z6La-=&;8tWWFX?_AY;
zTI*YEUN6@bh5W#-_u9O6Zr~Rba{F2J4N$C_obD+CydElKFT^It+k(PV?{!=E?zJ_D
z^c2{N7c{h>=-%Gi5;KW-Cy3|$dU5aa)6`NeR`sv)x`
zL8;HmlE2MT;`zW19a4^6NtmycJLDizg@JFkIKdBlm
z{Dnb3`49#O1B3y>0AYYIKo}ql5C#YXgaN_;VSq63XUqT^|EK8Qmg#<{`;G1wx}WI=
zbvJdVbzQnvoeeIN4`F~XKo}ql5C#YXgaN_;VSq3|7$6J~1_%RFF_4y$xJn+G|D;Jy
zPF$|3vwHSy&wuVZ|Yqiy)-GYAOWR;89y)qvxaiFz+^3$8zpN~D-svU(XEwfiGUorbtokvak(4|c($a;
zK{sa(4|)GTl@rN5!T@1_FhCd}3=jqg1B3y>0AYYIKo}ql{CO~d#{cq^@50AYYIKo}ql5C#YX&&)tio;*#aKU}h=zf`Wt%af_CjV(3@^VPAy&>7~;1Ez2A
zoAHa))w>K1>VU!8*l0LF)qBw1Ti=Wy_c&p5oda&CqiJJZGi7k2)yf{&eaPUlHc^HK
ztHa^+8tN&7m0fEL*XyYUE9@R&@Up34e+0M&3*PtInp$C}9C#s!_Uy5uZN1netQwmK
zw#3Lf0nzP8a-z
zEvtt2zi96@@EIoAwF$qgHK15|ld3mVINcOWziZQWr`HBM7GMwWcI*FiUb8wH
zVHY9;BrzPKyoN^Dy$aqAJE+EB0t|;X)G*{8EY8g>g6$CUg7;t-BM6vHx}m>=jH^{)-)gTKql>m8mqTCcnucXLr`y{yv@$W*m=aM(2MlgX@Zs*
z>fF`_o1@84X>)_wu$P3PV&l6=6z2flMmtWS9D3g6^R&y^>TaMy?kaP54p8pUFC!G^
zy*5W9TkcT#Uh6SfT`qgbYc8kL?g^?ht6QE7Nf{M)bZisp|yh2}pV#+m^Wak>;pCLDQBl}O}
z5*q(&Qs0y5KGtQY{Z-l??SI$yX){v)H@HMTgaN_;VSq3|7$6J~1_%R$0m1-b;Mo~y
zfbGQ=8Rx4t>a0>(sXTXm@%pM=%<-f2(D*mw-A4b|k#EL(C{LiRogTmDzj%cH_#u7&
zmMPa{%FfM40~cfAMq~cQ{GtsoRux<>fFTXKtbSjumCesu7z9!0u76{96=?B2z7}Xd
z?Z0$&e=9W|fXOHVkiQXMwyCtTr6rt97}w{or%#^n-yNbK^s{;BHu<04gsfy|Pk~gh
zv7mUPF;9rZxva1$qoDHE(>;A$DC4t188_yOL4__SQc2*NoTWk5G`Z`I>&q+NsL7@u
zPte1k(A`~=9e42esk4;3(IkeGyD>i><&;v0!}vyenXiU14E{bPOn%8mQ&bQXYz$wf
z62)QYAg}Mxb5rlUq)}_M(lZ0uiv#WitQ&*{d^>
zk}yCRAPf)&2m^!x!T@1_FhCd}3=jqg1K(B#(Aj(my5A%7*P^re(pG67Y2QfwZR*j~
z#zW2sD5s*Y@k0CRDIbED2apvOk7E*o4iz*DEmb9elM
z*O?QybKqJ|L?EY$@}|ObH@g1;(>4Z4{3pBUQ|CqIG~mY_QL`V=<)+n(WST{5g=V3n
z$XGb`%WMF(r(^)q_cDb@Wlb=t!;p=$o^7Bf?oPH{WroM--fPT>0lNQF=1Rxpg_Eo?
zY}#4L_Q6%)4P&;@n81l)y8kTQc?W1`&JEBL=UCirPKOO9#LNn^+W^RGqLAtCYm*ml
z!UQyW@CJ*Cwxq~uWY64_?Bspv$jLdv+=iXZ!7@n)d-0jUjFQ3H6ILQRw+XYhh4R8P
z^+5OM%$4gbop4}YaA%MlxVPQ9-`2!V8Y{QD^-{~w!4=4c5}^&gi7WK|^XOS?XP?l9
zGT5Y~$srk;T8@y@BgkvmN+lS^{9szZ^q;J6Z3;ZPMfVTKS4p%i1DNyzaTw6a=8m&J
z3!+#8+z*zbTybg&oGV-@1a5y6=y}K@!ZCwXjteHsNx-r#L0Fvn4`cZz2AR{3qp(_~
zK-u*Oic|726fXHfC|vTTWNfi$#&Bo|(V&8t0M#yA1Xx)+#N#8-f0^z(!(2NhECT=<
zDV1I~MM*Hh^#aOmRD=dYhP6NlFEMbO3lSoxJ?90EIHIKRaW6oCoLYt#KB9nrc1egPv3j92(2Ejj+1b{QQwmTUD52imtA;EYanDc#qY@aBpiv2q4VPR`=cH6IPn#_6rcY05{eTg2j;bK0PwZ=)W0JK^=qQk!%`kt
zCB)HK$rnE|36XpZ|HXxn*Xo+H|+tf
zJhd}bo^mE7H~H_9-_!hy<}Wm<>PzZZRHLfbl)q9^N&lYolO&zu6Ge97&l2BF_^$~c
zCMe}Mw??CZnO`tdCAb7YE;rD_w|q};;~C46Ck3lkQZT6>VAMhw
zJR=!TsFw_rv7!}b^c&Zx1u*KI$We