在我的 SQL 表 (2008) 中,我有一个名为 Timestamp 的时间戳列。
在我的 .Net 项目中,我有一个带有属性的 POCO 类
public byte[] Timestamp {get; set;}
在我的配置代码中,我有以下内容:
Property(p => p.Timestamp).IsRowVersion();
现在,如果我打开两个编辑屏幕,对其中一个进行更改并保存(接受保存),然后在第二个中进行更改并保存(DbUpdateConcurrencyException 拒绝保存)。
我觉得奇怪的一件事是,即使我收到并发异常,SQL Profiler 也会显示正在发送到 SQL 数据库的更新请求。更新未在数据库上提交,但已发送。这正常吗?我有点希望 EF 提前检查,甚至不发送请求。
最后,如果我在此表上启用触发器:
ALTER TRIGGER [dbo].[trg_person_log_changes]
ON [dbo].[Person]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @auditBody XML
DECLARE @actionType char(1)
DECLARE @username nvarchar(100)
if not exists(select * from deleted)
Begin
SET @actionType = 'I'
SET @username = (select Case
When lastchangedby is null or lastchangedby = '' then Suser_name()
Else lastchangedby
End
from inserted)
End
else if not exists(select * from inserted)
Begin
SET @actionType = 'D'
SET @username = Suser_name()
End
else
Begin
SET @actionType = 'U'
SET @username = (select distinct Case
When lastchangedby is null or lastchangedby = '' then Suser_name()
Else lastchangedby
End
from inserted)
End
If @actionType = 'I'
Set @auditBody = (select 'Person' as "@tableName", 'True' as "@synch",
(select * from inserted for xml path('DataItem'), type, binary base64)
for xml path('Root'))
Else
SET @auditBody = (select 'Person' as "@tableName", 'True' as "@synch",
(select * from deleted for xml path('DataItem'), type, binary base64)
for xml path('Root'))
insert into [dbo].[AuditLog]
([Action]
,[ActionDate]
,[ActionUser]
,[AuditData]
)
values (
@actionType
,getdate()
,@username
,@auditBody)
END
现在,当我尝试保存第二次编辑时,我不再收到 DbUpdateConcurrencyException,我收到一条错误消息,指出 ActionUser 不能为空。再一次,我认为我的触发器正在执行,因为即使存在冲突,EF 也允许更新通过。
关于我可能做错了什么的任何想法?
笔记
这是一个 MVC 项目。在我的 Edit POST 控制器中,我收到了一个包含所有表单属性的 DTO 对象(其中之一是 Timestamp - 我的编辑表单上的一个隐藏字段)。我正在从 datacontext 加载已编辑的人员,并将已编辑的属性从 DTO 对象映射到从 datacontext 返回的 Domain 对象。