2011-03-16 3 views
0

이봐, 를 XML로 그 "여기서"쿼리에서> 이름 = XXXX 및 날짜 "문자열 =으로동적 쿼리 Linq에 내가 쿼리를 작성하려는 VB.NET

희미한 쿼리"와 같은 문자열 무언가가있다 10 "

희미한 t = doc.Descendants 책에서 ("책 ")을 선택 _ [이름] = book..value, [날짜] = book..value .... 경우 (쿼리)

런타임에 쿼리 문자열을 만듭니다.

감사합니다.

+0

왜 거기에서 일하는 것이 효과가 없습니까? 예외를 던지거나 예상 한 결과를 얻지 못하거나 무엇을 얻고 있습니까? – Manatherin

+0

Where()가 부울 만 가져올 수 있다는 예외가 발생합니다. – Beno

답변

0

저는 이것이 당신의 경우라고 말하지는 않지만 항상 동적 SQL 문자열을 구축하는 데 사용 된 ASP 클래식에서 온 사람들로부터 많이 봅니다. 우리는 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 

그리고 단지 (난 당신이 가서하지 DO 추천 경로 인) 자신의 쿼리 파서를 작성 설명 : metimes 당신은 쿼리의 몇 가지를 작성해야 할 수 없습니다 아주, 아주, 아주 거친 시작이다. =과 문자열 만 지원하며 여러 지점에서 중단 될 수 있습니다.

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() 
0

아니, 직접 당신이 문자열에 전달할 수있는 무엇을 찾고 있는지처럼 아무것도 없다. 그들이 말했듯이, 당신이 갖고있는 모든 것이 망치 일 때, 모든 것이 못처럼 보입니다 ... 진짜 문제는 LINQ가 무엇인지를 배우고 코드에 적용하는 것입니다 (적합하다면). 시도한 것보다 동적으로 작성된 SQL 쿼리 문자열로 할 수있는 일을하도록하십시오.

어쨌든 "Where"절을 강력하게 입력하도록해야합니다. 현재 코드는 폭파되어 디버그하기가 쉽지 않습니다. 대신 무엇을 할 수 있는지

이 같은 (죄송합니다, C#을 사용하는 동안 내가 VB.NET 감동했습니다 된 이후)입니다 : LINQ와

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(); 

, "쿼리는"실제로 실행되지 않습니다 "ToList()"호출까지.늦은 실행을 사용하기 때문에 쿼리는 실제로 실행해야 할 때까지 빌드되고 있다는 점에서 동적입니다. 이는 미리 쿼리 문자열을 작성한 후 특정 지점에서 실행 한 이후에 사용하던 코드와 유사합니다.