嘿, 我想编写一个查询的“凡”在查询是一个字符串像“动态查询LINQ到xml的VB.NET
昏暗查询的String =” NAME = XXXX和日期> 10 “
昏暗的T =从书doc.Descendants(” 书“)选择_ [名] = book..value,[日期] = book..value .... 凡(查询)
我在运行时构建查询字符串
谢谢..
嘿, 我想编写一个查询的“凡”在查询是一个字符串像“动态查询LINQ到xml的VB.NET
昏暗查询的String =” NAME = XXXX和日期> 10 “
昏暗的T =从书doc.Descendants(” 书“)选择_ [名] = book..value,[日期] = book..value .... 凡(查询)
我在运行时构建查询字符串
谢谢..
我并不是说这是你的情况,但我从ASP经典的人那里看到了很多,我们经常用它来构建动态SQL字符串。我们倾向于希望LINQ在部分代码中给我们更多的权力,但让我们在其他地方使用字符串。不幸的是,这不是事实。 Where
需要一个布尔参数,并且没有办法。你可以编写自己的使用反射的解析器,并最终返回一个布尔值,但是你会写很多可能容易出错的代码。下面是你真的应该这样做:
假设这是我们的数据类:
Public Class TestObject
Public Property Name As String
Public Property Job As String
End Class
下面是我们的测试数据:
Dim Objects As New List(Of TestObject)
Objects.Add(New TestObject() With {.Name = "A", .Job = "Baker"})
Objects.Add(New TestObject() With {.Name = "B", .Job = "President"})
Objects.Add(New TestObject() With {.Name = "C", .Job = "Bus Driver"})
Objects.Add(New TestObject() With {.Name = "D", .Job = "Trainer"})
你想要做什么是创建一个代表一个变量要搜索的数据:
''//This variable simulates our choice. Normally we would be parsing the querystring, form data, XML values, etc
Dim RandNum = New Random().Next(0, 3)
Dim LookForName As String = Nothing
Select Case RandNum
Case 0 : LookForName = "A"
Case 1 : LookForName = "B"
Case 2 : LookForName = "C"
End Select
''//Query based on our name
Dim Subset = (From O In Objects Select O Where (O.Name = LookForName)).ToList()
如果有时您需要在Job上进行搜索,有时甚至是metimes你没有你就可能需要编写几个查询:
Dim Subset As List(Of TestObject)
Select Case RandNum
Case 0
Subset = (From O In Objects Select O Where (O.Name = "A" And O.Job = "Baker")).ToList()
Case Else
Select Case RandNum
Case 1 : LookForName = "B"
Case 2 : LookForName = "C"
End Select
Subset = (From O In Objects Select O Where (O.Name = LookForName)).ToList()
End Select
而只是为了解释编写自己的查询分析器(这是我建议你切勿往下走的路径),在这里是一个非常非常非常粗糙的开始。它仅支持=
并且仅支持字符串,并且可以在多个点中断。
Public Shared Function QueryParser(ByVal obj As Object, ByVal ParamArray queries() As String) As Boolean
''//Sanity check
If obj Is Nothing Then Throw New ArgumentNullException("obj")
If (queries Is Nothing) OrElse (queries.Count = 0) Then Throw New ArgumentNullException("queries")
''//Array of property/value
Dim NameValue() As String
''//Loop through each query
For Each Q In queries
''//Remove whitespace around equals sign
Q = System.Text.RegularExpressions.Regex.Replace(Q, "\s+=\s+", "=")
''//Break the query into two parts.
''//NOTE: this only supports the equal sign right now
NameValue = Q.Split("="c)
''//NOTE: if either part of the query also contains an equal sign then this exception will be thrown
If NameValue.Length <> 2 Then Throw New ArgumentException("Queries must be in the format X=Y")
''//Grab the property by name
Dim P = obj.GetType().GetProperty(NameValue(0))
''//Make sure it exists
If P Is Nothing Then Throw New ApplicationException(String.Format("Cannot find property {0}", NameValue(0)))
''//We only support strings right now
If Not P.PropertyType Is GetType(String) Then Throw New ApplicationException("Only string property types are support")
''//Get the value of the property for the supplied object
Dim V = P.GetValue(obj, Nothing)
''//Assumming null never equals null return false for a null value
If V Is Nothing Then Return False
''//Compare the two strings, return false if something doesn't match.
''//You could use String.Compare here, too, but this will use the current Option Compare rules
If V.ToString() <> NameValue(1) Then Return False
Next
''//The above didn't fail so return true
Return True
End Function
此代码将允许你写:
Dim Subset = (From O In Objects Select O Where (QueryParser(O, "Name = A", "Job = Baker"))).ToList()
没有,没有什么直接像你要找的内容,您可以在传递一个字符串。正如他们所说的,当你拥有的只是一把锤子时,一切都看起来像一个钉子......真正的问题是你需要学习LINQ擅长的东西并将它应用于你的代码(如果它很合适),而不是比尝试使用动态构建的SQL查询字符串做得更好。
你应该做的是让那些“Where”子句强制类型化。你目前的代码有很大的潜力可以炸毁并且很难调试。
你可以做什么,而不是是这样的(对不起,使用C#,已经有一段时间,因为我已经感动VB.NET):
var query = from book in doc.Descendants("books")
select book;
if(needsNameComparison)
{
query = query.where(book.Name == nameToCompare);
}
if(needsDateComparison)
{
query = query.Where(book.Date > 10);
}
List<book> bookList = query.ToList();
使用LINQ,“查询”是不是真正运行直到“ToList()”调用。由于它使用后期执行,所以查询是动态的,因为它正在建立,直到它实际需要运行。这与您在提前构建查询字符串之前希望使用的代码类似,然后在特定点执行它。
为什么不在你那里做什么工作?它是抛出一个异常,没有得到你期望的结果或什么? – Manatherin 2011-03-16 09:46:02
它引发异常,Where()可以得到布尔值 – Beno 2011-03-16 11:52:46