LINQ to SQL 插入连续的 GUID

7
我有一个数据库,它是合并复制方案的一部分,具有GUID作为其PK。具体来说,数据类型是uniqueidentifier,默认值为(newsequentialid()),RowGUID设置为Yes。当我执行InsertOnSubmit(CaseNote)时,我认为我可以让CaseNoteID保持不变,数据库会像在MSSMS中手动输入新行一样输入下一个Sequential GUID。但实际上它发送了00000000-0000-0000-0000-000000000000。如果我添加CaseNoteID = Guid.NewGuid(),那么我得到的是一个GUID,但不是顺序的(我非常确定)。是否有一种方法可以让SQL在LINQ InsertOnSubmit()上创建下一个顺序id?

以下是我用于将新记录插入数据库的代码。

            CaseNote caseNote = new CaseNote
                                {
                                    CaseNoteID = Guid.NewGuid(),
                                    TimeSpentUnits = Convert.ToDecimal(tbxTimeSpentUnits.Text),
                                    IsCaseLog = chkIsCaseLog.Checked,
                                    ContactDate = Convert.ToDateTime(datContactDate.Text),
                                    ContactDetails = memContactDetails.Text
                                };
        caseNotesDB.CaseNotes.InsertOnSubmit(caseNote);

        caseNotesDB.SubmitChanges();

根据以下建议之一,我启用了该列的LINQ自动生成功能,现在出现以下错误-> 如果语句包含不带INTO子句的OUTPUT子句,则DML语句的目标表不能有任何已启用的触发器。 有什么想法吗?
7个回答

5
在Linq to Sql设计器中,将该列的“自动生成值”属性设置为true。
这相当于对于某一列的IsDbGenerated property。唯一的限制是您无法使用Linq更新该值。

我尝试了这个,现在出现以下错误 -> 如果语句包含没有INTO子句的OUTPUT子句,则DML语句的目标表不能有任何启用的触发器。 - Refracted Paladin
对我来说,这已经设置好了,但是数据库仍然尝试分配默认的0个guid而不是生成一个。 - DCShannon

5

从右侧的“相关”框顶部开始:

Linq-to-Sql中的连续GUID?

如果您真的想要“下一个”值,请使用int64而不是GUID。 COMB GUID将确保GUID按顺序排序。


2
如果您需要排序,请使用数字类型。Guids 的设计目的是作为唯一标识符,而不提供任何排序方法。 - Adam Robinson
翻译:true,但在两种情况下可能会导致大量的操作:聚集索引和复制性能(看起来像是 OP 的问题)。COMB 可以解决这个问题,但不一定使它们成为序列。 - Michael Meadows
@Michael - 感谢您指出这一点。当我创建标题时,它没有出现在“建议”中,这很奇怪。 - Refracted Paladin
节省了我寻找多年前最初发现COMB GUID文章的时间。 - Michael Meadows

1

你真的需要做几件事情。

  1. 删除任何GUID类型属性的赋值
  2. 将列更改为自动生成
  3. 在数据库中创建一个约束,将列默认为NEWSEQUENTIALID()
  4. 像以前一样在提交时进行插入。

在表格插入时,ID将被创建并且是连续的。 NEWSEQUENTIALID()与其他方法的性能比较


@C Tierney:这与已接受的解决方案有何不同?听起来是一样的东西,只是拼写出来而已,对吗? - Refracted Paladin

1
关于您的问题"The target table of the DML statement cannot have any enabled triggers if the statement contains an OUTPUT clause without INTO clause",请查看此MS KB文章,似乎是LINQ中的一个错误:

http://support.microsoft.com/kb/961073


0

0

Masstransit 使用一个 combguid:

https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit/NewId/NewId.cs

这是你要找的吗?

来自维基百科:

顺序算法

GUID通常用作数据库表的主键,因此该属性往往具有聚集索引。这会在插入记录时导致性能问题,因为完全随机的GUID意味着记录可能需要插入表中的任何位置,而不仅仅是附加到其末尾。为了减轻这个问题,同时仍然提供足够的随机性以有效地防止重复编号碰撞,已经使用了几种算法来生成连续的GUID。第一种技术由Jimmy Nilsson于2002年8月描述,并称为“COMB”(“组合guid /时间戳”),它将Data4的最后6个字节替换为当前系统日期/时间的最低有效6个字节。虽然这可能导致在同一秒钟的不同时间点内生成的GUID是无序的,但他的测试表明,这对于插入没有太多现实世界的影响。这种方法的一个副作用是,如果需要,可以轻松地从值中提取插入日期和时间。从Microsoft SQL Server 2005版本开始,Microsoft添加了一个名为NEWSEQUENTIALID()的Transact-SQL语言函数,用于生成保证增加值的GUID,但在服务器重新启动时可能从较低的数字(仍然保证唯一)开始。这减少了可以进行插入的数据库表页面数量,但不能保证值始终会增加。此函数返回的值可以轻松预测,因此该算法不适合生成用于安全或哈希目的的模糊数字。2006年,一位程序员发现Oracle提供的SYS_GUID函数在某些平台上返回连续的GUID,但这似乎是一个错误而不是一个功能。


0

你必须处理 OnCreated() 方法

Partial Class CaseNote
    Sub OnCreated()
        id = Guid.NewGuid()
    End Sub
End Class

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接