【问题标题】:SELECT with CASE after UPDATE uses old valueUPDATE 后使用 CASE SELECT 使用旧值
【发布时间】:2018-08-07 11:50:06
【问题描述】:

我对实体框架生成的 sql 语句组合有疑问。

看起来 powerloss 字段的更新值没有在更新语句完成并执行 select 后立即设置。

我不知道这是否可能。 也许我只是错过了一些东西。

代码执行后更新和选择的行和表中的数据都是正确的。

它应该做什么(并且它 99% 的时间都在做)

我从设备获取 counterValue 并将其插入到 sql-server 2008 R2 (SP3) 上的表中。如果设备断电并且在某个时刻又回来了,则数据库中最后一个 counterValue 条目中的字段“powerloss”将更新为 1(true)。默认情况下,该字段为 0(false)。

之后,我查询这个设备的最后一个 counterValue 并取反。 但仅当“powerloss”字段为 0(假)时。否则查询必须返回零。

出了什么问题

有时(非常罕见)当 powerloss 字段在选择之前更新为 1(true) 时,我得到否定的 counterValue...

这至少是我的日志文件向我显示的内容(记录了每个查询)。

代码的作用

  1. 创建 dbContext
  2. BeginTransaction(isolationLevel.ReadComitted)
  3. WriteNewCounterValue(断电后)

    1. 更新字段powerloss=true

    2. 根据 powerloss 字段中的值选择 counterValue

      offset = (From qItem In DB.SlaveCounterEntries 
                Where qItem.deviceId= deviceId
                And qItem.Received < timestamp 
                Order By qItem.Received Descending 
                Select If(qItem.Powerloss = True, 0, -qItem.CounterValue) 
                Take 1).SingleOrDefault()
      
    3. 在表中插入新的 counterValue

  4. 提交事务
  5. 处置 dbContext

生成的 sql 语句

更新声明:

UPDATE [dbo].[slaveCounter]
    SET [powerloss] = @0
    WHERE ([id] = @1)
    -- @0: 'True' (Type = Boolean)
    -- @1: '3371747' (Type = Int32)
    -- Executing at 29.06.2018 05:57:24 +02:00
    -- Completed in 0 ms with result: 1

select 语句(更新后 14 毫秒):

SELECT TOP (1) 
    [Project1].[C1] AS [C1]
    FROM ( SELECT 
        CASE WHEN (1 = [Extent1].[powerloss]) THEN 0 ELSE  -([Extent1].[counterValue]) END AS [C1], 
        [Extent1].[datReceived] AS [datReceived]
        FROM [dbo].[slaveCounter] AS [Extent1]
        WHERE ([Extent1].[slaveId] = @p__linq__0) AND ([Extent1].[datReceived] < @p__linq__1)
    )  AS [Project1]
    ORDER BY [Project1].[datReceived] DESC

    -- p__linq__0: '48' (Type = Int16, IsNullable = false)
    -- p__linq__1: '28.06.2018 23:00:03' (Type = DateTime2, IsNullable = false)
    -- Executing at 29.06.2018 05:57:24 +02:00
    -- Completed in 0 ms with result: SqlDataReader

【问题讨论】:

  • 如果更新后14ms,可能还没有提交。
  • 如果他不使用 NOLOCK,他将如何读取未提交的数据?更新在事务中。他是否也可以保存时间戳,然后也记录下来?
  • 事务只确保数据被读取,就好像它是按顺序完成的一样,不保证实际的顺序。
  • 这里没有足够的信息来完全理解发生了什么。
  • qItem.Received 是否保证唯一?

标签: sql .net sql-server entity-framework tsql


【解决方案1】:

我找到了更新语句不起作用的原因似乎

另一个事务添加了第二条记录,该记录具有相同的 counterValue 并且没有更新,后来被删除。 所以只剩下“正确”的条目。

回想起来,一切似乎都那么清晰^^

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 2012-06-11
    • 2012-07-18
    • 2014-11-29
    • 1970-01-01
    相关资源
    最近更新 更多