我如何防止 Linq 添加 GUID 以便 SQL 服务器可以做到这一点?
Posted
技术标签:
【中文标题】我如何防止 Linq 添加 GUID 以便 SQL 服务器可以做到这一点?【英文标题】:How do i prevent Linq from adding a GUID so that SQL server can do it? 【发布时间】:2012-04-02 06:29:24 【问题描述】:我正在以编程方式创建和填充 LINQ to SQL 对象,然后将它们添加到带有唯一标识符列的 sql 服务器数据库中以用于 PK。 LINQ 会自动分配一个全 0 的 PK。这会在插入时产生错误,因为 PK 是重复的。
Dim myNewRecord as IceCreamTrackerTable
myNewRecord.name=Bob
myNewRecord.favoriteIceCream=Vanilla
'myNewRecord.PK=00000000-0000-0000-0000-000000000000 (by default)'
myDataContext.IceCreamTrackerTables.insertOnSubmit(myNewRecord)
''second record added throws an error because it also has PK 00000 etc.
-
我知道我可以使用 myNewRecord.pk=Guid.newGuid() 分配 PK
Guid is all 0's (zeros)?
但我真正想要的是让 SQL Server 分配 GUID,因为我假设它有一些方法来确保它不会重新分配相同的 guid
有什么方法可以告诉 LINQ 我不想自己填写 GUID 而是让 SQL Server 来处理?
【问题讨论】:
【参考方案1】:Guid 是值类型,因此它们不能为空。这意味着当创建 Guid 时,它必须分配一个默认值(全为 0)。 SQL Server 不会像为标识列那样自动为主键生成 GUID。您可以将默认值设置为 NEWID(),但默认情况下 EF 会忽略它并尝试插入一个值。您可以通过执行此处描述的操作来覆盖它
http://softmindit.blogspot.com/p/using-guid-as-entitykey-in-entity.html
编辑:我刚刚意识到您使用的是 Linq to sql 而不是 Linq to entity。不过,我确信 L2S 中也有类似的东西可以处理这个问题。
Edit2:在 linq to sql 中也有类似的东西,如截图所示。更改此属性可解决问题
【讨论】:
【参考方案2】:您可以注释您的 GUID 列以表明它是使用 IsDbGenerated
生成的 DB:
[Column(Storage="_PK",
AutoSync=AutoSync.OnInsert,
DbType="UniqueIdentifier NOT NULL",
IsPrimaryKey=true, IsDbGenerated=true)]
public Guid PK
//...
【讨论】:
【参考方案3】:我假设它有一些方法可以确保它不是 重新分配相同的 guid
Guids 的全部意义在于它们是独一无二的……或者至少通常是独一无二的。如果它们都是从同一个来源分配的,例如在您的服务器上调用 Guid.NewGuid()
,那么您肯定不会遇到任何冲突。
【讨论】:
谢谢。我担心的是 SQL 服务器上的 GUID 和 Visual Studio 中的 GUID 没有“说话”。因此,有两个独立的 guid 制造商,每个都分配 guid。我宁愿只有一个实体负责制作向导。 Visual Studio 的 Guid 制作方法是否考虑了数据库中已经存在的 guid?这对我来说似乎不太可能。我错过了什么吗? 不,它不考虑它,但它没有必要。无论是谁生成,无论多快,无论是什么平台或软件,理论上都不可能得到重复的 GUID。 @akh2103 - 在特定机器上生成的任何 Guid 最终解析为调用相同的底层方法,无论是从 Visual Studio 应用程序、SQL Server 中的函数调用还是第三方应用程序调用.我不知道评估的细节,但我怀疑它是当前计时器和其中的 MAC 地址。同样,通常是独一无二的,但不能保证 100.00000% 如此。但是,如果它们都是从同一来源生成的,那么您就极不可能遇到冲突。 GUID 生成器不会验证您的表中不存在 GUID 值。它怎么知道它要去哪里? SQL 中的 GUID 生成器也不会进行此验证,并且可能会在操作系统中调用相同的生成器。简短的故事是:不要让您担心,两次生成相同 GUID 的机会非常小。【参考方案4】:这里的问题是,由于您的 PK 是一个值类型,它总是有一些值(没有 null
的等价物)。因此,除非生成的类包含特定的功能来跟踪您是否“手动”设置了值并在没有设置值的情况下省略它,否则没有办法做到这一点。
因此,查看IceCreamTrackerTable
的来源将提供明确的答案。
【讨论】:
啊!我从 LINQ to sql IceCreamTrackerTable 对象中删除了 PK,现在尝试提交时出现此错误:Can't perform Create, Update, or Delete operations on 'Table(IceCreamTrackerTable)' because it has no primary key.以上是关于我如何防止 Linq 添加 GUID 以便 SQL 服务器可以做到这一点?的主要内容,如果未能解决你的问题,请参考以下文章
与布尔值 false 进行比较时,如何防止 Linq2Sql 否定位列?
使用 LINQ to SQL 是不是有助于防止 SQL 注入