2010-03-12 20 views
12

Tôi đang sử dụng SQL Server 2005, với một cơ sở dữ liệu nhạy cảm trường hợp ..LINQ to Entities: sử dụng ToLower() trên các lĩnh vực ntext

Trong một chức năng tìm kiếm, tôi cần phải tạo ra một LINQ to Entities (L2E) truy vấn với mệnh đề "where" so sánh nhiều chuỗi với dữ liệu trong cơ sở dữ liệu với các quy tắc sau:

  1. So sánh là chế độ "Chứa", không được phép so sánh chặt chẽ: dễ dàng như phương thức Chứa() của chuỗi L2E
  2. So sánh phải phân biệt chữ hoa chữ thường: Tôi sử dụng ToLower() trên cả hai phần tử để thực hiện so sánh không nhạy cảm.

Tất cả điều này thực hiện tốt nhưng tôi chạy vào ngoại lệ sau đây: "Loại dữ liệu đối số ntext không hợp lệ cho đối số 1 của hàm thấp hơn" trên một trong các trường của tôi.

Dường như trường đó là trường NText và tôi không thể thực hiện ToLower() trên đó.
Tôi có thể làm gì để có thể thực hiện một trường hợp không nhạy cảm Chứa() trên trường NText đó?

Trả lời

26

Không bao giờ sử dụng .ToLower() để thực hiện so sánh phân biệt dạng chữ. Đây là lý do:

  1. Có thể sai (collation khách hàng của bạn có thể là, nói, Thổ Nhĩ Kỳ và collation DB của bạn không).
  2. Đó là cao không hiệu quả; SQL được phát ra là LOWER thay vì = với collation phân biệt chữ hoa chữ thường.

Thay vào đó, sử dụng StringComparison.OrdinalIgnoreCase hoặc StringComparison.CurrentCultureIgnoreCase:

var q = from f in Context.Foos 
     where f.Bar.Equals("hi", StringComparison.OrdinalIgnoreCase) 
     select f; 

Nhưng đối với Contains() có một vấn đề: Không giống như Equals, StartsWith, vv, nó không có tình trạng quá tải cho một cuộc tranh luận StringComparison. Tại sao? Câu hỏi hay; hỏi Microsoft.

Điều đó, kết hợp với giới hạn của SQL Server trên LOWER có nghĩa là không có cách nào đơn giản để thực hiện những gì bạn muốn.

cách giải quyết có thể có thể bao gồm:

  • Sử dụng một chỉ mục văn bản đầy đủ, và thực hiện tìm kiếm trong một thủ tục.
  • Sử dụng Equals hoặc StartsWith thay vào đó, nếu có thể cho công việc của bạn
  • Thay đổi đối chiếu mặc định của cột?
+0

hum ... Tôi đoán bạn nói với tôi rằng việc sử dụng ToLower() là sai nhưng tôi không có giải pháp nào khác như: - Thay đổi collation là quá nhiều công việc & rủi ro chỉ cho một số tiêu chí tìm kiếm - Equals & StartsWith won không phù hợp với nhu cầu ở đây. Tôi đang suy nghĩ về việc chuyển đổi trường NText thành NVarchar và giới hạn đầu vào của người dùng ... Hiệu suất không thực sự quan trọng trong trường hợp của tôi. –

+0

Tôi chỉ đang cố gắng cho bạn biết các tùy chọn là gì, không khẳng định rằng một số tùy chọn lý tưởng cho bạn tồn tại .... –

5

Sử dụng biểu thức lambda tại đây và tạo danh sách trung gian có thể xử lý mệnh đề thấp hơn.

var q = Context.Foos.ToList().Where(s => s.Bar.ToLower().Contains("hi")); 

Không hiệu quả khủng khiếp, nhưng nó hoạt động.Nếu bạn có các vị từ bổ sung trong mệnh đề where của bạn thì nó hoạt động với lợi thế của bạn:

var q = Context.Foos.Where(p => p.f1 == "foo" && p.f2 == "bar"). 
      ToList().Where(s => s.Bar.ToLower().Contains("hi")); 
+1

Đây là LINQ to Entities: mục tiêu là tạo ra một yêu cầu SQL thích hợp. Giải pháp của bạn sẽ lấy tất cả các hàng của bảng (hoặc các hàng được lọc với các tiêu chí khác) và sau đó áp dụng bộ lọc. Thật vậy, điều này hoàn toàn không hiệu quả :). Nhưng tôi thừa nhận rằng nó sẽ hoạt động! –

+1

Tôi nghĩ rằng mục tiêu là một LINQ thích hợp cho các thực thể? Về hiệu quả ... Đôi khi khách hàng của bạn đang la hét để sửa lỗi chết tiệt và sếp của bạn đang khai thác ngón tay của họ cho bạn đôi mắt bốc mùi ... Hiệu suất và hiệu suất được đánh giá cao ngoại trừ trong trường hợp họ không. Chỉ vì một cái gì đó có thể được tối ưu hóa không có nghĩa là nó phải như vậy. –

+2

Đồng ý, tôi chỉ đề cập đến nó để những người mới sử dụng kỹ thuật này biết nó thực sự làm gì (tôi luôn ngạc nhiên khi thấy có bao nhiêu người sử dụng L2E mà không biết điều gì xảy ra bên dưới). Vì vậy, với các bảng lớn, nó có thể có tác động đáng kể/hiệu suất bộ nhớ. Trong trường hợp của tôi, hiệu suất không quan trọng. –

0

như chúng ta đã biết, đây là một tình huống rất "bị lỗi". và nó gây lỗi cho tôi rất nhiều.

Hôm nay, tôi quyết định để tạo ra một cái nhìn như:

select * from tableName nơi theColumn như '% key%'

sau đó tải quan điểm này vào EF.

cuộc sống trở nên dễ dàng!

Các vấn đề liên quan