Динамический запрос Linq к xml VB.NET - PullRequest
0 голосов
/ 16 марта 2011

Привет, я хочу написать запрос о том, что «где» в запросе - это строка типа «

Dim query as string =" Name = xxxx and Date> 10 "

Dim t = из книги в doc. Потомки ("книги") Выберите _ [Имя] = книга..значение, [Дата] = книга..значение .... Где (запрос)

Я строюстрока запроса во время выполнения

Спасибо ...

Ответы [ 2 ]

0 голосов
/ 16 марта 2011

Нет, нет ничего напрямую , как то, что вы ищете, где вы можете передать строку. Как говорится, когда все, что у вас есть, это молоток, все выглядит как гвоздь ... Реальная проблема в том, что вам нужно узнать, в чем хорош LINQ, и применить его к своему коду (если он подходит) чем пытаться заставить его делать то, что вы могли бы с помощью динамически построенной строки запроса SQL.

Что вы, вероятно, должны делать, так это делать так, чтобы предложения "Где" были строго напечатаны. Ваш текущий код может сильно взорваться и его будет сложно отладить.

Вместо этого вы могли бы сделать что-то вроде этого (извините, с помощью 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 ()». Поскольку он использует позднее выполнение, запрос является динамическим в том смысле, что он строится до тех пор, пока он фактически не должен быть запущен. Это похоже на код, который вы хотели использовать ранее, поскольку вы заранее строили строку запроса, а затем выполняли ее в определенной точке.

0 голосов
/ 16 марта 2011

Я не говорю, что это ваш случай, но я часто вижу это от людей, которые пришли из ASP classic, где мы все время строили динамические строки 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()

Если иногда вам нужно искать работу, а иногда, а иногда нет, вам, возможно, придется написать пару запросов:

    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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...