使用带有 Linq to Sql 的 Sql Server 唯一标识符/更新日期列 - 最佳方法

Posted

技术标签:

【中文标题】使用带有 Linq to Sql 的 Sql Server 唯一标识符/更新日期列 - 最佳方法【英文标题】:Using SqlServer uniqueidentifier/updated date columns with Linq to Sql - Best Approach 【发布时间】:2010-10-29 19:54:41 【问题描述】:

无论对错,我使用唯一标识符作为我的 sqlserver 数据库中表的主键。我已经使用 linq to sql (c#) 生成了一个模型,但是在 identity 列的情况下,linq to sql 在为 guid /uniqueidentifier 插入新记录时生成唯一键 @987654324 的默​​认值@。

我知道我可以在我的代码中设置 guid:在 linq to sql 模型或其他地方,或者在创建 sql server 表时有默认值(尽管这被代码中生成的值覆盖)。但是最好在哪里生成这个密钥,注意我的表总是会随着我的解决方案的发展而改变,因此当它发生时我将重新生成我的 Linq to Sql 模型。

相同的解决方案是否适用于保存当前datetime(插入)的列,每次更新都会更新?

【问题讨论】:

【参考方案1】:

正如您在自己的帖子中所述,您可以使用可扩展性方法。添加到您的帖子中,您可以查看在数据上下文中创建的用于插入和更新每个表的部分方法。一个名为“test”的表和一个“changeDate”列的示例:

partial void InsertTest(Test instance)

    instance.idCol = System.Guid.NewGuid();
    this.ExecuteDynamicInsert(instance);


partial void UpdateTest(Test instance)

    instance.changeDate = DateTime.Now;
    this.ExecuteDynamicUpdate(instance);

【讨论】:

谢谢 Stephan,我认为这可能是我的首选方法,UpdateTest(...) 看起来不错,但是在 OnCreated 上使用 InsertTest 的一个问题是对象生命周期中可能发生的关系到其他相关对象。我可以使用尚未生成 guid 的默认 0 创建指向其他对象的链接吗? AFAIK 如果您的相关对象作为实体集附加到您的父对象,则相关对象的外键在插入后更新。但是,我发现在 OnCreate 方法中设置 guid 没有任何问题。我使用插入方法是因为我需要设置一个唯一的连续编号(例如发票编号),该编号取自数据库中的编号池。对于唯一键,我使用标识列。 谢谢,我已经尝试过了,它似乎工作正常。我曾使用原始的 OnCreated() 方法,但现在已更改为这种方法。 只是为了跟进此事。这种方法不适用于 Guid,因为在调用 insert 方法之前添加了一个集合重复的 0s 键,因此会引发异常。我有另一种方法,我想我将用于 guid:sqlserver 默认值为 newid(),然后在 linqtosql 中将自动生成的值属性设置为 true。这必须在每一代模型上完成,但这相当简单。【参考方案2】:

谢谢,我已经尝试过了,它似乎工作正常。 我有另一种方法,我想我将用于 guid:sqlserver 默认值为 newid(),然后在 linqtosql 中将自动生成的值属性设置为 true。这必须在每一代模型上完成,但这相当简单。

【讨论】:

【参考方案3】:

你可以做两件事:

要么在 C# 客户端代码中生成 GUID 并使用该值 在 SQL Server 中的 GUID 列上创建默认约束,该列默认为 newid() - SQL Server 将确保始终添加默认值 - 除非您自己指定值

至于自更新日期/时间列 - 在这里您可能必须使用客户端逻辑来执行此操作,或者如果您想在 SQL Server 上执行此操作,则必须编写一个触发器。这确实是每次更新行时更新特定列的唯一方法 - 没有“自动更新”约束或类似的东西(默认约束仅适用于 INSERT,而不适用于更新)。

这样的事情可能会奏效:

CREATE TRIGGER TRG_UpdateDateTimestamp
ON (your table name)
AFTER UPDATE 
AS
    IF NOT UPDATE(DateTimeStamp)
    BEGIN
       UPDATE (yourtablename) 
       SET DateTimeStamp = GETDATE()
       WHERE EXISTS (SELECT * FROM inserted AS i 
                     WHERE i.OID = (yourtable).OID)
   END

马克

【讨论】:

感谢 Marc,默认 linq to sql 生成代码的问题在于它生成 0s guid,因此 sqlserver 创建的默认值被覆盖(我相信我已经找到了解决方案 -我自己添加了一个答案)。虽然触发器看起来很有用,但我会试一试,但我觉得我需要一个更通用的解决方案来避免为每个表编写此代码。也许我应该有一个包含 tname、id 和 datetime 列的通用更新表,在每个表上都有一个触发器来运行通用存储过程以将新记录插入到该表中?这可行吗? 由于某种原因我的答案没有出现,可以在这里找到答案:codecadet.strongerforyou.com/post/…

以上是关于使用带有 Linq to Sql 的 Sql Server 唯一标识符/更新日期列 - 最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

如何在带有 LINQ to SQL 的存储过程中使用临时表

使用DISTINCT时,LINQ to SQL不生成ORDER BY?

使用 SQL Server Compact Edition 的 Linq-to-SQL

带有存储过程的实体框架 VS LINQ to SQL VS ADO.NET? [关闭]

LinQ to SQL用法详解

LINQ to SQL class LINQ to sql Objects?