using Magicodes.ExporterAndImporter.Core; using Magicodes.ExporterAndImporter.Core.Extension; using Magicodes.ExporterAndImporter.Excel; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using Omu.ValueInjecter; using System; using System.Data; using System.Data.Common; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; using TaskManager.Contracts.Dtos; using TaskManager.Controllers; using TaskManager.Entity; using TaskManager.EntityFramework; using TaskManager.EntityFramework.Repository; using Wood.Service; using Wood.Util; using Wood.Util.Filters; namespace TaskManager.Controllers { //[ApiController] //[Route("api/[controller]")] public class CheryRecurringJobOutPageController : RecurringJobBaseController where T : CherryReadBaseEntity, new() where ToutputDetial : CherryReadBaseEntityDto { protected readonly IRepository _repository; public CheryRecurringJobOutPageController(HttpClient httpClient, JobDbContext jobDbContext, LogController log, IRepository repository) : base(httpClient, jobDbContext, log) { _repository = repository; } protected virtual async Task ConfirmDataInsertAsync(List plist,JobDbContext dbContext, DbTransaction dbTransaction) { } private async Task InsertDataAsync(List list) { if (list.Any()) { using (var transaction = await _jobDbContext.Database.BeginTransactionAsync()) { var tran = transaction.GetDbTransaction(); try { await _jobDbContext.BulkMergeAsync(list, options => { options.ColumnPrimaryKeyExpression = p => p.Id; }); //_jobDbContext.BulkMerge(list, options => { // options.ColumnPrimaryKeyExpression = p => p.Id; //}); await ConfirmDataInsertAsync(list, _jobDbContext, tran); // 提交事务 await transaction.CommitAsync(); } catch (Exception ex) { await transaction.RollbackAsync(); new JsonResult(new { Code = 400, Message = ex.Message }); } } } } [NonAction] public async Task> FetchAllDataAsync(string inputdate) { var allData = new List(); int totalItems = 0; int pageSize = 0; int currentPage = 1; string date = !string.IsNullOrEmpty(inputdate) ? inputdate : DateTime.Now.ToString("yyyy-MM-dd"); var taskId = Guid.NewGuid(); var version = date.Replace("-", ""); var readedcount = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Count(); if (readedcount == 0)//第一次请求用false,接口人胡启名要求 { PagedResponse firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date,PageSize=CPageSize, IsForce = false},taskId,version); if (firstResponse == null || firstResponse.Code != 200) { await _logger.AddError("首次请求失败,无法获取分页信息。", TaskName,taskId,version); return allData; } if (firstResponse.Data.Total == "0") { await _logger.AddInfo("首次请求失败,Total为0是否已经全部读取过。", TaskName, taskId, version); return allData; } if (readedcount != int.Parse(firstResponse.Data.Total))//记录数不相等 { var ids = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList();//已经同步的ID totalItems = int.Parse(firstResponse.Data.Total); pageSize = int.Parse(firstResponse.Data.PageSize); List pagefirstList = new List(); // firstResponse.Data.Rows.Select(p=>p.Id) foreach (var itm in firstResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; entity.RequestDate = date; pagefirstList.Add(entity); allData.Add(itm); } //if (readedcount > 0) //{ // var listrows = firstResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); // foreach (var itm in firstResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // pagefirstList.Add(entity); // allData.Add(itm); // } //} //else //{ // foreach (var itm in firstResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // pagefirstList.Add(entity); // allData.Add(itm); // } //} if (pagefirstList.Any()) { await InsertDataAsync(pagefirstList); } // 计算总页数 int totalPages = (int)Math.Ceiling((double)totalItems / pageSize); //Console.WriteLine($"总共需要请求 {totalPages} 页数据"); // 循环请求剩余页面 for (currentPage = 2; currentPage <= totalPages; currentPage++) { PAGE_DTO pageinput = new PAGE_DTO() { Date = date, PageNum = currentPage, PageSize = CPageSize, IsForce = false }; Console.WriteLine($"正在请求第 {currentPage} 页..."); PagedResponse pageResponse = await GetPageAsync(pageinput, taskId, version); if (pageResponse?.Data.Rows != null && pageResponse.Data.Rows.Count > 0) { List pageList = new List(); foreach (var itm in pageResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; entity.RequestDate = date; pageList.Add(entity); allData.Add(itm); } //if (readedcount > 0) //{ // var listrows = pageResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); // foreach (var itm in pageResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // pageList.Add(entity); // allData.Add(itm); // } //} //else //{ // foreach (var itm in pageResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // pageList.Add(entity); // allData.Add(itm); // } //} if (pageList.Any()) { await InsertDataAsync(pageList); } } else { await _logger.AddInfo($"第 {currentPage} 页未返回数据", TaskName, taskId, version); } // 简单的请求间隔,避免过于频繁 await Task.Delay(200); } await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName, taskId, version); } } else { PagedResponse firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date, PageSize = CPageSize, IsForce = true },taskId,version); if (firstResponse == null || firstResponse.Code != 200) { await _logger.AddInfo("首次请求失败,无法获取分页信息。", TaskName, taskId, version); return allData; } if (firstResponse.Data.Total == "0") { await _logger.AddInfo("首次请求失败,Total为0是否已经全部读取过。", TaskName, taskId, version); return allData; } if (readedcount != int.Parse(firstResponse.Data.Total))//记录数不相等 { var ids = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList();//已经同步的ID totalItems = int.Parse(firstResponse.Data.Total); pageSize = int.Parse(firstResponse.Data.PageSize); List pagefirstList = new List(); foreach (var itm in firstResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; pagefirstList.Add(entity); entity.RequestDate = date; allData.Add(itm); } //if (readedcount > 0) //{ // var listrows = firstResponse.Data.Rows.Where(p => !ids.Contains(p.Id)); // foreach (var itm in firstResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // pagefirstList.Add(entity); // allData.Add(itm); // } //} //else //{ // foreach (var itm in firstResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // pagefirstList.Add(entity); // allData.Add(itm); // } //} if (pagefirstList.Any()) { await InsertDataAsync(pagefirstList); } //Console.WriteLine($"总记录数: {totalItems}, 每页大小: {pageSize}"); // 计算总页数 int totalPages = (int)Math.Ceiling((double)totalItems / pageSize); //Console.WriteLine($"总共需要请求 {totalPages} 页数据"); // 循环请求剩余页面 for (currentPage = 2; currentPage <= totalPages; currentPage++) { PAGE_DTO pageinput = new PAGE_DTO() { Date = date, PageNum = currentPage, PageSize = CPageSize, IsForce = true }; //Console.WriteLine($"正在请求第 {currentPage} 页..."); PagedResponse pageResponse = await GetPageAsync(pageinput,taskId,version); if (pageResponse?.Data.Rows != null && pageResponse.Data.Rows.Count > 0) { List pageList = new List(); foreach (var itm in pageResponse.Data.Rows) { T entity = new T(); entity.InjectFrom(itm); entity.CreationTime = DateTime.Now; entity.RequestDate = date; pageList.Add(entity); allData.Add(itm); } if (pageList.Any()) { await InsertDataAsync(pageList); } //await _logger.AddInfo($"成功获取 {pageResponse.Data.Rows.Count} 条记录", TaskName); } else { await _logger.AddInfo($"第 {currentPage} 页未返回数据", TaskName, taskId, version); } // 简单的请求间隔,避免过于频繁 await Task.Delay(200); } await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName, taskId, version); } } // 首次请求获取总条数和分页信息 return allData; } private async Task> GetPageAsync(PAGE_DTO input,Guid taskId,string version) { try { var inputjson = JsonSerializer.Serialize(input, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, WriteIndented = true // 可选,用于格式化输出 } ); inputjson = RemoveWhitespace(inputjson); var content = await Post(Url, Path, inputjson, taskId, version); if (!string.IsNullOrEmpty(content)) { var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, Converters = { new JsonStringEnumConverter(), // 枚举转换 new CustomDateTimeConverter("yyyy-MM-dd HH:mm:ss","yyyy-MM-dd") // 日期转换 } }; return JsonSerializer.Deserialize>(content, options); } else { await _logger.AddError($"调用接口无返回值{Url}", TaskName, taskId, version); return null; } } catch (Exception ex) { await _logger.AddError($"调用接口无返回值错误{ex.Message}", TaskName, taskId, version); return null; } } /// /// 手工获取调用接口 /// /// 任务名称 /// 请求日期 /// 客户(Chery) /// [HttpGet] public virtual async Task CustomInvokeAsync(string taskName, string inputdate,string client) { var first= _jobDbContext.TaskConifgure.FirstOrDefault(p => p.TaskName == taskName && p.Client == client); if (first == null) { return; } Url =first.Url; Path = first.Api; TaskName = taskName; CPageSize = first.PageSize; await FetchAllDataAsync(inputdate); } protected override async Task DoExecutingAsync(string url, string path, string takName, string client, int pagesize) { Url = url; Path = path; TaskName = takName; Client = client; CPageSize = pagesize; await FetchAllDataAsync(string.Empty); } /// /// 获取所有记录 /// /// [HttpGet] public async Task>> GetAll() { return await _repository.GetAllAsync() as List; } /// /// 获取实体通过ID /// /// /// [HttpGet("{id}")] public async Task> GetById(int id) { var entity = await _repository.GetByIdAsync(id); if (entity == null) return NotFound(); return entity; } [HttpPost] public async Task> Create(T entity) { entity.CreationTime = DateTime.Now; var createdEntity = await _repository.AddAsync(entity); return CreatedAtAction(nameof(GetById), new { id = createdEntity.Id }, createdEntity); } /// /// 修改 /// /// /// [HttpPut("{id}")] public async Task Update(T entity) { if (entity.UId == 0) { throw new Exception("更新时,实体主键UId不能为空或0"); } var target = await _repository.GetByIdAsync(entity.UId); if (target == null) { throw new Exception($"CheryRecurringJobOutPageController.Update报错:根据UId{entity.UId}没有找到记录"); return new JsonResult(new { Code = 400, Message = "修改失败!" }); } EntityMapper.Trans(entity, target, "UId"); await _repository.UpdateAsync(target); return new JsonResult(new { Code = 200, Message = "修改成功!" }); } /// /// 删除 /// /// /// [HttpDelete("{id}")] public async Task Delete(int id) { await _repository.DeleteAsync(id); return new JsonResult(new { Code = 200, Message = "删除成功!" }); ; } /// /// 分页 /// /// /// [HttpPost] public async Task>> GetDataPaged(RequestInputBase input) { var pagingParams = new PagingParams { PageNumber = input.pageNumber, PageSize = input.pageSize, SortBy = input.sortBy, IsAscending = input.isAscending, }; // 可以在这里构建表达式树过滤条件 Expression> filter = null; var pagedResult = await _repository.GetDataPagedAsync(filter, pagingParams, input.Condition); return Ok(pagedResult); } /// /// 导出 /// /// /// 每页条数 /// 排序字段 /// 正序还是倒序 /// 过滤条件 /// /// 导出New /// /// /// [HttpPost] public async Task ExportData(RequestInputBase input) { var pagingParams = new PagingParams { PageNumber = input.pageNumber, PageSize = input.pageSize, SortBy = input.sortBy, IsAscending = input.isAscending, }; // 可以在这里构建表达式树过滤条件 //Expression> filter = null; var pagedResult = await _repository.GetDataPagedAsync(null, pagingParams, input.Condition); return await ExportFile(pagedResult.Data, Guid.NewGuid().ToString() + ".xlsx"); } protected async Task ExportFile(ICollection dtos, string fileName) { var excelExporter = HttpContext.RequestServices.GetRequiredService(); var res = await excelExporter.ExportAsByteArray(dtos); return new FileStreamResult(new MemoryStream(res), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "_" + fileName }; } /// /// 获取导入模板 /// /// [HttpGet] public async Task GetImportTemplate() { try { // 创建导入模板生成器 var importer = new ExcelImporter(); // 生成导入模板流(这里假设使用 YourModel 作为导入模型) var bytes = await importer.GenerateTemplateBytes(); //using var stream = new MemoryStream(bytes); //stream.Seek(0, SeekOrigin.Begin); // 设置友好的文件名,例如:"导入模板_20250530.xlsx" var fileName = $"导入模板_{DateTime.Now:yyyyMMdd}.xlsx"; // 返回文件流结果 return new FileStreamResult(new MemoryStream(bytes), "application/octet-stream") { FileDownloadName = DateTime.Now.ToString("yyyyMMddHHmm") + "_" + fileName }; //return File( // fileStream: stream, // contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // fileDownloadName: fileName); } catch (Exception ex) { // 记录异常日志 Console.WriteLine($"生成导入模板时出错: {ex.Message}"); // 返回错误响应 return StatusCode(500, "生成导入模板时发生错误"); } } /// /// 导入 /// /// 选择文件 /// [HttpPost("Import")] public async virtual Task Import(IFormFile file) { if (file == null || file.Length <= 0) { return NotFound("No file uploaded."); } try { var excelImporter = HttpContext.RequestServices.GetRequiredService(); var importResult = await excelImporter.Import(file.OpenReadStream()); if (importResult.HasError) { StringBuilder sb = new StringBuilder(); foreach (var rowErr in importResult.RowErrors) { string temp = string.Join(";", rowErr.FieldErrors.Select(itm => $"第{rowErr.RowIndex}行:{itm.Key}-{itm.Value}")); sb.AppendLine(temp); } foreach (var templateErr in importResult.TemplateErrors) { string temp = $"列名:{templateErr.RequireColumnName},错误信息:{templateErr.Message}"; sb.AppendLine(temp); } throw new Exception(sb.ToString()); } // 处理导入的数据 List list = importResult.Data.ToList(); await ImportBefore(list); // 校验数据长度 var validationErrors = ValidationHelper.ValidateDataLength(list, _jobDbContext); if (validationErrors.Any()) { throw new Exception("数据校验失败:" + string.Join(", ", validationErrors)); } foreach (var item in list) { item.ReadState = true; item.CreationTime = CommonHelper.CurrentTime; } await _jobDbContext.BulkInsertAsync(list); await ImportAfter(list); return new JsonResult(new { Code = 200, Message = "修改成功!" }); } catch (Exception ex) { //await _logger.AddError(ex.Message, TaskName); return new JsonResult(new { Code = 400, Message = "导入失败:" + ex.Message }); } } protected virtual async Task ImportBefore(List p_list) { } protected virtual async Task ImportAfter(List p_list) { } /// /// 高级查询字段 /// /// [HttpGet("fields")] public IActionResult GetQueryFields() { // 获取实体类的所有属性 Type entityType = typeof(T); var properties = entityType.GetProperties(); // 构建字段信息列表 var fields = new List(); foreach (var property in properties) { // 获取ExporterHeader特性中的DisplayName var exporterHeader = property.GetCustomAttribute(); string displayName = exporterHeader?.DisplayName ?? property.Name; // 获取属性类型 string dataType = property.PropertyType.Name; // 添加到字段列表 fields.Add(new QueryFieldInfo { FieldName = property.Name, DisplayName = displayName, DataType = dataType }); } return Ok(fields); } } public class CustomDateTimeConverter : JsonConverter { private readonly string[] _formats; public CustomDateTimeConverter(params string[] formats) { _formats = formats; } public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) { throw new JsonException($"Expected string but got {reader.TokenType}"); } var dateString = reader.GetString(); // 尝试解析多种日期格式 foreach (var format in _formats) { if (DateTime.TryParseExact(dateString, format, null, System.Globalization.DateTimeStyles.None, out var result)) { return result; } } // 如果无法解析,尝试默认解析 if (DateTime.TryParse(dateString, out var defaultResult)) { return defaultResult; } throw new JsonException($"无法解析日期: {dateString}"); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString(_formats[0])); } } } /*并发修改*/ //public class CheryRecurringJobOutPageController : RecurringJobBaseController // where T : CherryReadBaseEntity, new() // where ToutputDetial : CherryReadBaseEntityDto //{ // // 其他成员保持不变... // // 并发控制参数 // private readonly int _maxConcurrency; // private readonly SemaphoreSlim _semaphore; // public CheryRecurringJobOutPageController( // HttpClient httpClient, // JobDbContext jobDbContext, // LogController log, // IRepository repository, // int maxConcurrency = 5) : base(httpClient, jobDbContext, log) // { // _repository = repository; // _maxConcurrency = maxConcurrency; // _semaphore = new SemaphoreSlim(maxConcurrency); // } // [NonAction] // public async Task> FetchAllDataAsync(string inputdate) // { // var allData = new List(); // int totalItems = 0; // int pageSize = 0; // int currentPage = 1; // string date = !string.IsNullOrEmpty(inputdate) ? inputdate : DateTime.Now.ToString("yyyy-MM-dd"); // var taskId = Guid.NewGuid(); // var version = date.Replace("-", ""); // var readedcount = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Count(); // if (readedcount == 0) // { // PagedResponse firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date, PageSize = CPageSize, IsForce = false }, taskId, version); // if (firstResponse == null || firstResponse.Code != 200) // { // await _logger.AddError("首次请求失败,无法获取分页信息。", TaskName, taskId, version); // return allData; // } // if (firstResponse.Data.Total == "0") // { // await _logger.AddInfo("首次请求失败,Total为0是否已经全部读取过。", TaskName, taskId, version); // return allData; // } // if (readedcount != int.Parse(firstResponse.Data.Total)) // { // var ids = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList(); // totalItems = int.Parse(firstResponse.Data.Total); // pageSize = int.Parse(firstResponse.Data.PageSize); // List pagefirstList = new List(); // foreach (var itm in firstResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // entity.RequestDate = date; // pagefirstList.Add(entity); // allData.Add(itm); // } // if (pagefirstList.Any()) // { // await InsertDataAsync(pagefirstList); // } // // 计算总页数 // int totalPages = (int)Math.Ceiling((double)totalItems / pageSize); // // 并发请求剩余页面 // await FetchPagesConcurrently(2, totalPages, date, taskId, version, ids, allData); // await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName, taskId, version); // } // } // else // { // // 类似的逻辑,修改为并发请求 // PagedResponse firstResponse = await GetPageAsync(new PAGE_DTO() { Date = date, PageSize = CPageSize, IsForce = true }, taskId, version); // if (firstResponse == null || firstResponse.Code != 200) // { // await _logger.AddInfo("首次请求失败,无法获取分页信息。", TaskName, taskId, version); // return allData; // } // if (firstResponse.Data.Total == "0") // { // await _logger.AddInfo("首次请求失败,Total为0是否已经全部读取过。", TaskName, taskId, version); // return allData; // } // if (readedcount != int.Parse(firstResponse.Data.Total)) // { // var ids = _jobDbContext.Set().Where(p => p.RequestDate == inputdate).Select(p => p.Id).ToList(); // totalItems = int.Parse(firstResponse.Data.Total); // pageSize = int.Parse(firstResponse.Data.PageSize); // List pagefirstList = new List(); // foreach (var itm in firstResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // entity.RequestDate = date; // pagefirstList.Add(entity); // allData.Add(itm); // } // if (pagefirstList.Any()) // { // await InsertDataAsync(pagefirstList); // } // int totalPages = (int)Math.Ceiling((double)totalItems / pageSize); // // 并发请求剩余页面 // await FetchPagesConcurrently(2, totalPages, date, taskId, version, ids, allData); // await _logger.AddInfo($"所有数据获取完成,总共获取了 {allData.Count} 条记录", TaskName, taskId, version); // } // } // return allData; // } // private async Task FetchPagesConcurrently(int startPage, int totalPages, string date, Guid taskId, string version, List existingIds, List allData) // { // var tasks = new List(); // // 为每个页面创建一个任务 // for (int page = startPage; page <= totalPages; page++) // { // int currentPage = page; // 避免闭包问题 // tasks.Add(ProcessPageAsync(currentPage, date, taskId, version, existingIds, allData)); // } // // 分批执行任务,控制并发量 // for (int i = 0; i < tasks.Count; i += _maxConcurrency) // { // int batchSize = Math.Min(_maxConcurrency, tasks.Count - i); // var batch = tasks.GetRange(i, batchSize); // await Task.WhenAll(batch); // } // } // private async Task ProcessPageAsync(int page, string date, Guid taskId, string version, List existingIds, List allData) // { // await _semaphore.WaitAsync(); // 限制并发量 // try // { // PAGE_DTO pageinput = new PAGE_DTO() { Date = date, PageNum = page, PageSize = CPageSize, IsForce = existingIds.Count == 0 ? false : true }; // //Console.WriteLine($"正在请求第 {page} 页..."); // PagedResponse pageResponse = await GetPageAsync(pageinput, taskId, version); // if (pageResponse?.Data.Rows != null && pageResponse.Data.Rows.Count > 0) // { // List pageList = new List(); // foreach (var itm in pageResponse.Data.Rows) // { // T entity = new T(); // entity.InjectFrom(itm); // entity.CreationTime = DateTime.Now; // entity.RequestDate = date; // pageList.Add(entity); // allData.Add(itm); // } // if (pageList.Any()) // { // await InsertDataAsync(pageList); // } // } // else // { // await _logger.AddInfo($"第 {page} 页未返回数据", TaskName, taskId, version); // } // } // catch (Exception ex) // { // await _logger.AddError($"第 {page} 页请求出错: {ex.Message}", TaskName, taskId, version); // } // finally // { // _semaphore.Release(); // 释放信号量 // } // } // // 优化数据库插入方法,支持批量处理 // private async Task InsertDataAsync(List list) // { // if (list.Any()) // { // // 使用分块处理大列表,避免内存压力 // int batchSize = 500; // for (int i = 0; i < list.Count; i += batchSize) // { // int end = Math.Min(i + batchSize, list.Count); // var batch = list.GetRange(i, end - i); // using (var transaction = await _jobDbContext.Database.BeginTransactionAsync()) // { // try // { // await _jobDbContext.BulkMergeAsync(batch, options => { options.ColumnPrimaryKeyExpression = p => p.Id; }); // await ConfirmDataInsertAsync(batch, _jobDbContext, transaction.GetDbTransaction()); // await transaction.CommitAsync(); // } // catch (Exception ex) // { // await transaction.RollbackAsync(); // await _logger.AddError($"数据插入失败: {ex.Message}", TaskName, Guid.NewGuid(), "1.0"); // } // } // // 短暂延迟,避免数据库过载 // await Task.Delay(100); // } // } // } // // 其他方法保持不变... //}