1

我正在使用没有 rowversion 或时间戳的 Sql 表。但是,我需要使用 Linq 来更新表中的某些值。由于 Linq 无法知道要更新哪些值,因此我使用第二个 DataContext 从数据库中检索当前对象,并使用数据库和实际对象作为 Attach 方法的输入,如下所示:

Public Sub SaveCustomer(ByVal cust As Customer)
    Using dc As New AppDataContext()
        If (cust.Id > 0) Then
            Dim tempCust As Customer = Nothing

            Using dc2 As New AppDataContext()
                tempCust = dc2.Customers.Single(Function(c) c.Id = cust.Id)
            End Using

            dc.Customers.Attach(cust, tempCust)
        Else
            dc.Customers.InsertOnSubmit(cust)
        End If

        dc.SubmitChanges()
    End Using
End Sub

虽然这确实有效,但我有一个问题:我还在某些时候使用 StoredProcedures 来更新 Customer 的某些字段。现在想象以下工作流程:

  1. 从数据库中获取客户
  2. 将客户字段设置为新值
  3. 使用存储过程更新另一个客户字段
  4. 调用 SaveCustomer

现在发生的情况是,SaveCustomer 方法从数据库中检索当前对象,该对象不包含代码中设置的值,但包含存储过程设置的值。当将它与实际对象附加然后提交时,它将更新数据库中代码中设置的值,并且... tadaaaa... 将另一个设置为 NULL,因为实际对象不包含由存储过程。

这可以理解吗?

有没有解决这个问题的最佳实践?

4

2 回答 2

0

如果要将对象与一个上下文断开连接并使用另一个上下文进行更新,则需要保留原始对象,使用行版本,或在数据库中实现某种散列例程并将散列保留为一部分你的对象。其中,我强烈推荐 Rowversion 选项。像您尝试做的那样使用当前值作为原始值只是要求并发问题。

于 2009-07-31T00:05:41.323 回答
0

如果您在 ORM 背后进行更改,并且不使用并发检查 - 那么您将遇到问题。您没有显示您在步骤“3”中所做的事情,但 IMO 您应该更新对象模型以反映这些更改,也许使用OUTPUTTSQL 参数。或者; 坚持面向对象。

当然,在没有并发检查的情况下做任何事情都是丢失数据的好方法——所以我更喜欢的选择是简单地“添加一个rowversion”。否则,您也许可以读取更新的对象并合并内容...以某种方式猜测正确的数据是什么...

于 2009-07-13T09:38:50.290 回答