Merge branch 'Test.Study' of http://192.168.3.68:2000/XCKJ/irc-netcore-api into Test.Study
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
84e2e14b73
|
@ -1,126 +0,0 @@
|
|||
using System;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using System.Threading.Tasks;
|
||||
using MassTransit;
|
||||
using MassTransit.NewIdProviders;
|
||||
using System.IO;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public readonly string environment;
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enviromentName))
|
||||
{
|
||||
|
||||
var index = Array.IndexOf(args, "--env");
|
||||
enviromentName = index > -1
|
||||
? args[index + 1]
|
||||
: "Development";
|
||||
}
|
||||
|
||||
//Dicom 浏览
|
||||
//ImageManager.SetImplementation(WinFormsImageManager.Instance);
|
||||
|
||||
var host = CreateHostBuilder(args)
|
||||
.UseEnvironment(enviromentName) //命令行传入环境
|
||||
.ConfigureAppConfiguration((hostContext, config) =>
|
||||
{
|
||||
|
||||
//Console.WriteLine(hostContext.HostingEnvironment.EnvironmentName);
|
||||
config.AddJsonFile("appsettings.json", false, true)
|
||||
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
|
||||
})
|
||||
.Build();
|
||||
|
||||
|
||||
//// Serilog
|
||||
SerilogExtension.AddSerilogSetup(enviromentName, host.Services);
|
||||
|
||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:windows");
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:linux");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:OSX or FreeBSD");
|
||||
}
|
||||
|
||||
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||
|
||||
|
||||
host.Run();
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.UseWindowsService()
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.ConfigureKestrel((context, options) =>
|
||||
{
|
||||
//设置应用服务器Kestrel请求体最大为1GB // if don't set default value is: 30 MB
|
||||
options.Limits.MaxRequestBodySize = long.MaxValue;
|
||||
options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(30);
|
||||
options.Limits.RequestHeadersTimeout = TimeSpan.FromMinutes(20);
|
||||
|
||||
});
|
||||
//webBuilder.UseSerilog();//在宿主机启动的时候配置serilog,与微软ILogger进行整合
|
||||
webBuilder.UseStartup<Startup>();
|
||||
}).UseSerilog()
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
|
||||
|
||||
|
||||
private static async Task InitCache(IHost host)
|
||||
{
|
||||
var _repository = host.Services.GetService(typeof(IRepository)) as IRepository;
|
||||
|
||||
//初始化 国际化数据,并且监测国际化文件变更
|
||||
//await InternationalizationHelper.InitInternationlizationDataAndWatchJsonFileAsync(_repository);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,306 @@
|
|||
using System;
|
||||
using Autofac.Extensions.DependencyInjection;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Serilog;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using System.Threading.Tasks;
|
||||
using MassTransit;
|
||||
using MassTransit.NewIdProviders;
|
||||
using System.IO;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using IRaCIS.Core.API;
|
||||
using Autofac;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using LogDashboard;
|
||||
using OfficeOpenXml.Utils;
|
||||
|
||||
|
||||
|
||||
#region 获取环境变量
|
||||
//以配置文件为准,否则 从url中取环境值(服务以命令行传递参数启动,配置文件配置了就不需要传递环境参数)
|
||||
var config = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var enviromentName = config["ASPNETCORE_ENVIRONMENT"];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(enviromentName))
|
||||
{
|
||||
|
||||
var index = Array.IndexOf(args, "--env");
|
||||
enviromentName = index > -1
|
||||
? args[index + 1]
|
||||
: "Development";
|
||||
}
|
||||
#endregion
|
||||
|
||||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
|
||||
{
|
||||
EnvironmentName = enviromentName
|
||||
});
|
||||
|
||||
#region 兼容windows 服务命令行的方式
|
||||
|
||||
//foreach (var arg in args)
|
||||
//{
|
||||
// Console.WriteLine(arg);
|
||||
//}
|
||||
|
||||
int urlsIndex = Array.FindIndex(args, arg => arg != null && arg.StartsWith("--urls"));
|
||||
|
||||
if (urlsIndex > -1)
|
||||
{
|
||||
var url = args[urlsIndex].Substring("--urls=".Length);
|
||||
Console.WriteLine(url);
|
||||
builder.WebHost.UseUrls(url);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 主机配置
|
||||
|
||||
|
||||
NewId.SetProcessIdProvider(new CurrentProcessIdProvider());
|
||||
|
||||
builder.Configuration.AddJsonFile("appsettings.json", false, true)
|
||||
.AddJsonFile($"appsettings.{enviromentName}.json", false, true);
|
||||
|
||||
builder.Host
|
||||
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
|
||||
.ConfigureContainer<ContainerBuilder>(containerBuilder =>
|
||||
{
|
||||
containerBuilder.RegisterModule<AutofacModuleSetup>();
|
||||
})
|
||||
.UseWindowsService().UseSerilog();
|
||||
#endregion
|
||||
|
||||
|
||||
#region 配置服务
|
||||
var _configuration = builder.Configuration;
|
||||
|
||||
//健康检查
|
||||
builder.Services.AddHealthChecks();
|
||||
//本地化
|
||||
builder.Services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||
builder.Services.AddControllers(options =>
|
||||
{
|
||||
//options.Filters.Add<LogActionFilter>();
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
options.Filters.Add<ProjectExceptionFilter>();
|
||||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
|
||||
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
||||
{
|
||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
}
|
||||
|
||||
})
|
||||
.AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
|
||||
|
||||
builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.GetSection("SystemEmailSendConfig"));
|
||||
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||
|
||||
|
||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||
builder.Services.AddDynamicWebApiSetup();
|
||||
//AutoMapper
|
||||
builder.Services.AddAutoMapperSetup();
|
||||
//EF ORM QueryWithNoLock
|
||||
builder.Services.AddEFSetup(_configuration);
|
||||
//Http 响应压缩
|
||||
builder.Services.AddResponseCompressionSetup();
|
||||
//Swagger Api 文档
|
||||
builder.Services.AddSwaggerSetup();
|
||||
//JWT Token 验证
|
||||
builder.Services.AddJWTAuthSetup(_configuration);
|
||||
|
||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||
// EasyCaching 缓存
|
||||
builder.Services.AddEasyCachingSetup(_configuration);
|
||||
|
||||
// hangfire 定时任务框架 有界面,更友好~
|
||||
builder.Services.AddhangfireSetup(_configuration);
|
||||
|
||||
//
|
||||
builder.Services.AddQuartZSetup(_configuration);
|
||||
|
||||
//Serilog 日志可视化 LogDashboard日志
|
||||
builder.Services.AddLogDashboardSetup();
|
||||
|
||||
|
||||
builder.Services.AddJsonConfigSetup(_configuration);
|
||||
//转发头设置 获取真实IP
|
||||
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
//Dicom影像渲染图片 跨平台
|
||||
builder.Services.AddDicomSetup();
|
||||
|
||||
// 实时应用
|
||||
builder.Services.AddSignalR();
|
||||
|
||||
builder.Services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
||||
|
||||
//builder.Services.AddMemoryCache();
|
||||
|
||||
|
||||
|
||||
#region 历史废弃配置
|
||||
|
||||
////上传限制 配置
|
||||
//builder.Services.Configure<FormOptions>(options =>
|
||||
//{
|
||||
// options.MultipartBodyLengthLimit = int.MaxValue;
|
||||
// options.ValueCountLimit = int.MaxValue;
|
||||
// options.ValueLengthLimit = int.MaxValue;
|
||||
//});
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
var app = builder.Build();
|
||||
var env = app.Environment;
|
||||
|
||||
#region 配置中间件
|
||||
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
||||
//本地化
|
||||
app.UseLocalization();
|
||||
|
||||
app.UseForwardedHeaders();
|
||||
|
||||
//响应压缩
|
||||
app.UseResponseCompression();
|
||||
|
||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||
app.UseStaticFiles();
|
||||
|
||||
//app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/LogDashboard");
|
||||
|
||||
//hangfire
|
||||
app.UseHangfireConfig(env);
|
||||
|
||||
|
||||
////限流 中间件
|
||||
//app.UseIpRateLimiting();
|
||||
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
//app.UseHsts();
|
||||
}
|
||||
|
||||
// 特殊异常处理 比如 404
|
||||
app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||
|
||||
SwaggerSetup.Configure(app, env);
|
||||
|
||||
|
||||
////serilog 记录请求的用户信息
|
||||
app.UseSerilogConfig(env);
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.MapHub<UploadHub>("/UploadHub");
|
||||
app.MapHealthChecks("/health");
|
||||
|
||||
|
||||
// Serilog
|
||||
SerilogExtension.AddSerilogSetup(enviromentName, app.Services);
|
||||
|
||||
|
||||
var hangfireJobService = app.Services.GetRequiredService<IIRaCISHangfireJob>();
|
||||
|
||||
await hangfireJobService.InitHangfireJobTaskAsync();
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
try
|
||||
{
|
||||
#region 运行环境 部署平台
|
||||
|
||||
Log.Logger.Warning($"当前环境:{enviromentName}");
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:windows");
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:linux");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Logger.Warning($"当前部署平台环境:OSX or FreeBSD");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
Log.Logger.Warning($"ContentRootPath:{env.ContentRootPath}");
|
||||
|
||||
|
||||
string parentDirectory = Path.GetFullPath(Path.Combine(env.ContentRootPath, ".."));
|
||||
|
||||
|
||||
Log.Logger.Warning($"ContentRootPath——parentDirectory:{parentDirectory}");
|
||||
|
||||
//Log.Logger.Warning($"ContentRootPath——GetParent:{Directory.GetParent(env.ContentRootPath).Parent.FullName}");
|
||||
//Log.Logger.Warning($"ContentRootPath——xx:{Path.GetDirectoryName(Path.GetDirectoryName(env.ContentRootPath))}");
|
||||
|
||||
app.Run();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Log.Logger.Error(e.InnerException is null ? e.Message + e.StackTrace : e.InnerException?.Message + e.InnerException?.StackTrace);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
using Autofac;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System;
|
||||
using IRaCIS.Core.Application.Filter;
|
||||
using LogDashboard;
|
||||
using MediatR;
|
||||
using IRaCIS.Core.Application.MediatR.Handlers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using AspNetCoreRateLimit;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using IRaCIS.Core.Infra.EFCore;
|
||||
using System.Globalization;
|
||||
using Microsoft.AspNetCore.Localization;
|
||||
using Localization;
|
||||
using Magicodes.ExporterAndImporter.Core.Filters;
|
||||
using IRaCIS.Core.Application.MediatR.CommandAndQueries;
|
||||
using IRaCIS.Core.Infra.EFCore.Common;
|
||||
using Invio.Extensions.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using IRaCIS.Application.Services.BackGroundJob;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Autofac.Core;
|
||||
using DocumentFormat.OpenXml.InkML;
|
||||
using EasyCaching.Core;
|
||||
|
||||
namespace IRaCIS.Core.API
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
public ILogger<Startup> _logger { get; }
|
||||
|
||||
public IConfiguration _configuration { get; }
|
||||
|
||||
//// ConfigureContainer is where you can register things directly
|
||||
//// with Autofac. This runs after ConfigureServices so the things
|
||||
//// here will override registrations made in ConfigureServices.
|
||||
//// Don't build the container; that gets done for you by the factory.
|
||||
// for castle
|
||||
public void ConfigureContainer(ContainerBuilder containerBuilder)
|
||||
{
|
||||
containerBuilder.RegisterModule<AutofacModuleSetup>();
|
||||
|
||||
#region Test
|
||||
//containerBuilder.RegisterType<ClinicalDataService>().PropertiesAutowired().InstancePerLifetimeScope();//注册仓储
|
||||
|
||||
//var container = containerBuilder.Build();
|
||||
|
||||
//// Now you can resolve services using Autofac. For example,
|
||||
//// this line will execute the lambda expression registered
|
||||
//// to the IConfigReader service.
|
||||
//using (var scope = container.BeginLifetimeScope())
|
||||
//{
|
||||
// var reader = scope.Resolve<BaseService>();
|
||||
|
||||
// var test = scope.Resolve<ClinicalDataService>();
|
||||
// var test2 = scope.Resolve<IClinicalDataService>();
|
||||
|
||||
// var test3 = scope.Resolve<IEFUnitOfWork<IRaCISDBContext>>();
|
||||
//}
|
||||
#endregion
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
//健康检查
|
||||
services.AddHealthChecks();
|
||||
//本地化
|
||||
services.AddJsonLocalization(options => options.ResourcesPath = "Resources");
|
||||
|
||||
// 异常、参数统一验证过滤器、Json序列化配置、字符串参数绑型统一Trim()
|
||||
services.AddControllers(options =>
|
||||
{
|
||||
//options.Filters.Add<LogActionFilter>();
|
||||
options.Filters.Add<ModelActionFilter>();
|
||||
options.Filters.Add<ProjectExceptionFilter>();
|
||||
options.Filters.Add<UnitOfWorkFilter>();
|
||||
|
||||
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
|
||||
{
|
||||
options.Filters.Add<LimitUserRequestAuthorization>();
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
.AddNewtonsoftJsonSetup(); // NewtonsoftJson 序列化 处理
|
||||
|
||||
services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.GetSection("SystemEmailSendConfig"));
|
||||
services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
|
||||
services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
|
||||
services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
|
||||
|
||||
|
||||
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码
|
||||
services.AddDynamicWebApiSetup();
|
||||
//AutoMapper
|
||||
services.AddAutoMapperSetup();
|
||||
//EF ORM QueryWithNoLock
|
||||
services.AddEFSetup(_configuration);
|
||||
//Http 响应压缩
|
||||
services.AddResponseCompressionSetup();
|
||||
//Swagger Api 文档
|
||||
services.AddSwaggerSetup();
|
||||
//JWT Token 验证
|
||||
services.AddJWTAuthSetup(_configuration);
|
||||
// MediatR 进程内消息 事件解耦 从程序集中 注册命令和handler对应关系
|
||||
services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<ConsistencyVerificationHandler>());
|
||||
// EasyCaching 缓存
|
||||
services.AddEasyCachingSetup(_configuration);
|
||||
|
||||
//services.AddDistributedMemoryCache();
|
||||
|
||||
// hangfire 定时任务框架 有界面,更友好~
|
||||
services.AddhangfireSetup(_configuration);
|
||||
|
||||
// QuartZ 定时任务框架 使用了hangfire 暂时不用,后续需要可以打开,已经配好
|
||||
services.AddQuartZSetup(_configuration);
|
||||
|
||||
// 保护上传文件
|
||||
//services.AddStaticFileAuthorizationSetup();
|
||||
|
||||
|
||||
////HttpReports 暂时废弃
|
||||
//services.AddHttpReports().AddHttpTransport();
|
||||
//Serilog 日志可视化 LogDashboard日志
|
||||
services.AddLogDashboardSetup();
|
||||
//上传限制 配置
|
||||
services.Configure<FormOptions>(options =>
|
||||
{
|
||||
options.MultipartBodyLengthLimit = int.MaxValue;
|
||||
options.ValueCountLimit = int.MaxValue;
|
||||
options.ValueLengthLimit = int.MaxValue;
|
||||
});
|
||||
//IP 限流 可设置白名单 或者黑名单
|
||||
//services.AddIpPolicyRateLimitSetup(_configuration);
|
||||
// 用户类型 策略授权
|
||||
//services.AddAuthorizationPolicySetup(_configuration);
|
||||
|
||||
services.AddJsonConfigSetup(_configuration);
|
||||
//转发头设置 获取真实IP
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
//Dicom影像渲染图片 跨平台
|
||||
services.AddDicomSetup();
|
||||
|
||||
// 实时应用
|
||||
services.AddSignalR();
|
||||
|
||||
|
||||
services.AddSingleton<IUserIdProvider, IRaCISUserIdProvider>();
|
||||
|
||||
//services.AddSingleton<IImportResultFilter, ImportResultFilteTest>();
|
||||
|
||||
services.AddMemoryCache();
|
||||
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public async void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
{
|
||||
//app.UsePathBase(PathString.FromUriComponent("/api"));
|
||||
|
||||
//本地化
|
||||
app.UseLocalization();
|
||||
|
||||
app.UseForwardedHeaders();
|
||||
|
||||
//响应压缩
|
||||
app.UseResponseCompression();
|
||||
|
||||
//app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//不需要 token 访问的静态文件 wwwroot css, JavaScript, and images don't require authentication.
|
||||
app.UseStaticFiles();
|
||||
|
||||
|
||||
//LogDashboard
|
||||
app.UseLogDashboard("/back/logs");
|
||||
|
||||
//hangfire
|
||||
app.UseHangfireConfig(env);
|
||||
|
||||
////暂时废弃
|
||||
//app.UseHttpReports();
|
||||
|
||||
////限流 中间件
|
||||
//app.UseIpRateLimiting();
|
||||
|
||||
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
//app.UseHsts();
|
||||
}
|
||||
Console.WriteLine("当前环境: " + env.EnvironmentName);
|
||||
|
||||
//app.UseMiddleware<AuthMiddleware>();
|
||||
|
||||
// 特殊异常处理 比如 404
|
||||
app.UseStatusCodePagesWithReExecute("/Error/{0}");
|
||||
|
||||
SwaggerSetup.Configure(app, env);
|
||||
|
||||
|
||||
|
||||
////serilog 记录请求的用户信息
|
||||
app.UseSerilogConfig(env);
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
app.UseCors(t => t.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
|
||||
|
||||
//app.UseIRacisHostStaticFileStore(env);
|
||||
app.UseMiddleware<MultiDiskStaticFilesMiddleware>();
|
||||
|
||||
|
||||
app.UseAuthentication();
|
||||
//app.UseJwtBearerQueryString();
|
||||
app.UseAuthorization();
|
||||
|
||||
////文件伺服 必须带Token 访问
|
||||
////app.UseIRacisHostStaticFileStore(env);
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
|
||||
endpoints.MapHub<UploadHub>("/UploadHub");
|
||||
|
||||
endpoints.MapHealthChecks("/health");
|
||||
});
|
||||
|
||||
|
||||
var hangfireJobService = app.ApplicationServices.GetRequiredService<IIRaCISHangfireJob>();
|
||||
|
||||
await hangfireJobService.InitHangfireJobTaskAsync();
|
||||
//有的时候每调用
|
||||
//HangfireJobHelper.NotImmediatelyOnceOnlyJob<IIRaCISHangfireJob>(t => t.InitHangfireJobTaskAsync(),TimeSpan.FromSeconds(1));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ namespace IRaCIS.Core.API
|
|||
app.UseSerilogRequestLogging(opts
|
||||
=>
|
||||
{
|
||||
opts.MessageTemplate = "{TokenUserRealName} {TokenUserType} {ClientIp} {RequestIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||
opts.MessageTemplate = "{TokenUserRealName} {TokenUserTypeShortName} {ClientIp} {LocalIP} {Host} {Protocol} {RequestMethod} {RequestPath} {RequestBody} responded {StatusCode} in {Elapsed:0.0000} ms";
|
||||
opts.EnrichDiagnosticContext = SerilogHelper.EnrichFromRequest;
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
using IRaCIS.Core.Infrastructure.Extention;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Serilog;
|
||||
using System;
|
||||
|
@ -41,9 +42,9 @@ namespace IRaCIS.Core.API
|
|||
// Set the content-type of the Response at this point
|
||||
diagnosticContext.Set("ContentType", httpContext.Response.ContentType);
|
||||
|
||||
diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst("realName")?.Value);
|
||||
diagnosticContext.Set("TokenUserRealName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.RealName)?.Value);
|
||||
|
||||
diagnosticContext.Set("TokenUserType", httpContext?.User?.FindFirst("userTypeEnumName")?.Value);
|
||||
diagnosticContext.Set("TokenUserTypeShortName", httpContext?.User?.FindFirst(JwtIRaCISClaimType.UserTypeShortName)?.Value);
|
||||
|
||||
// Retrieve the IEndpointFeature selected for the request
|
||||
var endpoint = httpContext.GetEndpoint();
|
||||
|
|
|
@ -26,24 +26,26 @@ namespace IRaCIS.Core.API
|
|||
|
||||
//控制台 方便调试 问题 我们显示记录日志 时 获取上下文的ip 和用户名 用户类型
|
||||
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Warning,
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3} ] {LocalIP} {ClientIp} {TokenUserRealName} {TokenUserType} {Message:lj} {Properties:j}{NewLine} {Exception}")
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}")
|
||||
|
||||
.WriteTo.File($"{AppContext.BaseDirectory}Serilogs/.log", rollingInterval: RollingInterval.Day,
|
||||
outputTemplate: "{Timestamp:HH:mm:ss} || {Level} || {SourceContext:l} || {Message} ||{Exception} ||end {NewLine}");
|
||||
outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine}");
|
||||
|
||||
//.WriteTo.MSSqlServer("Data Source=DESKTOP-4TU9A6M;Initial Catalog=CoreFrame;User ID=sa;Password=123456", "logs", autoCreateSqlTable: true, restrictedToMinimumLevel: LogEventLevel.Information)//从左至右四个参数分别是数据库连接字符串、表名、如果表不存在是否创建、最低等级。Serilog会默认创建一些列。
|
||||
|
||||
if (environment == "Production")
|
||||
{
|
||||
config.WriteTo.Email(new EmailConnectionInfo()
|
||||
{
|
||||
EmailSubject = "系统警告,请速速查看!",//邮件标题
|
||||
FromEmail = "test@extimaging.com",//发件人邮箱
|
||||
MailServer = "smtp.qiye.aliyun.com",//smtp服务器地址
|
||||
NetworkCredentials = new NetworkCredential("test@extimaging.com", "SHzyyl2021"),//两个参数分别是发件人邮箱与客户端授权码
|
||||
Port = 465,//端口号
|
||||
ToEmail = "872297557@qq.com"//收件人
|
||||
}, restrictedToMinimumLevel: LogEventLevel.Error,
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [ {Level} {ClientIp} {ClientAgent} {TokenUserRealName} {TokenUserType} ] || [path: {RequestPath} arguments: {RequestBody}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine})");
|
||||
}
|
||||
//if (environment == "Production")
|
||||
//{
|
||||
// config.WriteTo.Email(new EmailConnectionInfo()
|
||||
// {
|
||||
// EmailSubject = "系统警告,请速速查看!",//邮件标题
|
||||
// FromEmail = "test@extimaging.com",//发件人邮箱
|
||||
// MailServer = "smtp.qiye.aliyun.com",//smtp服务器地址
|
||||
// NetworkCredentials = new NetworkCredential("test@extimaging.com", "SHzyyl2021"),//两个参数分别是发件人邮箱与客户端授权码
|
||||
// Port = 465,//端口号
|
||||
// ToEmail = "872297557@qq.com"//收件人
|
||||
// }, restrictedToMinimumLevel: LogEventLevel.Error,
|
||||
// outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [ {Level} {ClientIp} {ClientAgent} {TokenUserRealName} {TokenUserType} ] || [path: {RequestPath} arguments: {RequestBody}] {SourceContext:l} || {Message} || {Exception} ||end {NewLine})");
|
||||
//}
|
||||
|
||||
//扩展方法 获取上下文的ip 用户名 用户类型
|
||||
Log.Logger = config.Enrich.WithHttpContextInfo(serviceProvider).CreateLogger();
|
||||
|
|
|
@ -163,7 +163,8 @@ namespace IRaCIS.Core.Application.Helper
|
|||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithStreamData(memoryStream);
|
||||
.WithStreamData(memoryStream)
|
||||
.WithObjectSize(memoryStream.Length);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
}
|
||||
|
@ -179,7 +180,8 @@ namespace IRaCIS.Core.Application.Helper
|
|||
var putObjectArgs = new PutObjectArgs()
|
||||
.WithBucket(minIOConfig.bucketName)
|
||||
.WithObject(ossRelativePath)
|
||||
.WithStreamData(memoryStream);
|
||||
.WithStreamData(memoryStream)
|
||||
.WithObjectSize(memoryStream.Length);
|
||||
|
||||
await minioClient.PutObjectAsync(putObjectArgs);
|
||||
}
|
||||
|
|
|
@ -547,6 +547,32 @@
|
|||
InternationalizationService
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.InternationalizationService.GetFrontInternationalizationList">
|
||||
<summary>
|
||||
前端国际化内容接口
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.InternationalizationService.BatchAddOrUpdateFrontInternationalization(System.Collections.Generic.List{IRaCIS.Core.Application.ViewModel.BatchInternationalizationDto})">
|
||||
<summary>
|
||||
前端批量提交,后端判断不存在就添加,存在就更新
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.InternationalizationService.BatchAddInternationalization(IRaCIS.Core.Application.ViewModel.BatchAddInternationalization)">
|
||||
<summary>
|
||||
后端之前批量添加接口
|
||||
</summary>
|
||||
<param name="batchAdd"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Core.Application.Service.InternationalizationService.AddOrUpdateInternationalization(IRaCIS.Core.Application.ViewModel.InternationalizationAddOrEdit)">
|
||||
<summary>
|
||||
前后端添加的时候,区分了,前端判断重复多了多了一个路由 路由+标识唯一
|
||||
</summary>
|
||||
<param name="addOrEditInternationalization"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Core.Application.Service.PublishLogService">
|
||||
<summary>
|
||||
PublishLogService
|
||||
|
@ -12413,6 +12439,12 @@
|
|||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:IRaCIS.Application.Services.TestService.OldLocalImageResizeJpg(IRaCIS.Core.Application.Helper.IOSSService,IRaCIS.Core.Infra.EFCore.IRepository,Microsoft.AspNetCore.Hosting.IWebHostEnvironment)">
|
||||
<summary>
|
||||
维护OSS 影像数据
|
||||
</summary>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:IRaCIS.Application.Contracts.DoctorSearchDTO">
|
||||
<summary>
|
||||
Reviewer 列表查询参数
|
||||
|
|
|
@ -356,7 +356,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
.Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync();
|
||||
|
||||
|
||||
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false)
|
||||
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable==false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
.Include(t => t.TrialEmailNoticeUserList).Include(t => t.TrialEmailBlackUserList).FirstOrDefaultAsync();
|
||||
|
||||
|
||||
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false)
|
||||
if (trialEmailConfig == null || trialEmailConfig.IsAutoSend == false || trialEmailConfig.IsEnable==false)
|
||||
{
|
||||
return (null, null);
|
||||
}
|
||||
|
|
|
@ -173,7 +173,16 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public string[]? VisitPlanArray { get; set; }
|
||||
|
||||
}
|
||||
public Guid? VisitTaskId { get; set; }
|
||||
|
||||
public bool? IsDicom { get; set; }
|
||||
|
||||
public string? Uploader { get; set; }
|
||||
|
||||
public bool? IsSuccess { get; set; }
|
||||
|
||||
public string? StudyCode { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class PreArchiveDicomStudyCommand
|
||||
|
@ -215,6 +224,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
|
||||
public int FailedFileCount { get; set; }
|
||||
|
||||
public string RecordPath { get; set; }
|
||||
|
||||
public AddOrUpdateStudyDto Study { get; set; }
|
||||
|
||||
|
||||
|
|
|
@ -151,7 +151,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
studyMonitor.UploadFinishedTime = DateTime.Now;
|
||||
studyMonitor.ArchiveFinishedTime = DateTime.Now;
|
||||
studyMonitor.FailedFileCount = incommand.FailedFileCount;
|
||||
studyMonitor.IsSuccess = true;
|
||||
studyMonitor.IsSuccess = incommand.FailedFileCount==0;
|
||||
studyMonitor.RecordPath=incommand.RecordPath;
|
||||
|
||||
//上传
|
||||
if (studyMonitor.IsDicomReUpload == false)
|
||||
|
@ -209,6 +210,9 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
series.SubjectId = incommand.SubjectId;
|
||||
series.SubjectVisitId = incommand.SubjectVisitId;
|
||||
|
||||
//前端传递的数量不准,上传的时候,把失败的也加进来了,以实际数组的数字为准
|
||||
series.InstanceCount = seriesItem.InstanceList.Count;
|
||||
|
||||
await _dicomSeriesRepository.AddAsync(series);
|
||||
|
||||
foreach (var instanceItem in seriesItem.InstanceList)
|
||||
|
@ -241,6 +245,8 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
|
||||
var study = await _dicomstudyRepository.FirstOrDefaultAsync(t => t.Id == studyId);
|
||||
|
||||
//重传的时候也要赋值检查Id
|
||||
studyMonitor.StudyId = study.Id;
|
||||
|
||||
//特殊处理逻辑
|
||||
study.Modalities = string.Join("、", incommand.Study.SeriesList.Select(t => t.Modality).Union(study.Modalities.Split("、", StringSplitOptions.RemoveEmptyEntries)).Distinct());
|
||||
|
@ -457,6 +463,10 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
|
|||
.WhereIf(studyQuery.SubjectId != null, t => t.SubjectId == studyQuery.SubjectId)
|
||||
.WhereIf(studyQuery.SubjectVisitId != null, t => t.SubjectId == studyQuery.SubjectVisitId)
|
||||
.WhereIf(studyQuery.SiteId != null, t => t.SiteId == studyQuery.SiteId)
|
||||
.WhereIf(studyQuery.IsDicom != null, t => t.IsDicom == studyQuery.IsDicom )
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.Uploader), t => t.Uploader.UserName.Contains(studyQuery.Uploader))
|
||||
.WhereIf(studyQuery.IsSuccess != null, t => t.IsSuccess == studyQuery.IsSuccess)
|
||||
.WhereIf(!string.IsNullOrWhiteSpace(studyQuery.StudyCode), t => t.StudyCode.Contains(studyQuery.StudyCode))
|
||||
.Select(t => new UnionStudyMonitorModel()
|
||||
{
|
||||
TrialId = t.TrialId,
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace IRaCIS.Core.Application.Service
|
|||
.ForMember(o => o.UploadedTime, t => t.MapFrom(u => u.CreateTime))
|
||||
.ForMember(o => o.Uploader, t => t.MapFrom(u => u.Uploader.LastName + " / " + u.Uploader.FirstName))
|
||||
.ForMember(o => o.StudyId, t => t.MapFrom(u => u.Id))
|
||||
.ForMember(o => o.IsHaveUploadFailed, t => t.MapFrom(u => u.DicomStudyMonitorList.Any(t=>t.FailedFileCount>0)))
|
||||
.ForMember(o => o.Modalities, t => t.MapFrom(u => string.Join('、', u.SeriesList.Select(t => t.Modality).Distinct()) ));
|
||||
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
siteCommand.Code = await _siteRepository.Select(t => t.Code).DefaultIfEmpty().MaxAsync() + 1;
|
||||
|
||||
siteCommand.SiteCode = AppSettings.GetCodeStr(siteCommand.Code, nameof(User));
|
||||
siteCommand.SiteCode = AppSettings.GetCodeStr(siteCommand.Code, nameof(Site));
|
||||
}
|
||||
|
||||
var site = await _siteRepository.InsertOrUpdateAsync(siteCommand, true, exp);
|
||||
|
|
|
@ -12,6 +12,7 @@ using Microsoft.Identity.Client;
|
|||
using static IRaCIS.Core.Domain.Share.StaticData;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using Medallion.Threading;
|
||||
using EasyCaching.Core;
|
||||
|
||||
namespace IRaCIS.Application.Services
|
||||
{
|
||||
|
@ -25,7 +26,7 @@ namespace IRaCIS.Application.Services
|
|||
private readonly IRepository<UserLog> _userLogRepository;
|
||||
|
||||
private readonly IDistributedLockProvider _distributedLockProvider;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IEasyCachingProvider _cache;
|
||||
|
||||
private readonly IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig;
|
||||
|
||||
|
@ -34,7 +35,7 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
IMailVerificationService mailVerificationService,
|
||||
IRepository<VerificationCode> verificationCodeRepository,
|
||||
IMemoryCache cache,
|
||||
IEasyCachingProvider cache,
|
||||
IRepository<TrialUser> userTrialRepository,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> verifyConfig,
|
||||
IRepository<UserLog> userLogRepository
|
||||
|
@ -629,7 +630,7 @@ namespace IRaCIS.Application.Services
|
|||
string cacheKey = $"{cachePrefix}{userName}";
|
||||
|
||||
// 从缓存中获取登录失败次数
|
||||
int? failCount = _cache.Get<int?>(cacheKey);
|
||||
int? failCount = _cache.Get<int?>(cacheKey).Value;
|
||||
|
||||
if (failCount == null)
|
||||
{
|
||||
|
|
|
@ -386,7 +386,7 @@ namespace IRaCIS.Core.Application.Contracts.DTO
|
|||
|
||||
public string ModalityForEdit { get; set; } = string.Empty;
|
||||
|
||||
|
||||
public bool IsHaveUploadFailed { get; set; }
|
||||
}
|
||||
|
||||
public class QASeriesInfoDto
|
||||
|
|
|
@ -1099,6 +1099,8 @@ namespace IRaCIS.Core.Application.Contracts
|
|||
public int? Age { get; set; }
|
||||
public string Sex { get; set; } = string.Empty;
|
||||
|
||||
public bool IsHaveUploadFailed { get; set; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -395,6 +395,8 @@ namespace IRaCIS.Core.Application.Service
|
|||
|| t.ReadingClinicalDataList.Any(x => x.ClinicalDataTrialSet.UploadRole == Domain.Share.UploadRole.CRC && x.ReadingClinicalDataPDFList.Count() > 0)
|
||||
|| t.PreviousSurgeryList.Any()))
|
||||
|
||||
.ForMember(d => d.IsHaveUploadFailed, u => u.MapFrom(t => t.StudyList.SelectMany(c=>c.DicomStudyMonitorList).Any(h => h.FailedFileCount>0) ))
|
||||
|
||||
//.ForMember(d => d.VisitName, u => u.MapFrom(t =>t.InPlan? t.VisitStage.VisitName : t.VisitName))
|
||||
//.ForMember(d => d.VisitNum, u => u.MapFrom(t => t.InPlan ? t.VisitStage.VisitNum : t.VisitNum))
|
||||
//.ForMember(d => d.VisitDay, u => u.MapFrom(t => t.InPlan ? t.VisitStage.VisitDay : t.VisitDay))
|
||||
|
|
|
@ -89,7 +89,6 @@ namespace IRaCIS.Application.Services
|
|||
IRepository<User> userRepository,
|
||||
IEasyCachingProvider provider,
|
||||
IRepository<ReadingCustomTag> readingCustomTagRepository,
|
||||
IMemoryCache cache,
|
||||
IRepository<ReadingSystemCriterionDictionary> readingCriterionDictionaryRepository,
|
||||
IRepository<ReadingTrialCriterionDictionary> readingTrialCriterionDictionaryRepository,
|
||||
IRepository<TumorAssessment_RECIST1Point1> tumorAssessmentRepository,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using DocumentFormat.OpenXml.Office2010.Excel;
|
||||
using Aliyun.OSS;
|
||||
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
|
||||
using IRaCIS.Core.Application.Helper;
|
||||
using IRaCIS.Core.Application.Service;
|
||||
using IRaCIS.Core.Application.ViewModel;
|
||||
using IRaCIS.Core.Domain.Share;
|
||||
|
@ -12,8 +14,15 @@ using Microsoft.Extensions.Caching.Distributed;
|
|||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MiniExcelLibs;
|
||||
using Minio;
|
||||
using Minio.DataModel.Args;
|
||||
using NPOI.HPSF;
|
||||
using NPOI.POIFS.Crypt;
|
||||
using SharpCompress.Common;
|
||||
using Spire.Doc;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -25,7 +34,7 @@ namespace IRaCIS.Application.Services
|
|||
public class TestService : BaseService
|
||||
{
|
||||
|
||||
public static int IntValue = 100;
|
||||
public static int IntValue = 100;
|
||||
private readonly IRepository<Dictionary> _dicRepository;
|
||||
private readonly IRepository<Trial> _trialRepository;
|
||||
|
||||
|
@ -40,7 +49,7 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
private readonly ILogger<TestService> _logger;
|
||||
|
||||
public TestService(IRepository<Dictionary> dicRepository, IRepository<Trial> trialRepository,ILogger<TestService> logger
|
||||
public TestService(IRepository<Dictionary> dicRepository, IRepository<Trial> trialRepository, ILogger<TestService> logger
|
||||
|
||||
, IOptionsMonitor<SystemEmailSendConfig> systemEmailConfig, IOptionsMonitor<ServiceVerifyConfigOption> basicConfig, IRepository<VisitTask> visitTaskRepository, IDistributedLockProvider distributedLockProvider)
|
||||
{
|
||||
|
@ -52,31 +61,56 @@ namespace IRaCIS.Application.Services
|
|||
_dicRepository = dicRepository;
|
||||
_trialRepository = trialRepository;
|
||||
|
||||
_distributedLockProvider= distributedLockProvider;
|
||||
_distributedLockProvider = distributedLockProvider;
|
||||
|
||||
_logger= logger;
|
||||
_logger = logger;
|
||||
//_cache = cache;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput> TestDistributedLock( )
|
||||
public async Task<IResponseOutput> TestEFcore8()
|
||||
{
|
||||
|
||||
await _repository.Where<User>().Select(t => t.FullName).FirstNotNullAsync();
|
||||
|
||||
//var aa= _dicRepository._dbContext.Subject.Where(t => t.Id == Guid.Empty).ExecuteUpdate("FirstName","ddd");
|
||||
|
||||
await _repository.BatchUpdateAsync<Subject>(t => t.Id == Guid.Empty, u => new Subject() { FirstName = "fddd", LastName = "sss", UpdateTime = DateTime.Now });
|
||||
|
||||
await _repository.Where<Subject>().ExecuteUpdateAsync(t => t.SetProperty(t => t.UpdateTime, u => DateTime.Now));
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
// 设置 Ne
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput> TestMinIO([FromServices] IOSSService oSSService)
|
||||
{
|
||||
|
||||
await oSSService.UploadToOSSAsync("C:\\Users\\Administrator\\Desktop\\TrialSiteUserImportTemplate.xlsx", "myfolder");
|
||||
|
||||
await oSSService.DownLoadFromOSSAsync("/myfolder/TrialSiteUserImportTemplate.xlsx", "C:\\Users\\Administrator\\Desktop\\aws.xlsx");
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput> TestDistributedLock()
|
||||
{
|
||||
|
||||
await _repository.Where<User>().Select(t => t.FullName).FirstNotNullAsync();
|
||||
|
||||
Console.WriteLine($"我进来了当前值是:" + IntValue);
|
||||
_logger.LogWarning($"我进来了当前值是:" + IntValue);
|
||||
|
||||
var @lock = _distributedLockProvider.CreateLock($"UserAccount");
|
||||
|
||||
using (await @lock.AcquireAsync())
|
||||
using (await @lock.AcquireAsync())
|
||||
{
|
||||
await Task.Delay(4);
|
||||
IntValue--;
|
||||
|
||||
_logger.LogWarning( IntValue.ToString());
|
||||
_logger.LogWarning(IntValue.ToString());
|
||||
Console.WriteLine(IntValue);
|
||||
}
|
||||
|
||||
|
@ -85,86 +119,126 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput> GetMemoryStoreData()
|
||||
public async Task<IResponseOutput> InternationazitionInit()
|
||||
{
|
||||
|
||||
|
||||
|
||||
var rows = await MiniExcel.QueryAsync<InternationalizationAddOrEdit>(@"C:\Users\Administrator\Desktop\i18n-new2.xlsx");
|
||||
|
||||
return ResponseOutput.Ok(new { StaticData.En_US_Dic , StaticData.Zh_CN_Dic });
|
||||
rows = rows.Where(t => !string.IsNullOrEmpty(t.Code)).ToList();
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
await _repository.InsertOrUpdateAsync<Internationalization, InternationalizationAddOrEdit>(row);
|
||||
|
||||
}
|
||||
|
||||
await _repository.SaveChangesAsync();
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
|
||||
//[AllowAnonymous]
|
||||
//public async Task<IResponseOutput> InternationazitionInit()
|
||||
//{
|
||||
|
||||
|
||||
// var rows = await MiniExcel.QueryAsync<InternationalizationAddOrEdit>(@"C:\Users\Administrator\Desktop\Export\vue.xlsx");
|
||||
|
||||
// foreach (var row in rows)
|
||||
// {
|
||||
// await _repository.InsertOrUpdateAsync<Internationalization, InternationalizationAddOrEdit>(row);
|
||||
|
||||
// }
|
||||
|
||||
// await _repository.SaveChangesAsync();
|
||||
|
||||
// return ResponseOutput.Ok();
|
||||
//}
|
||||
[AllowAnonymous]
|
||||
[UnitOfWork]
|
||||
public async Task<string> Get()
|
||||
{
|
||||
|
||||
return "修改服务器时间自动发布测试--我又修改了";
|
||||
|
||||
//Expression<Func<VisitTask, bool>> visitTaskLambda = x => x.TrialId == Guid.Empty && x.SubjectId == Guid.Empty && x.TrialReadingCriterionId == Guid.Empty;
|
||||
|
||||
//var visitTaskIdQueryable = _visitTaskRepositoryy.Where(visitTaskLambda).Where(t => t.Subject.SubjectVisitTaskList.AsQueryable().Where(visitTaskLambda).Any(c => c.IsNeedClinicalDataSign == true && c.IsClinicalDataSign == false && c.VisitTaskNum < t.VisitTaskNum)).Select(t => t.Id);
|
||||
|
||||
//await _visitTaskRepositoryy.BatchUpdateNoTrackingAsync(t => visitTaskIdQueryable.Contains(t.Id), u => new VisitTask()
|
||||
//{
|
||||
// IsFrontTaskNeedSignButNotSign = true
|
||||
//});
|
||||
|
||||
|
||||
//var a = ((Decimal)1.00).ToString().TrimEnd(new char[] { '.', '0' });
|
||||
//var b = ((Decimal)1.01).ToString().TrimEnd(new char[] { '.', '0' });
|
||||
//var c = ((Decimal)100).ToString().TrimEnd(new char[] { '.', '0' });
|
||||
//var subject1 = Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391693");
|
||||
//var subject2 = Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391694");
|
||||
|
||||
// var subjectList = new List<Guid>() { Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391693") ,
|
||||
// Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391694") ,
|
||||
// Guid.Parse("431D0C58-ABC5-4166-B9BC-08DA0E391695")
|
||||
// };
|
||||
|
||||
//string[] citys = new string[] { "广州", "深圳", "上海", "北京" };
|
||||
//foreach (var item in subjectList)
|
||||
//{
|
||||
// Console.WriteLine(await BNRFactory.Default.Create($"[CN:{item}][N:[CN:{item}]/0000000]"));
|
||||
//}
|
||||
//foreach (var item in subjectList)
|
||||
//{
|
||||
// Console.WriteLine(await BNRFactory.Default.Create($"[N:[CN:{item}]/0000000]"));
|
||||
//}
|
||||
|
||||
//foreach (var item in subjectList)
|
||||
//{
|
||||
// Console.WriteLine(await BNRFactory.Default.Create($"[CN:{item}][redis:city/0000000]"));
|
||||
//}
|
||||
|
||||
//var needAddVisitList = await _repository.Where<VisitTask>(t => t.TrialId == Guid.Empty).DistinctBy(t => t.VisitTaskNum).ToListAsync();
|
||||
|
||||
|
||||
//await _repository.BatchUpdateAsync<VisitTask>(t => t.Id == Guid.Empty, u => new VisitTask()
|
||||
//{
|
||||
// SuggesteFinishedTime = u.IsUrgent ? DateTime.Now.AddDays(2) : DateTime.Now.AddDays(7),
|
||||
|
||||
// Code = u.Code + 1
|
||||
//});
|
||||
|
||||
//var query = from item1 in _repository.Where<ReadingQuestionTrial>()
|
||||
// join item2 in _repository.Where<ReadingQuestionTrial>() on item1.ValueType equals item2.ValueType
|
||||
// select new
|
||||
// {
|
||||
// item1.ValueType,
|
||||
// dd = item2.ValueType
|
||||
// };
|
||||
|
||||
//var list2 = query.ToList();
|
||||
|
||||
//await Task.CompletedTask;
|
||||
|
||||
//var list = await _repository.Where<ClinicalDataTrialSet>(t => t.TrialId == Guid.Parse("40400000-3e2c-0016-239b-08da581f0e74")).ToListAsync();
|
||||
|
||||
////await _repository.BatchDeleteAsync<ClinicalDataTrialSet>(t => t.TrialId == Guid.Parse("40400000-3e2c-0016-239b-08da581f0e74"));
|
||||
|
||||
//await _repository.AddRangeAsync(list, true);
|
||||
|
||||
//await _repository.SaveChangesAsync();
|
||||
|
||||
//await _repository.BatchUpdateAsync<DataInspection>(t => t.TrialId == Guid.Parse("40400000-3e2c-0016-239b-08da581f0e74") && t.EntityName== "ClinicalDataTrialSet", t => new DataInspection() { CreateTime= DateTime.Now.AddMonths(-2) } );
|
||||
|
||||
//await _visitTaskRepositoryy.UpdatePartialFromQueryAsync( Guid.Parse("78360000-3E2C-0016-9B53-08DA6A002040"), c => new VisitTask() { UpdateTime = DateTime.Now });
|
||||
|
||||
//await _visitTaskRepositoryy.UpdatePartialFromQueryAsync( Guid.Parse("78360000-3E2C-0016-9B53-08DA6A002040"), c => new VisitTask() { UpdateTime = DateTime.Now.AddMinutes(1) });
|
||||
|
||||
//var a = _userInfo.IsTestUser;
|
||||
|
||||
//var list1 = await _repository.Where<Dictionary>().Select(t => t.TranslateValue(t.Value, t.ValueCN, true)).ToListAsync();
|
||||
//var list2 = await _repository.Where<Dictionary>().Select(t => t.TranslateValue(t.Value, t.ValueCN, false)).ToListAsync();
|
||||
|
||||
return "测试自动发布--再次提交";
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static Dictionary<string, string> _replacePatterns = new Dictionary<string, string>()
|
||||
{
|
||||
{ "test", "Atlanta Knight" },
|
||||
{ "GAME_TIME", "7:30pm" },
|
||||
{ "GAME_NUMBER", "161" },
|
||||
{ "DATE", "October 18 2018" },
|
||||
};
|
||||
|
||||
private static string ReplaceFunc(string findStr)
|
||||
{
|
||||
if (_replacePatterns.ContainsKey(findStr))
|
||||
{
|
||||
return _replacePatterns[findStr];
|
||||
}
|
||||
return findStr;
|
||||
}
|
||||
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<List<Guid>> testwwwww([FromServices] IWebHostEnvironment env)
|
||||
public async Task testwwwww([FromServices] IWebHostEnvironment env)
|
||||
{
|
||||
int count = 200;
|
||||
|
||||
var list=new List<Guid>();
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Guid guid = NewId.NextGuid();
|
||||
list.Add(guid);
|
||||
}
|
||||
|
||||
return list;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
[AllowAnonymous]
|
||||
public async Task<object> GetEnvironmentName([FromServices] IWebHostEnvironment env)
|
||||
{
|
||||
var a = IdentifierHelper.CreateGuid("1.2.840.113619.2.416.3358551739363725609857319676326094825431.2.840.113619.2.80.2338912612.50499.1563432834.1.4.11.2.840.113619.2.80.2338912612.50499.1563432835.4b8340000-3e2c-0016-fbdd-08db883b137f");
|
||||
var a = IdentifierHelper.CreateGuid("123456");
|
||||
|
||||
var k = MD5.Create().ComputeHash(Encoding.UTF8.GetBytes("123456"));
|
||||
|
||||
var c = MD5Helper.Md5("1.2.840.113619.2.416.3358551739363725609857319676326094825431.2.840.113619.2.80.2338912612.50499.1563432834.1.4.11.2.840.113619.2.80.2338912612.50499.1563432835.4b8340000-3e2c-0016-fbdd-08db883b137f");
|
||||
|
||||
var c = MD5Helper.Md5("123456");
|
||||
|
||||
//update DicomInstance set Path = '/IRaCISData/TrialData/' + cast(DicomInstance.TrialId as varchar) + '/' + DicomInstance.SiteId + '/' + DicomInstance.SubjectId + '/' + DicomInstance.SubjectVisitId + '/Dicom/' + DicomInstance.StudyId + '/' + DicomInstance.Id + '.dcm'
|
||||
|
||||
|
@ -255,11 +329,7 @@ namespace IRaCIS.Application.Services
|
|||
|
||||
|
||||
|
||||
public string PostData(TestModel testModelList)
|
||||
{
|
||||
return String.Empty;
|
||||
}
|
||||
|
||||
#region 历史维护
|
||||
/// <summary>
|
||||
/// 维护临床数据 --一定要在同步表前同步数据才行
|
||||
/// </summary>
|
||||
|
@ -299,6 +369,89 @@ namespace IRaCIS.Application.Services
|
|||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 维护OSS 影像数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[AllowAnonymous]
|
||||
[UnitOfWork]
|
||||
public async Task<IResponseOutput> OldLocalImageResizeJpg([FromServices] IOSSService oSSService, [FromServices] IRepository _repository, [FromServices] IWebHostEnvironment _hostEnvironment)
|
||||
{
|
||||
|
||||
var aliConfig = oSSService.ObjectStoreServiceOptions.AliyunOSS;
|
||||
var _ossClient = new OssClient(aliConfig.endPoint, aliConfig.accessKeyId, aliConfig.accessKeySecret);
|
||||
|
||||
var rootPath = FileStoreHelper.GetIRaCISRootDataFolder(_hostEnvironment);
|
||||
|
||||
var studyList = _repository.Where<DicomStudy>(t => t.SeriesList.Any(t => t.ImageResizePath.Length < 10)).Select(t => new { t.TrialId, t.SiteId, t.SubjectId, t.SubjectVisitId, t.Id }).ToList();
|
||||
|
||||
foreach (var studyitem in studyList)
|
||||
{
|
||||
|
||||
var relativePath = $"{studyitem.TrialId}/{studyitem.SiteId}/{studyitem.SubjectId}/{studyitem.SubjectVisitId}/{StaticData.Folder.DicomFolder}/{studyitem.Id}/";
|
||||
|
||||
try
|
||||
{
|
||||
string nextMarker = null;
|
||||
do
|
||||
{
|
||||
// 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
|
||||
var objectListing = _ossClient.ListObjects(new ListObjectsRequest(aliConfig.bucketName)
|
||||
{
|
||||
Prefix = relativePath,
|
||||
MaxKeys = 1000,
|
||||
Marker = nextMarker
|
||||
});
|
||||
|
||||
var jpgInfoList = objectListing.ObjectSummaries
|
||||
.Where(summary => summary.Key.EndsWith(".jpg"))
|
||||
.Select(summary =>
|
||||
{
|
||||
string fileName = summary.Key.Split('/').Last(); // 提取文件夹名
|
||||
return new
|
||||
{
|
||||
|
||||
Key = summary.Key,
|
||||
InstanceId = Guid.TryParse(
|
||||
fileName.Split('.')[0],
|
||||
out Guid instanceId)
|
||||
? instanceId
|
||||
: Guid.Empty
|
||||
};
|
||||
})
|
||||
.Where(info => info.InstanceId != Guid.Empty)
|
||||
.ToList();
|
||||
|
||||
foreach (var jpg in jpgInfoList)
|
||||
{
|
||||
var seriesId = _repository.Where<DicomInstance>(t => t.Id == jpg.InstanceId).Select(t => t.SeriesId).FirstOrDefault();
|
||||
|
||||
await _repository.BatchUpdateAsync<DicomSeries>(t => t.Id == seriesId, t => new DicomSeries() { ImageResizePath = "/" + jpg.Key });
|
||||
}
|
||||
|
||||
// 设置 NextMarker 以获取下一页的数据
|
||||
nextMarker = objectListing.NextMarker;
|
||||
|
||||
} while (!string.IsNullOrEmpty(nextMarker));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Error: {ex.Message}");
|
||||
}
|
||||
|
||||
await _repository.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return ResponseOutput.Ok();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class TestModel
|
||||
|
|
|
@ -85,7 +85,9 @@ namespace IRaCIS.Core.Domain.Models
|
|||
|
||||
public bool IsSuccess { get; set; }
|
||||
|
||||
public string Note = string.Empty;
|
||||
public string Note { get; set; } = string.Empty;
|
||||
|
||||
public string RecordPath { get; set; }=string.Empty;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Query;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace IRaCIS.Core.Infra.EFCore
|
||||
{
|
||||
|
||||
public static class DynamicRelationalExtensions
|
||||
{
|
||||
static MethodInfo UpdateMethodInfo =
|
||||
typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.ExecuteUpdate));
|
||||
|
||||
static MethodInfo UpdateAsyncMethodInfo =
|
||||
typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.ExecuteUpdateAsync));
|
||||
|
||||
#region 避免使用
|
||||
|
||||
public static int ExecuteUpdate(this IQueryable query, string fieldName, object? fieldValue)
|
||||
{
|
||||
var updateBody = BuildUpdateBody(query.ElementType,
|
||||
new Dictionary<string, object?> { { fieldName, fieldValue } });
|
||||
|
||||
return (int)UpdateMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody });
|
||||
}
|
||||
|
||||
public static int ExecuteUpdate(this IQueryable query, IReadOnlyDictionary<string, object?> fieldValues)
|
||||
{
|
||||
var updateBody = BuildUpdateBody(query.ElementType, fieldValues);
|
||||
|
||||
return (int)UpdateMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody });
|
||||
}
|
||||
public static Task<int> ExecuteUpdateAsync(this IQueryable query, string fieldName, object? fieldValue, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var updateBody = BuildUpdateBody(query.ElementType,
|
||||
new Dictionary<string, object?> { { fieldName, fieldValue } });
|
||||
|
||||
return (Task<int>)UpdateAsyncMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody, cancellationToken })!;
|
||||
}
|
||||
#endregion
|
||||
|
||||
public static Dictionary<string, object?> ExtractFieldValues<TSource>(this Expression<Func<TSource, TSource>> updateFactory)
|
||||
{
|
||||
var dic = new Dictionary<string, object?>();
|
||||
var obj = (TSource)Activator.CreateInstance(typeof(TSource));
|
||||
|
||||
Func<TSource, TSource> func = updateFactory.Compile();
|
||||
|
||||
TSource applyObj = func(obj);
|
||||
|
||||
var propList = ((MemberInitExpression)updateFactory.Body).Bindings.Select(mb => mb.Member.Name)
|
||||
.Select(propName => typeof(TSource).GetProperty(propName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)).ToList();
|
||||
|
||||
|
||||
foreach (PropertyInfo prop in propList)
|
||||
{
|
||||
object value = prop.GetValue(applyObj);
|
||||
dic.Add(prop.Name, value);
|
||||
}
|
||||
|
||||
return dic;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Task<int> ExecuteUpdateAsync(this IQueryable query, IReadOnlyDictionary<string, object?> fieldValues, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var updateBody = BuildUpdateBody(query.ElementType, fieldValues);
|
||||
|
||||
return (Task<int>)UpdateAsyncMethodInfo.MakeGenericMethod(query.ElementType).Invoke(null, new object?[] { query, updateBody, cancellationToken })!;
|
||||
}
|
||||
|
||||
|
||||
static LambdaExpression BuildUpdateBody(Type entityType, IReadOnlyDictionary<string, object?> fieldValues)
|
||||
{
|
||||
var setParam = Expression.Parameter(typeof(SetPropertyCalls<>).MakeGenericType(entityType), "s");
|
||||
var objParam = Expression.Parameter(entityType, "e");
|
||||
|
||||
Expression setBody = setParam;
|
||||
|
||||
foreach (var pair in fieldValues)
|
||||
{
|
||||
var propExpression = Expression.PropertyOrField(objParam, pair.Key);
|
||||
var valueExpression = ValueForType(propExpression.Type, pair.Value);
|
||||
|
||||
// s.SetProperty(e => e.SomeField, value)
|
||||
setBody = Expression.Call(setBody, nameof(SetPropertyCalls<object>.SetProperty),
|
||||
new[] { propExpression.Type }, Expression.Lambda(propExpression, objParam), valueExpression);
|
||||
|
||||
}
|
||||
|
||||
// s => s.SetProperty(e => e.SomeField, value)
|
||||
var updateBody = Expression.Lambda(setBody, setParam);
|
||||
|
||||
return updateBody;
|
||||
}
|
||||
|
||||
static Expression ValueForType(Type desiredType, object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return Expression.Default(desiredType);
|
||||
}
|
||||
|
||||
if (value.GetType() != desiredType)
|
||||
{
|
||||
return Expression.Convert(Expression.Constant(value), desiredType);
|
||||
}
|
||||
|
||||
return Expression.Constant(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -157,7 +157,7 @@ namespace IRaCIS.Core.Infra.EFCore
|
|||
{
|
||||
if (deleteFilter == null) throw new ArgumentNullException(nameof(deleteFilter));
|
||||
|
||||
return await _dbContext.Set<T>().IgnoreQueryFilters().Where(deleteFilter).BatchDeleteAsync() > 0;
|
||||
return await _dbContext.Set<T>().IgnoreQueryFilters().Where(deleteFilter).ExecuteDeleteAsync() > 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -166,34 +166,64 @@ namespace IRaCIS.Core.Infra.EFCore
|
|||
{
|
||||
if (where == null) throw new ArgumentNullException(nameof(where));
|
||||
|
||||
var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
|
||||
|
||||
var hasPropNameList = bindings.Select(t => t.Member.Name).ToList();
|
||||
#region history 使用扩展删除包,同时自动赋值更新人 更新时间
|
||||
|
||||
//var bindings = ((MemberInitExpression)updateFactory.Body).Bindings.ToList();
|
||||
|
||||
//var hasPropNameList = bindings.Select(t => t.Member.Name).ToList();
|
||||
|
||||
|
||||
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
|
||||
//if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
|
||||
//{
|
||||
|
||||
// if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
|
||||
// {
|
||||
// bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
|
||||
|
||||
// }
|
||||
|
||||
// if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
|
||||
// {
|
||||
// bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(updateUserId)));
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
//var member = Expression.MemberInit(Expression.New(typeof(T)), bindings);
|
||||
|
||||
//var factory = Expression.Lambda<Func<T, T>>(member, Expression.Parameter(typeof(T), "x"));
|
||||
|
||||
//return await _dbContext.Set<T>().IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory).ConfigureAwait(false) > 0;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region efcore 7 & 8
|
||||
{
|
||||
var fieldValues = updateFactory.ExtractFieldValues();
|
||||
|
||||
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
|
||||
var hasPropNameList = ((MemberInitExpression)updateFactory.Body).Bindings.Select(t => t.Member.Name).ToList();
|
||||
|
||||
if (typeof(IAuditUpdate).IsAssignableFrom(typeof(T)))
|
||||
{
|
||||
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateTime))[0], Expression.Constant(DateTime.Now)));
|
||||
|
||||
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateTime)))
|
||||
{
|
||||
fieldValues.Add(nameof(IAuditUpdate.UpdateTime), DateTime.Now);
|
||||
}
|
||||
|
||||
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
|
||||
{
|
||||
fieldValues.Add(nameof(IAuditUpdate.UpdateUserId), updateUserId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasPropNameList.Contains(nameof(IAuditUpdate.UpdateUserId)))
|
||||
{
|
||||
bindings.Add(Expression.Bind(typeof(T).GetMember(nameof(IAuditUpdate.UpdateUserId))[0], Expression.Constant(updateUserId)));
|
||||
|
||||
}
|
||||
return await _dbContext.Set<T>().IgnoreQueryFilters().Where(where).ExecuteUpdateAsync(fieldValues).ConfigureAwait(false) > 0;
|
||||
}
|
||||
|
||||
|
||||
var member = Expression.MemberInit(Expression.New(typeof(T)), bindings);
|
||||
|
||||
var factory = Expression.Lambda<Func<T, T>>(member, Expression.Parameter(typeof(T), "x"));
|
||||
|
||||
|
||||
return await _dbContext.Set<T>().IgnoreQueryFilters().Where(where).BatchUpdateAsync(factory).ConfigureAwait(false) > 0;
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue