Skip to content

Aop 批量更新审计字段时统一使用相同值 #2236

@HuiJiOnGit

Description

@HuiJiOnGit

<!-- 
以下为必读项,不仔细阅读会导致你的 Issue 被关闭

1. 该分类下只能提交 Feature,如果要询问使用方法等,请前往讨论区:https://github.com/dotnetcore/FreeSql/discussions
2. 请尽量详细的描述清楚你的需求
-->

#### Feature 特性

批量执行 `InsertOrUpdate<T>().SetSource(entities)` 时,当通过 `Aop.AuditValue` 设置的更新字段值在所有实体中均相同,期望生成统一的 `SET` 赋值,而非为每个实体生成独立的 `CASE WHEN` 分支。

**当前生成的 SQL:**
```sql
UPDATE [Table] 
SET [UpdateTime] = CASE [Id]
    WHEN 178493 THEN '2026-04-29 14:47:11.015'
    WHEN 178494 THEN '2026-04-29 14:47:11.016'
    WHEN 178495 THEN '2026-04-29 14:47:11.017'
END
WHERE [Id] IN (178493, 178494, 178495)

期望生成的 SQL:

UPDATE [Table] 
SET [UpdateTime] = '2026-04-29 14:47:11.015'
WHERE [Id] IN (178493, 178494, 178495)

简要描述原因

Aop.AuditValue 事件中对 AuditValueType.Update 统一赋值时(如设置更新时间 DateTime.Now),所有实体的该字段值实际上是相同的。

但 FreeSql 当前会为每个实体执行AOP代码的时候UpdateTime 都不一样, 导致生成独立的 CASE WHEN 分支,导致以下问题:

  1. SQL 体积随批量数量线性膨胀,影响传输和执行效率
  2. CASE WHEN 需要数据库逐行判断,无额外收益
  3. 毫秒级时间差导致同一批次数据审计时间不一致

建议:当 AuditValue 事件中设置的值对所有实体相同时,自动优化为统一赋值;或提供配置项让开发者显式标记"该审计字段为批量统一值"。

使用场景

批量更新时自动维护审计字段,如:

// AOP 统一设置审计值
freeSql.Aop.AuditValue += (_, e) =>
{
    if (e.AuditValueType == AuditValueType.Update)
    {
        e.Value = e.Column.CsName switch
        {
            "UpdateTime" => DateTime.Now,
            _ => e.Value
        };
    }
};

// 批量插入或更新
await freeSql.Update<Entity>()
    .SetSource(entities)
    .ExecuteAffrowsAsync();

期望批量字段值统一时,通过AOP修改的审计字段生成的 SQL 能自动优化为单一赋值,减少 SQL 体积并提升执行效率。


---

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions