views:

183

answers:

1

How do I get Linq to ignore any parameters that are empty? So Lastname, Firstname, etc? If I have data in all parameters it works fine...

refinedresult = From x In theresult _
                    Where x.<thelastname>.Value.TestPhoneElement(LastName) And _
                    x.<thefirstname>.Value.TestPhoneElement(FirstName) And _
                    x.<id>.Value.TestPhoneElement(Id) And _
                    x.<number>.Value.TestPhoneElement(Telephone) And _
                    x.<location>.Value.TestPhoneElement(Location) And _
                    x.<building>.Value.TestPhoneElement(building) And _
                    x.<department>.Value.TestPhoneElement(Department) _
                    Select x


Public Function TestPhoneElement(ByVal parent As String, ByVal value2compare As String) As Boolean
'find out if a value is null, if not then compare the passed value to see if it starts with
Dim ret As Boolean = False

If String.IsNullOrEmpty(parent) Then
    Return False
End If
If String.IsNullOrEmpty(value2compare) Then
    Return ret
Else
    ret = parent.ToLower.StartsWith(value2compare.ToLower.Trim)
End If

Return ret
End Function
+1  A: 

Just to make sure I understand what you want: You want an IEnumerable of XElements x returned where at least one of the child elements' values matching the corresponding string variable. So by ignore you mean that your extension method would return false. So I deduce that if it's not working fine, then an empty parameter causes true to (mistakenly) be returned by TestPhoneElement, and hence you get false positives. Meaning, if a parameter is an emptystring or nothing, it always returns true, and hence you are getting items in your result that you shouldn't be getting.

My thinking is this:

  1. Only ret = parent.ToLower.StartsWith(value2compare.ToLower.Trim) could possibly return true.
  2. value2compare.ToLower.Trim() would certainly cause the problem you indicate.
  3. String.IsNullOrEmpty(value2compare) has to be returning false.

I believe that the second parameter that you're passing into TestPhoneElement must in fact be a string containing at least one space. This way, String.IsNullOrEmpty(value2compare) returns false. Then in the final line value2compare.ToLower.Trim evaluates to an empty string because you trimmed it, and ret = parent.ToLower.StartsWith(value2compare.ToLower.Trim) evaluates to true because every string begins with an empty string.

So, trim value2compare when it first comes in, or change you 2nd conditional to:

If String.IsNullOrEmpty(value2compare.trim()) Then

and you should be good.

Edit:

solution based on clarified situation

You want an empty string passed into the extension method to result in True then, right? Also, I updated the extension method to allow for slightly cleaner code. The key though is that you want any blank string passed in to result in True being returned:

refinedresult = From x In theresult _
            Where x.<thelastname>.MatchesOrIsBlank(LastName) And _
                x.<thefirstname>.MatchesOrIsBlank(FirstName) And _
                x.<id>.MatchesOrIsBlank(Id) And _
                x.<number>.MatchesOrIsBlank(Telephone) And _
                x.<location>.MatchesOrIsBlank(Location) And _
                x.<building>.MatchesOrIsBlank(Building) And _
                x.<department>.MatchesOrIsBlank(Department) _
            Select x

And:

Public Function TestPhoneElement(ByVal xE As XElement, ByVal value2compare As String) As Boolean
    Return xE.Value.ToLower.StartsWith(value2compare.ToLower.Trim)
End Function
Patrick Karcher
I will try it thank you for answering. +1 for such a nice detailed attempt, I'll report back if it works. Thanks again.
Cj Anderson
Ok, I made a mistake in my code. I really want to "AND" each parameter. I had the ORs on there from when I was fooling around trying to get it to work. So in the end I don't get any results currently. (I updated the question) The only time I get results is if all the parameters have something. So yes it has something to do with an empty string being in any of the parameters.
Cj Anderson
So, do you want *TestPhoneElement* to return True or False in the case where the *value2compare* parameter is an empty string (or nothing)?
Patrick Karcher
We'll perhaps I can answer that by explaining what I was trying to accomplish with my code in general. The extension method might not even be needed. I want to pass the query search parameters, but allow for some not to be passed. So department might not get passed to the query. Right now the code above works if and only if all parameters are passed. So frankly I thought my code would work as is, it is failing because of the empty strings for parameters. Does that explain it well?
Cj Anderson
Thank you for the update. I implemented what you suggested. I am getting a compiler error. It says the extension method isn't a member of System.Collections.Generic.Ienumerable(Of System.XMl.Linq.Xelement)
Cj Anderson
Ok. Here is what I did... IT WORKS, because of you! ;-) I just passed .value from the Xelement and my extension method bolts onto the string class. Works like a charm. One problem I did have is if there was an empty xelement it would give me a null reference exception. So I have if not xe is nothing then ... return xe.startswith(value2compare.trim, stringcomparison.ordinalignorecase). That did it. Think my approach to your solution is sound?
Cj Anderson
absolutely. Using `x.Element("number").MatchesOrIsBlank(Telephone)` would have worked for passing in the XElement (my mistake: `.<number>` is the equivalent to .Elements(), not .Element()) Passing the value (rather than the xElement itself) is the way to go if the xElement might be missing anyway. As long as it's working! LINQ to XML is good stuff, and worth working with to get good at.
Patrick Karcher