簡體   English   中英

在LINQ to Entities中使用System.String Concat生成CAST而不是CONCAT

[英]Using `System.String Concat` in `LINQ to Entities` generates `CAST`s instead of `CONCAT`

文檔中可以理解,當使用string.Concat查詢技術(例如LINQ to Entities)中的string.Concat時,應將此規范函數轉換為所使用的提供程序的正確對應存儲函數,這意味着Concat適用於MsSQLT-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
顯然我做錯了什么,但是呢? 問題在於,將CASTNVARCHAR(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM