首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Entity Framework 全角半角查詢不一致陷阱:LINQ to Entities vs 記憶體 LINQ 的隱性差異

     編輯:關於.NET

SQL Server 查詢不區分大小寫,LINQ to Entities 同樣不區分;但記憶體中 LINQ 則嚴格區分。更隱蔽的是:SQL Server 甚至不區分全角半角,而記憶體 LINQ 區分,導致同一邏輯在資料庫層通過、記憶體層失效,引發主鍵衝突異常。

實戰場景還原

標籤服務 CNBlogsTagService:

  1. LINQ to Entities 查庫:tagNames = {"C++"}(全角),資料庫存 "c++"(半角),匹配成功,回傳既有實體。
  2. 記憶體 LINQ 判斷新增:existedTags.Select(y=>y.TagName).Contains(x, ...) 區分全半角,認為 "C++" 不存在,嘗試新增。
  3. SaveChanges 爆主鍵衝突:資料庫拒絕重複鍵 "C++"(視同 "c++")。
// LINQ to Entities - 不區分全半角
var existedTags = _unitOfWork.Set<Tag>()
    .Where(x => tagNames.Contains(x.TagName)).ToList();

// 記憶體 LINQ - 區分全半角
var createdTags = tagNames.Where(x => existedTags.Select(y => y.TagName)
    .Contains(x, StringComparer.InvariantCultureIgnoreCase) == false)
    .Select(x => new Tag { TagName = x }).ToList();

解決方案:VB.NET StrConv 統一轉半角

  1. 專案加入參考 Microsoft.VisualBasic
  2. 查詢前雙向轉半角:Strings.StrConv(x, VbStrConv.Narrow)
var createdTags = tagNames.Where(x => existedTags.Select(y => Strings.StrConv(y.TagName, VbStrConv.Narrow))
    .Contains(Strings.StrConv(x, VbStrConv.Narrow), StringComparer.InvariantCultureIgnoreCase) == false)
    .Select(x => new Tag { TagName = x }).ToList();

加入 VB 參考

核心啟示

  • LINQ to Entities ≠ 記憶體 LINQ,語義不完全對等
  • 資料庫 Collation 影響比較語義,跨層查詢必須統一正規化
  • 全角半角、大小寫、簡繁體等「視覺相同、編碼不同」字元,是跨層查詢的隱形殺手

以 VbStrConv.Narrow 統一正規化,為最低成本、最高相容性的解法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved