![](/img/trans.png)
[英]LINQ to Entities does not recognize the method 'System.String Concat(System.Object)' method,
[英]Using `System.String Concat` in `LINQ to Entities` generates `CAST`s instead of `CONCAT`
從文檔中可以理解,當使用string.Concat
查詢技術(例如LINQ to Entities)中的string.Concat
時,應將此規范函數轉換為所使用的提供程序的正確對應存儲函數,這意味着Concat
適用於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
定義的),因此看起來似乎無法完成,因此不支持重載,因此只能映射一個函數簽名(架構中的名稱應該是唯一的),因此顯然它們只是做了一個簡短的說明,通過在需要時使用plus運算符與強制類型轉換連接電路,即使我以代碼優先方式映射Concat
時,生成的SQL
仍在使用它,因此顯而易見。 我認為唯一的方法是利用DbSet.SqlQuery
。
可以使用item.Id +“:”我經常使用
我認為您可以一起從SQL中刪除串聯。 似乎您有一個包含數字后跟冒號的字符串列表。 為什么不從數字中刪除冒號並直接進行數字比較呢?
var list2 = list.Select(i => int.Parse(i.Replace(':','')));
var items = (from item in testDB.Items
where list2.Contains(item.Id,":"))
.AsEnumerable() // switch from DB query to memory query
.Select(item => new
{
Hit = string.Concat(item.Id,":"),
Item = item
}).ToList();
因此,為了使工作正常,我們將不使用LINQ
,而是使用DbSet.SqlQuery
:
var contains = list.Aggregate(new System.Text.StringBuilder(),
(sb, s) => sb.Append($"N'{s}', "),
sb => (sb.Length > 0)
? sb.ToString(0, sb.Length - 2)
: null);
if (contains == null)
{
//ToDo: list is empty, we've got a problem
}
else
{
var query = testDB.Items.SqlQuery($@"SELECT [E1].[Id],..
FROM [testDB].[Items] AS [E1]
WHERE CONCAT_WS(':', [E1].[Id],..) IN ({contains })");
}
當然,應該使用SqlParameter
完成,但這是解決方法的一般思路。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.