Browse Source

并发异常捕获

master
wxd 1 month ago
parent
commit
392a0916db
  1. 107
      src/Shentun.Peis.HttpApi.Host/Filter/CustomerExceptionFilterAttribute.cs

107
src/Shentun.Peis.HttpApi.Host/Filter/CustomerExceptionFilterAttribute.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
@ -15,6 +16,7 @@ using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.Domain.Entities;
namespace Shentun.Peis
@ -65,6 +67,69 @@ namespace Shentun.Peis
{
//errorMessage = "数据库更新错误:" + exceptionContext.Exception.Message;
errorMessage = "数据库更新错误:" + exceptionContext.Exception.Message + "=>" + exceptionContext.Exception.InnerException.Message;
}
else if (exceptionContext.Exception is AbpDbConcurrencyException concurrencyEx)
{
var detailBuilder = new System.Text.StringBuilder();
detailBuilder.AppendLine("并发冲突详细信息:");
// 从内部异常获取详细信息
if (concurrencyEx.InnerException is DbUpdateConcurrencyException dbUpdateEx)
{
// 获取涉及的所有实体
foreach (var entry in dbUpdateEx.Entries)
{
var entity = entry.Entity;
var entityType = entity.GetType().Name;
var entityId = GetEntityId(entity); // 使用之前的辅助方法
detailBuilder.AppendLine($"\n▶ 冲突实体 [{entityType}]");
detailBuilder.AppendLine($" 实体ID:{entityId}");
detailBuilder.AppendLine($" 状态:{entry.State}");
// 获取数据库中的当前值
var databaseValues = entry.GetDatabaseValues();
if (databaseValues != null)
{
// 记录所有发生冲突的属性
foreach (var property in entry.Properties)
{
var originalValue = property.OriginalValue;
var currentValue = property.CurrentValue;
var databaseValue = databaseValues[property.Metadata.Name];
if (!Equals(currentValue, databaseValue))
{
detailBuilder.AppendLine($" ⚠ 字段 [{property.Metadata.Name}] 冲突:");
detailBuilder.AppendLine($" 当前值:{currentValue}");
detailBuilder.AppendLine($" 数据库值:{databaseValue}");
detailBuilder.AppendLine($" 原始值:{originalValue}");
}
}
}
else
{
detailBuilder.AppendLine($" 数据库记录可能已被删除");
}
}
}
else
{
// 如果没有内部异常,只能记录基本信息
detailBuilder.AppendLine($"异常类型:{concurrencyEx.GetType().Name}");
detailBuilder.AppendLine($"消息:{concurrencyEx.Message}");
}
var detailInfo = detailBuilder.ToString();
// 记录详细日志
_logger.LogWarning(concurrencyEx, "并发冲突详情:\n{Detail}", detailInfo);
errorMessage = "数据并发,稍后再试";
}
else if (exceptionContext.Exception is BusinessException)
{
@ -158,5 +223,45 @@ namespace Shentun.Peis
ReadException(ex.InnerException, ref error);
}
}
private string GetEntityId(object entity)
{
try
{
// 方法1:通过实体类型获取 Id 属性
var entityType = entity.GetType();
// 查找名为 "Id" 的属性(不区分大小写)
var idProperty = entityType.GetProperty("Id") ??
entityType.GetProperty("id") ??
entityType.GetProperty("ID");
if (idProperty != null)
{
var idValue = idProperty.GetValue(entity);
return idValue?.ToString() ?? "null";
}
// 如果没找到 Id,查找可能的主键属性(以 Id 结尾)
var possibleKeys = entityType.GetProperties()
.Where(p => p.Name.EndsWith("Id", StringComparison.OrdinalIgnoreCase))
.ToList();
if (possibleKeys.Any())
{
var keyValues = possibleKeys
.Select(p => $"{p.Name}:{p.GetValue(entity)}")
.ToList();
return string.Join(", ", keyValues);
}
return "未找到主键属性";
}
catch (Exception ex)
{
return $"获取主键失败:{ex.Message}";
}
}
}
}
Loading…
Cancel
Save