views:

305

answers:

2

How can I build in wildcards to my LINQ To SQL lambda expression?

This is what I have currently:

var query = from log in context.Logs select log;
foreach (string filter in CustomReport.ExtColsToFilter)
{
    string tempFilter = filter;
    query = query.Where(Log => Log.FormattedMessage.Contains(tempFilter));
}

This works fine up until I try and pass wildcards in the filter string. I'm experimenting with SqlMethods.Like() but to no avail.

The filters above look like this: "<key>NID</key><value>mcass</value>".

I'd like to be able to pass filters like this: "<key>NID</key><value>%m%</value>"

A: 

The wildcard is such as, m*, so anything with an m, for the wildcard you can ask if it .Contains(m); and it will get anything containing 'm'.

If you need wildcard in the sense of ALL the results from that table, just use

query.ToList(); 

You now have the entire list of Logs.

Hope that helps.

Gnostus
if you need to get multiple strings, you can use the ForEach statement, and check on each string and tack it on to a local list with each string."List<string> Rules = new List<string>();var Logs = new List<Log>();Rules.ForEach(rule => Logs.Add(query.Contains(rule)));"I believe that should work!
Gnostus
+5  A: 

String.Contains is actually implemented as a LIKE expression in LINQ to SQL, so these queries would be equivalent:

query = query.Where(Log => Log.FormattedMessage.Contains("m"));
query = query.Where(Log => SqlMethods.Like(Log.FormattedMessage, "%m%"));

However, with SqlMethods.Like, you can specify more complex patterns, such as "%m%a%". Works fine for me. You can't really see the difference from inside visual studio, because the expression to be matched against is put inside a parameter in the T-SQL.

If you were to log the SQL query in a profiler, it would look something like this:

exec sp_executesql N'SELECT [t0].[ID], [t0].[FormattedMessage]
FROM [dbo].[Log] AS [t0]
WHERE [t0].[FormattedMessage] LIKE @p0',N'@p0 nvarchar(5)',@p0=N'%m%a%'

Not relevant to the question per se, but String.StartsWith and String.EndsWidth also translate to a SQL LIKE, with slightly different patterns of course.

Thorarin
Thanks for your input. I'm beginning to think that my problem lies with the filters themselves. If you look at the bottom of my question, I give to strings that I am querying for. The first returns a record. The second, doesn't. If it helps, I'm querying a SQL column that contains xml similar to my filter examples.
mcass20
@mcass20: That's very odd. If the first filter returns a record, the second filter should definitely return at *least* one. If you have SQL Profiler, it might be of help to figure out what's going on.
Thorarin
If you don't have SQL Profiler, attaching `Console.Out` (or another TextWriter) to `context.Log` would also work, of course.
Thorarin
The SQL output looks as it should and I've narrowed it down to the string itself. "%m%" returns records, but "<key>NID</key><value>%m%</value>" does not. As you suggested, I also tried "%<key>NID</key><value>%m%</value>%"...no luck.
mcass20