我使用CHECKSUM()
作为计算列,在nvarchar(MAX)
- 列上有一个索引表。 SQL查询可以使用带有文本值及其校验和的WHERE
- 子句来使用此索引。
linq-to-sql查询如何使用此索引?
我查看了sqlfunctions.checksum of linq object和How do I calculate a checksum on all columns in a row using LINQ and Entity Framework?及其答案,即SqlFunctions.Checksum("important")
,以获得单个值的校验和。
但SqlFunctions.Checksum("important")
抛出异常:
此功能只能从LINQ to Entities
调用
(此行为与Checksum(string)
)文档中记录的完全相同。
在sqlserver中,表格可以通过以下方式定义:
CREATE TABLE [Tags](
[TagId] [uniqueidentifier] NOT NULL PRIMARY KEY,
[Tag] [nvarchar](max) NOT NULL,
[TagHash] AS (checksum([Tag])) PERSISTED
)
和索引通过:
CREATE INDEX [IX_Tags] ON [Tags] (
[TagHash] ASC
)
以下SQL查询可能使用索引 1 :
SELECT * FROM [Tags]
WHERE [TagHash] = checksum('Important') AND
[Tag] = 'Important'
linqpad c#中的此查询表达式尝试会引发NotSupportedException
:
from tag in Tags
where SqlFunctions.Checksum("important") == tag.Hash &&
"important" == tag.Tag
select tag
如何在link-to-sql中构建上述查询而不使用link-to-entities这样的SqlFunctions.Checksum(string)
构造?
1) 这取决于查询优化器。
答案 0 :(得分:1)
如果您可以修改数据库并更改Linq2Sql模型,那么您可以通过创建自己的包装CheckSum的sql函数来完成此操作。例如
Create FUNCTION dbo.MyCheckSum (@input NVarChar(max)) RETURNS int
AS
BEGIN
Declare @output int
select @output = CheckSum(@input)
return @output
End
然后你就可以使用它了。
from tag in Tags
where MyChecksum("important") == tag.Hash && "important" == tag.Tag
select tag
如果您无法修改数据库或模型,则可以使用适用于您的示例的解决方法,但会牺牲另一个数据库命中,例如
int checkSum this dc.ExecuteQuery<int>("select Checksum('important')").Single();
from tag in Tags
where checkSum == tag.Hash && "important" == tag.Tag
select tag
答案 1 :(得分:0)
而不是围绕CHECKSUM
编写通用包装(作为sgmoore suggests)。
您可以编写一个访问器函数来通过校验和索引访问该表:
CREATE FUNCTION TagsByName(
@key nvarchar(max))
RETURNS TABLE
AS
RETURN SELECT
[TagId],
[Tag],
[TagHash]
FROM Tags
WHERE CHECKSUM(@key) = [TagHash] AND
@key = [Tag];
与sgmoore's solution相比,这样做的好处是所有link-to-sql - 和SQL查询都可以通过TVF访问该表,并且不使用索引和校验和。缺点是每个校验和索引构造都需要自己的TVF,而在sgmoore's solution中,单个TVF就足够了。