如何绕过 NHibernate 版本控制更新 SQL 中的记录

Posted

技术标签:

【中文标题】如何绕过 NHibernate 版本控制更新 SQL 中的记录【英文标题】:How to update a record in SQL bypassing NHibernate version control 【发布时间】:2017-08-12 18:40:52 【问题描述】:

假设我有一个带有timestamp 列的表,该列通过NHibernate 用于管理记录版本,现在我正在寻找一种方法来更新我的数据记录不增加 ts 列的值,因为如您所知,该值会在每次更新语句后增加以跟踪数据版本以避免并发问题。

CREATE TABLE [dbo].[TSTest]( 
    [ID] [int] NOT NULL, 
    [Name] [nvarchar](50) NULL, 
    [ts] [timestamp] NOT NULL, 
    CONSTRAINT [PK_TSTest] PRIMARY KEY CLUSTERED ( [ID] ASC )
        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY]

有什么想法吗?

【问题讨论】:

不,你不能。 我认为这是可能的,在软件中没有什么是不可能的! 感谢您编辑@Serg 【参考方案1】:

如果有某些列不应受到timestamp 跟踪,那么您可以将这些列移动到一个新表中,然后再引用该原始表。

如果需要,您可以通过生成一个名为 TSTest 的视图将这些表连接在一起(连同将插入、更新和删除应用到适当的基表)。

但是,在这种情况下,我们不清楚我们应该做什么,因为只有一个明显的“可更新”列 - Name - 所以如果我们不希望它受到 timestamp 跟踪,我们不清楚为什么我们有根本就在这张桌子上。

不幸的是,没有其他 T-SQL 机制可以避免timestamps 的行为——这通常被视为一件好事。您无法通过触发器执行任何操作,因为如果您实际触摸基表,timestamp 将被更改,并且您不允许UPDATE 时间戳列,因此您甚至无法在更改后重置它。

我认为这是可能的,软件中没有什么是不可能的

撇开诸如停止问题之类的存在,您当然是正确的,这个问题可以解决 - 但不是以可能对您有用的方式。正如我上面所说,通过 T-SQL 是不可能的。

如果您真的需要这样做,那么您可以通过直接操作数据库文件来完成。当然,这需要您分离数据库或关闭服务器,然后仔细检查文件结构以手动定位包含您希望更改的行的页面,然后应用这些更改,然后更正结构的其他部分(例如页面校验和),以便 SQL Server 不会认为页面现在已损坏。

我并不是真的提倡这种方法,只是概述了要真正执行您所要求的事情,您必须离正常多远。

【讨论】:

我喜欢你的回答,因为你对解决这个问题的广泛意见,仅供参考,这个表模式只是为了测试我的原始表是另一个表,顺便说一下,我对你第二个感兴趣建议我使用 View 的解决方案,我认为这适合我的情况,谢谢我的朋友 :)【参考方案2】:

有什么想法吗?

根据您的评论和架构您的ts[ts] [timestamp] NOT NULL。所以它会在每次更新操作时被修改。

一种方法是使用AFTER UPDATE 触发器并撤消发生的修改。但你为什么要这样做?此外,mysql 不支持在同一个表(或)递归触发器上触发。

【讨论】:

创建表 [dbo].[TSTest]( [ID] [int] NOT NULL, [Name] [nvarchar](50) NULL, [ts] [timestamp] NOT NULL, CONSTRAINT [PK_TSTest ] PRIMARY KEY CLUSTERED ([ID] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] 不,这是一个timestamp(又名rowversion)列,不是一个日期时间。所以提到current_timestampand triggers 是一个红鲱鱼。 @MohammadNikravesh - 当人们询问架构时(通常作为评论,而不是在答案中),通常最好编辑您的问题,以便您可以标记块作为代码 () 使其可读,这与 cmets 不同。 (当然,理想情况下,我们不必询问架构,它从一开始就在您的问题中) 哦,是的,你是对的,谢谢你的好建议,我会这样做:)

以上是关于如何绕过 NHibernate 版本控制更新 SQL 中的记录的主要内容,如果未能解决你的问题,请参考以下文章

如何更新 Nhibernate 中的 varchar 列长度?

如何使用 NHibernate 模式生成更新数据库表模式?

NHibernate之并发控制简记

如何使用 nhibernate 更新主键

如何在nHibernate中运行更新HQL查询?

如何使用 Fluent nhibernate 正确更新行?