【发布时间】:2019-07-30 16:23:38
【问题描述】:
正如我从docs 中了解到的那样,当人们从查询技术(例如 LINQ to Entities)中使用string.Concat 时,这个规范函数应该被转换为正在使用的提供程序的正确对应存储函数,这意味着@ 987654325@ 为MsSQL 的T-SQL。但是当我运行以下测试代码时:
var items = (from item in testDB.Items
where list.Contains(string.Concat(item.Id,":"))
select new
{
Hit = string.Concat(item.Id,":"),
Item = item
}).ToList();
正在生成以下 SQL:
SELECT
[Extent1].[Id] AS [Id],
CAST( [Extent1].[Id] AS nvarchar(max)) + N':' AS [C1],
FROM [testDB].[Items] AS [Extent1]
WHERE (CAST([Extent1].[Id] AS nvarchar(max)) + N':' -- N.B.
IN (N'1:', N'2:', N'3:')) AND (CAST([Extent1].[Id] AS nvarchar(max)) + N':' IS NOT NULL)
注意:+(加号运算符)使用CAST 而不是Concat。
显然我做错了什么,但是什么?问题是CAST 到NVARCHAR(MAX) 需要花费大量时间,尤其是在连接多个字段时。
好像做不到,因为Concat使用sql_variant类型,不是SQLProviderManifest定义的,不支持重载所以只能映射一个函数签名(模式中的名称应该是唯一的) ,所以很明显,他们只是通过在需要时使用加号运算符与强制转换连接来进行短路,即使我在代码优先中映射了Concat,生成的SQL 仍在使用它,所以它变得很明显。我认为唯一的方法是使用DbSet.SqlQuery。
【问题讨论】:
-
Id的数据库和 C# 类型是什么? -
通过从包含之前的列表项中删除“:”来反转您的 where 子句,它应该更优化。
-
@VidmantasBlazevicius 用作分隔符的分号,为简洁起见,此示例进行了简化,长版本连接多个字段并在列表中查找匹配项。
-
@NetMage 数据库是 MsSQL 2016,
Id列是int -
因此,要与
int进行字符串连接,LINQ 将强制转换为字符串。您可以尝试使用SqlFunctions.StringConvert手动强制一个。
标签: c# entity-framework linq entity-framework-6 linq-to-entities