Dynamic LINQ Query
July 8, 2008
I’ve been thinking for a couple days now how to create a dynamic LINQ query. There is a prety good sample in C# here: http://blog.bvsoftware.com/post/2008/02/How-to-create-a-Dynamic-LINQ-Query-Programmatically.aspx
I went a little further with this. One because I’m writing in vb.net so I had to convert this anyway, and two, because I’m passing my search through a webservice. I didn’t want to have to create a variable for every possible search criteria, but at the same time I wanted flexibility.
The slimmed down function in my webservice is as follows:
Public Function LidDataSet(ByVal Search As DataTable, ByVal bFullText As Boolean) As DataSet
Dim matches As IQueryable(Of Persons) = From p In dbA.Persons Select p
For i As Integer = 0 To Search.Rows().Count - 1
Dim field As String = Search.Rows(i).Item("Field").ToString()
Dim value As String = Search.Rows(i).Item("Value").ToString()
If bFullText Then
If field = "Name" Then _
matches = matches.Where(Function(p As Persons) p.Name.Contains(value))
If field = "Email" Then _
matches = matches.Where(Function(p As Persons) p.Email.Contains(value))
Else
If field = "Name" Then
If InStr(value, "%") Then
If value.IndexOf("%") > 0 Then
matches = matches.Where(Function(p As Persons) p.Name.StartsWith(value.Substring(0, value.IndexOf("%"))))
Else
matches = matches.Where(Function(p As Persons) p.Name.EndsWith(value.Substring(value.IndexOf("%") + 1, value.Length() - 1)))
End If
Else
matches = matches.Where(Function(p As Persons) p.Name = value)
End If
End If
If field = "RegEmail" Then
If InStr(value, "%") Then
If value.IndexOf("%") > 0 Then
matches = matches.Where(Function(p As Persons) p.Email.StartsWith(value.Substring(0, value.IndexOf("%"))))
Else
matches = matches.Where(Function(p As Persons) p.Email.EndsWith(value.Substring(value.IndexOf("%") + 1, value.Length() - 1)))
End If
Else
matches = matches.Where(Function(p As Persons) p.Email = value)
End If
End If
Next
Dim linqQuery = From li In matches Select li
Return dwTools.ConvertLinqToDataSet(linqQuery)
End Function
For more information on the ConvertLinqToDataSet(linqQuery) function see my previous post: http://helpmonkey.wordpress.com/2008/06/30/pass-back-a-da…inq-webservicepass-back-a-dataset-from-a-linq-webservice/
I think the code should do a better job explaining this than I can put into words, but basically you have to pass in a datatable of the fields and values you want to search. Since I couldn’t figure out how to build a string to use in my linq query i put an if statement to decide what field to search. The limitations of this are pretty obvious, but it suits my needs.
One major limit of this approach that I feel that I should mention is that this is only building an “AND query.” That’s probably not the technical term, but what I mean is that if you search for more than one term, you are searching with the AND term. So if you search for field: Name, value: “john” and field:Email, value: “john%” you will be building a query that will return matches on Name = “john” AND Email.startswith(“john%”).
April 1, 2009 at 3:53 pm
Josh,
I noticed this method:
dwTools.ConvertLinqToDataSet(linqQuery)
What is this? And where can I get a copy of it?
April 1, 2009 at 5:21 pm
http://helpmonkey.wordpress.com/2008/06/30/pass-back-a-dataset-from-a-linq-webservice/
April 1, 2009 at 5:37 pm
The other problem that I see is that you can’t use associated entities with this query either.
If you were searching Persons you couldn’t ever get their Department name like this:
Persons.Department.Name
You could only get Persons.DepartmentID and then you’d have to go an make a seperate lookup for the Department info.