一直没用过 new try 记录一下

本文介绍了一种使用自定义缓冲区进行文件复制的方法。通过创建大小为8192字节的缓冲区,此方法能够有效地从源文件读取数据并写入目标文件。这种方法适用于需要高效文件传输的应用场景。
private static void customBufferStreamCopy(File source, File target) {try (InputStream fis = new FileInputStream(source);OutputStream fos = new FileOutputStream(target)){byte[] buf = new byte[8192];int i;while ((i = fis.read(buf)) != -1) {fos.write(buf, 0, i);}}catch (Exception e) {e.printStackTrace();}}
你提到: > ✅ 页面提示“导入29条记录成功” > ❌ 但列表页仍然没有显示这29条数据 结合你之前提供的日志(特别是 EF 的 SQL 查询日志),我们可以得出一个非常关键的结论: --- ## 🔍 核心问题:**数据看似“保存了”,但实际上并未真正写入数据库** 虽然前端显示“导入29条成功”,但从你的日志中 **看不到任何 `INSERT INTO [Persons]` 的 SQL 执行记录**,说明: > 🚫 `SaveChangesAsync()` 虽然可能被调用了,但: > > - 要么 **在错误的作用域中调用(如新建了 context 却没用 DI)** > - 要么 **被包装在一个未提交的事务里** > - 要么 **上下文被提前释放或未正确注入** --- ## ✅ 排查重点:为什么“提示成功”却“无数据插入”? ### ✅ 场景一:你在 `using` 块中创建了新的 `DbContext`,然后调用了 `SaveChanges` #### ❌ 错误示例: ```csharp [HttpPost] public async Task<IActionResult> ImportExcel(IFormFile file) { using var stream = new MemoryStream(); await file.CopyToAsync(stream); using var wb = new XLWorkbook(stream); // ⚠️ 手动 new 了一个 DbContext! using var tempContext = new AppDbContext(); for (...) { var person = ...; tempContext.People.Add(person); // 添加到临时上下文 } await tempContext.SaveChangesAsync(); // 看似保存了 return Json(new { success = true, message = "导入29条成功" }); } // 🔥 using 结束后,tempContext 被 dispose → 但其实连接已断,某些配置下会导致“假保存” ``` 👉 这种方式极危险!尤其是在使用依赖注入(DI)容器管理 `DbContext` 生命周期时,手动 new 会导致: - 上下文不共享 - 可能无法正确提交事务 - 某些数据库连接池机制下会静默失败 --- ### ✅ 正确做法:始终使用 DI 注入的 `_context` ```csharp private readonly AppDbContext _context; public PeopleController(AppDbContext context) { _context = context; } ``` 然后在整个方法中只使用这个 `_context`,不要自己 new! --- ### ✅ 场景二:你调用了 `SaveChangesAsync()`,但上下文未追踪实体(Add 失败) 比如你在循环外声明了 `Person person;`,但在每次迭代时忘了 `new Person()`。 #### ❌ 错误代码: ```csharp Person person = null!; for (int row = 2; row <= lastRow; row++) { person.Name = GetString(...); // ❌ 使用的是 null 实例! _context.People.Add(person); // 添加 null?不会报错但无效 } ``` 或者更隐蔽的问题: ```csharp var person = MapToPerson(...); if (person == null) continue; // 如果映射失败就跳过 else _context.People.Add(person); // 但如果所有都失败,则 Add 0 个 ``` 即使返回“导入29条成功”,其实是你**计数逻辑和实际添加脱节了!** --- ## ✅ 解决方案:确保“计数”与“Add + Save”一致 ### ✅ 改进后的可靠代码结构 ```csharp [HttpPost] public async Task<IActionResult> ImportExcel(IFormFile file) { var errors = new List<string>(); int successCount = 0; try { using var stream = new MemoryStream(); await file.CopyToAsync(stream); using var wb = new XLWorkbook(stream); var sheet = wb.Worksheet(1); var headers = ReadHeaders(sheet); if (headers.Count == 0) return Json(new { success = false, message = "无法读取表头" }); var lastRowNum = sheet.LastRowUsed()?.RowNumber(); if (lastRowNum < 2) return Json(new { success = false, message = "无数据行" }); for (int row = 2; row <= lastRowNum; row++) { try { var person = new Person(); person.Name = GetString(sheet, row, headers, "姓名", "Name"); if (string.IsNullOrWhiteSpace(person.Name)) { errors.Add($"第 {row} 行:姓名不能为空"); continue; } person.IdCardNumber = GetString(sheet, row, headers, "身份证号", "ID Card"); // 其他字段... // ✅ 只有到这里才算一条有效记录 _context.People.Add(person); successCount++; // ✅ 在 Add 后才计数 } catch (Exception ex) { errors.Add($"第 {row} 行解析异常: {ex.Message}"); } } // ✅ 关键点:只有在这里才真正持久化 await _context.SaveChangesAsync(); // 必须 await! // ✅ 日志确认 Console.WriteLine($"✅ 成功导入 {successCount} 条记录"); return Json(new { success = true, message = $"导入成功!共 {successCount} 条新增", successCount, errorCount = errors.Count, errors }); } catch (Exception ex) { // 🔥 特别注意:这里要能看到异常 Console.WriteLine($"❌ 导入失败: {ex}"); return Json(new { success = false, message = "服务器错误:" + ex.Message }); } } ``` --- ## ✅ 验证是否真的插入了数据 ### 方法 1:查看 EF 日志是否有 INSERT 语句 你应该看到类似这样的输出: ``` Executed DbCommand (3ms) [Parameters=[@p0='张三', @p1='110...', ...], CommandType='Text'] INSERT INTO [Persons] ([Name], [IdCardNumber], ...) VALUES (@p0, @p1, ...) ``` 如果没有这条日志 → 说明压根没执行插入。 --- ### 方法 2:直接查询数据库 打开 SQL Server Management Studio 或 SQLite Browser,运行: ```sql SELECT COUNT(*) FROM Persons -- 或者查最新几条 SELECT TOP 5 * FROM Persons ORDER BY Id DESC ``` 看看有没有新增的记录。 --- ### 方法 3:重启应用后刷新页面 有时候缓存会让旧数据持续显示。尝试: - 重启项目(`dotnet run`) - 清除浏览器缓存 - 刷新 `/People` 页面 --- ## ✅ 加强调试建议 ### 1. 在 `SaveChangesAsync()` 前后加日志 ```csharp Console.WriteLine($"准备保存 {successCount} 条记录..."); await _context.SaveChangesAsync(); Console.WriteLine("✅ SaveChangesAsync() 执行完成!"); ``` 如果只打印前一句,没打印后一句 → 说明卡在 `SaveChangesAsync()` 里抛异常了。 --- ### 2. 捕获 `DbUpdateException` ```csharp try { await _context.SaveChangesAsync(); } catch (DbUpdateException dbEx) { foreach (var entry in dbEx.Entries) { Console.WriteLine($"Entity: {entry.Entity}, State: {entry.State}"); } throw; // 重新抛出便于调试 } ``` 常见原因包括: - 主键冲突 - 字段长度超限(如 Name > 50 字符) - 外键约束失败(HouseholdId 不存在) --- ## ✅ 总结:你现在应该检查什么? | 检查项 | 是否通过 | |------|--------| | ✅ 是否使用了 DI 注入的 `_context`?而不是手动 new | ☐ | | ✅ `successCount++` 是否放在 `_context.People.Add(...)` 之后? | ☐ | | ✅ 是否真的看到了 `INSERT INTO [Persons]` 的日志? | ☐ | | ✅ 数据库中能否查到新记录?(直接查表) | ☐ | | ✅ `SaveChangesAsync()` 是否被 `await`? | ☐ | | ✅ 是否有全局过滤器(如 `.HasQueryFilter(p => !p.IsDeleted)`)导致查不到? | ☐ | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值