Skip to content

InsertOrUpdate下使用UpdateSet的行为让人困惑 #2230

@LeaFrock

Description

@LeaFrock

问题描述及重现代码:

假设有TestEntity表,实体定义如下:

    public class TestEntity
    {
        [Column(IsPrimary = true, IsIdentity = true)]
        public int Id { get; set; }

        public int Key { get; set; }

        public int Year { get; set; }

        public int Count { get; set; }
    }

现需要实现逻辑:创建一个实例,如果表中没有则插入新行;否则将表中命中的行Count列加1。

很容易写出以下代码:

        var statEntity = new TestEntity()
        {
            Key = 1,
            Year = 2026
        };
        var sql = freeSql.InsertOrUpdate<TestEntity>()
          .SetSource(statEntity, p => new { p.Key })
          .UpdateSet((a, b) => a.Count == a.Count + 1)
          .ToSql();

但实际生成的SQL是:

MERGE INTO [TestEntity] t1 
USING (SELECT 0 as [Id], 1 as [Key], 2026 as [Year], 0 as [Count] ) t2 ON (t1.[Key] = t2.[Key]) 
WHEN MATCHED THEN 
  update set [Year] = t2.[Year], [Count] = (t1.[Count] + 1)  -- Year被更新为2026!
WHEN NOT MATCHED THEN 
  insert ([Key], [Year], [Count]) 
  values (t2.[Key], t2.[Year], t2.[Count]);

调整代码v1:

        var sql = freeSql.InsertOrUpdate<TestEntity>()
          .SetSource(statEntity, p => new { p.Key })
          .UpdateSet((a, b) => a.Count == a.Count + 1)
          .UpdateColumns(a => a.Count)
          .ToSql();

SQL符合预期:

MERGE INTO [TestEntity] t1 
USING (SELECT 0 as [Id], 1 as [Key], 2026 as [Year], 0 as [Count] ) t2 ON (t1.[Key] = t2.[Key]) 
WHEN MATCHED THEN 
  update set [Count] = (t1.[Count] + 1) 
WHEN NOT MATCHED THEN 
  insert ([Key], [Year], [Count]) 
  values (t2.[Key], t2.[Year], t2.[Count]);

调整代码v2:

        var sql = freeSql.InsertOrUpdate<TestEntity>()
          .SetSource(statEntity, p => new { p.Key })
          .UpdateSet((a, b) => a.Count == a.Count + 1)
          .UpdateColumns(a => a.Year) // 故意为之
          .ToSql();

SQL:

MERGE INTO [TestEntity] t1 
USING (SELECT 0 as [Id], 1 as [Key], 2026 as [Year], 0 as [Count] ) t2 ON (t1.[Key] = t2.[Key]) 
WHEN MATCHED THEN 
  update set [Year] = t2.[Year], [Count] = (t1.[Count] + 1)  -- UodateColumn约束失效
WHEN NOT MATCHED THEN 
  insert ([Key], [Year], [Count]) 
  values (t2.[Key], t2.[Year], t2.[Count]);

调整UpdateColumns和UpdateSet顺序,对结果没有影响。

以上行为实在让人困惑,尤其文档中没有明确UpdateColumn和UpdateSet的组合关系,极易让开发者误会导致数据被错误覆盖。

数据库版本

SqlServer 2016

安装的Nuget包

3.5.309

.net framework/. net core? 及具体版本

.NET 10

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