2009-06-24 44 views
29

Tôi muốn biết liệu có thể thực hiện tìm kiếm ký tự đại diện bằng LINQ hay không.Tìm kiếm theo ký tự đại diện cho LINQ

tôi thấy LINQ đã Contains StartsWith, EndsWith vv

gì nếu tôi muốn một cái gì đó như% Kiểm tra xem nó hoạt động%%, làm thế nào để làm điều đó?

Kính trọng

Trả lời

28

Tôi sẽ sử dụng Cụm từ thông dụng vì bạn không phải lúc nào cũng sử dụng LINQ to SQL.

Giống như ví dụ này của LINQ to Objects

List<string> list = new List<string>(); 
list.Add("This is a sentence."); 
list.Add("This is another one."); 
list.Add("C# is fun."); 
list.Add("Linq is also fun."); 

System.Text.RegularExpressions.Regex regEx = new System.Text.RegularExpressions.Regex("This"); 

var qry = list 
    .Where<string>(item => regEx.IsMatch(item)) 
    .ToList<string>(); 

// Print results 
foreach (var item in qry) 
{ 
    Console.WriteLine(item); 
} 
+6

Bit dài quanh co - ông chỉ có thể sử dụng SqlMethods.Like –

+1

Bạn luôn luôn giả định rằng bạn đang gọi một cơ sở dữ liệu SQL. Điều gì xảy ra nếu bạn truy vấn danh sách được tạo trong bộ nhớ? –

+9

Câu hỏi của ông được gắn thẻ với SQL –

69

Bạn có thể sử dụng SqlMethods.Like().

Một ví dụ về việc sử dụng:

var results = 
     from u in users 
     where SqlMethods.Like(u.FirstName, "%John%") 
     select u; 
+2

rất mát mẻ! không biết rằng tồn tại ... – bytebender

+11

Điều này sẽ chỉ làm việc với các truy vấn LINqToSql (như phải được rõ ràng bởi các lớp được sử dụng). –

+0

Rất đẹp, tôi không biết rằng đã tồn tại hoặc +1 –

2
.Where(column LIKE "Pattern") 
+3

Tốt cho VB, nhưng không phải là C#. – Noldorin

0

Bạn đang nói LINQ to đối tượng hoặc LINQ to SQL?

Đối với LINQ đối tượng bạn sẽ phải sử dụng đến regular expressions tôi nghĩ.

1

không chắc chắn nếu bạn nói chuyện LinqToSql hoặc chỉ LINQ ... nhưng bạn có thể biểu thức thông thường như thế này:

.Where(dto => System.Text.RegularExpressions.Regex.IsMatch(dto.CustomerName, @"Ad")); 
12

thêm System.Data.Linq.SqlClient việc sử dụng của bạn hoặc danh sách nhập khẩu sau đó thử:

var results= from x in data 
      where SqlMethods.Like(x.SearchField, “%something%like%this%”) 
      select x; 
3
var result = (from x in db.Members 
       where x.IDNumber.Contains(idnumber) 
       && x.InstitutionIdentifier == institution.Identifier 
       select x).ToList(); 
return result; 

Sẽ làm việc cho cả LINQ to SQL và LINQ trong bộ nhớ.

2

Bạn cũng có thể sử dụng "chứa"

var myresult = db.MyItems.Where(x=>x.MyField.Contains(mysearchstring)); 
2

Tôi biết đây là và chủ đề cũ, nhưng ở đây là giải pháp rất đơn giản của tôi:

string s=Regex.Escape("pattern - escaped for sanity").Replace("%", ".*").Replace("_", ".?"); 
user => Regex.IsMatch(user.FullName, s, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase); 

Trong mã này, tôi đang sử dụng các ký tự thoát chung cho ngôn ngữ SQL. Nếu bạn muốn sử dụng nói *?, thoát chuỗi sẽ chứa \*\? tương ứng, hãy chắc chắn để bao gồm các xuyệc ngược nhân vật trong .Replace(...) statement (s). Tất nhiên, nếu bạn muốn cung cấp cho người dùng khả năng tìm kiếm RexEx, chỉ cần không thoát khỏi chuỗi mẫu.

Tìm kiếm hướng dẫn Regex cho các tùy chọn khác.

Tôi tin thường % sẽ phù hợp ít nhất một nhân vật, trong khi RegEx .* sẽ phù hợp zero hoặc nhiều ký tự. Vì vậy, trên thực tế, ký tự đại diện % giống như .+ (tham lam) thay vì .* (lười).

Hy vọng điều này sẽ hữu ích.

2

Nhìn vào câu hỏi

gì nếu tôi muốn một cái gì đó như% Kiểm tra xem nó hoạt động%%, làm thế nào để làm điều đó?

sau đó tôi đang mong đợi một cái gì đó của

LIKE '%Test if%it work%' 

nghĩa là chuỗi phải chứa 'Kiểm tra xem' và 'nó hoạt động', theo thứ tự mà.

này sẽ không làm việc:

context.SomeTable.Where(s => s.Name.Contains("Test if%it work")).ToList(); 

Và nếu tôi sử dụng:

context.SomeTable.Where(s => s.Name.Contains("Test if") && s.Name.Contains("it work")).ToList(); 

sau đó tôi sẽ tìm thấy tất cả hồ sơ có chứa cả hai "Kiểm tra xem" và "nó hoạt động", nhưng không cụ thể theo thứ tự đó.

Vì vậy, với Chứa điều này là không thể. Nhưng với IndexOf.

IndexOf sẽ tìm chuỗi tìm kiếm VÀ trả về vị trí của chuỗi đó trong chuỗi. Làm cho nó có thể tìm thấy những từ theo đúng thứ tự.

- Cập nhật -

Với câu trả lời ban đầu của tôi đó không phải là mục tiêu của tôi để cung cấp một giải pháp chung chung, mà là một ví dụ về cách tiếp cận khác mà không phải là sql dependend. Vì vậy, chính xác là ví dụ ban đầu chỉ trả lời câu hỏi theo nghĩa đen. Nhưng kể từ khi câu trả lời có thể hữu ích hơn nếu nó là chung chung, tôi đã viết một phần mở rộng IQuerable cho phép thêm một tuyên bố giống như truy vấn dễ dàng như là một tuyên bố nơi. Phần mở rộng hoạt động cho cả Linq như Linq-Sql.

Thao tác này sẽ tìm tất cả các bản ghi có cả "Kiểm tra nếu" và "nó hoạt động", theo thứ tự đó.

context.SomeTable.Like("test if%it work", "Name").ToList(); 

listOfString.Like("test if%it work").ToList(); 

mở rộng, cho phép bất kỳ số lượng các kí hiệu:

/// <summary> 
/// Allow to search the string with wildcards. 
/// </summary> 
/// <typeparam name="T">String or an object with a string member.</typeparam> 
/// <param name="q">Original query</param> 
/// <param name="searchstring">The searchstring</param> 
/// <param name="memberName">The name of the field or null if not a field.</param> 
/// <returns>Query filtered by 'LIKE'.</returns> 
public static IQueryable<T> Like<T>(this IQueryable<T> q, string searchstring, string memberName = null) 
{ 
    // %a%b%c% --> IndexOf(a) > -1 && IndexOf(b) > IndexOf(a) && IndexOf(c) > IndexOf(b) 

    var eParam = Expression.Parameter(typeof(T), "e"); 

    MethodInfo methodInfo; 

    // Linq (C#) is case sensitive, but sql isn't. Use StringComparison ignorecase for Linq. 
    // Sql however doesn't know StringComparison, so try to determine the provider. 
    var isLinq = (q.Provider.GetType().IsGenericType && q.Provider.GetType().GetGenericTypeDefinition() == typeof(EnumerableQuery<>)); 
    if (isLinq) 
     methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) }); 
    else 
     methodInfo = typeof(string).GetMethod("IndexOf", new[] { typeof(string) }); 

    Expression expr; 
    if (string.IsNullOrEmpty(memberName)) 
     expr = eParam; 
    else 
     expr = Expression.Property(eParam, memberName); 

    // Split the searchstring by the wildcard symbol: 
    var likeParts = searchstring.Split(new char[] { '%' }, StringSplitOptions.RemoveEmptyEntries); 

    for (int i = 0; i < likeParts.Length; i++) 
    { 
     MethodCallExpression e; 
     if (isLinq) 
      e = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) }); 
     else 
      e = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i], typeof(string))); 

     if (i == 0) 
     { 
      // e.IndexOf("likePart") > -1 
      q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(e, Expression.Constant(-1, typeof(int))), eParam)); 
     } 
     else 
     { 
      // e.IndexOf("likePart_previous") 
      MethodCallExpression ePrevious; 
      if (isLinq) 
       ePrevious = Expression.Call(expr, methodInfo, new Expression[] { Expression.Constant(likeParts[i - 1], typeof(string)), Expression.Constant(StringComparison.OrdinalIgnoreCase) }); 
      else 
       ePrevious = Expression.Call(expr, methodInfo, Expression.Constant(likeParts[i - 1], typeof(string))); 

      // e.IndexOf("likePart_previous") < e.IndexOf("likePart") 
      q = q.Where(Expression.Lambda<Func<T, bool>>(Expression.LessThan(ePrevious, e), eParam)); 
     } 
    } 
    return q; 
} 

Kể từ khi nó không cần SqlMethods Tôi giả sử bạn có thể sử dụng này cho bất kỳ cơ sở dữ liệu, như MySQL hoặc PostgreSQL. Nhưng tôi không biết chắc chắn. Tôi đã kiểm tra điều này với Sql Server bằng Entity Framework 6. Câu lệnh trên tạo ra đoạn mã sau trong Sql Server.

SELECT [Extent1].* FROM SomeTable AS [Extent1] 
WHERE (((CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) > -1) 
AND (((CAST(CHARINDEX(N'test if', [Extent1].[Name]) AS int)) - 1) < 
    ((CAST(CHARINDEX(N'it work', [Extent1].[Name]) AS int)) - 1)) 

Giới thiệu về hiệu suất, có vẻ như có một số cuộc thảo luận về 'tốt hơn': LIKE hoặc CHARINDEX.Và từ những gì tôi đã đọc, CHARINDEX dường như được yêu thích.

+0

Câu trả lời của bạn không chứa câu trả lời cho câu hỏi chung về cách thực hiện tìm kiếm ký tự đại diện trong LINQ, nó chỉ trả lời ví dụ cụ thể và sẽ không hoạt động cho bất kỳ trường hợp nào khác. Như vậy, nó không cung cấp một câu trả lời hữu ích cho câu hỏi. – Frosty840

+0

@ Frosty840 Tôi đã cập nhật câu trả lời. –

+0

Thực ra tôi đang tìm kiếm một câu trả lời cụ thể cho SQL, vì nó làm phiền tôi phải viết thêm mã chung mà tôi sẽ không bao giờ cần vì chúng ta sẽ luôn sử dụng SQL Server. Thật không may trong khi bạn cho thấy lý do tại sao có chứa sẽ không làm việc bạn đã không hiển thị bất cứ điều gì đơn giản như vậy sẽ. Việc so sánh tôi đang cố gắng thực hiện là một trong một chuỗi chứa. Vì vậy, tôi đã hy vọng cho một cái gì đó đơn giản để thêm vào chuỗi đó. Có vẻ như SQLMethods.Like sẽ phải được sử dụng. – user1161391

0

Đối Entity Framework Core 2.0LIKE điều hành (announced in August 2017):

var query = from e in _context.Employees 
        where EF.Functions.Like(e.Title, "%developer%") 
        select e; 
Các vấn đề liên quan