views:

65

answers:

2

I've got what I think is a working left outer join linq query but I'm having problems with the select because of null values in the right hand side of the join. Here is what I have so far

 Dim Os = From e In oExcel
        Group Join c In oClassIndexS On c.tClassCode Equals Mid(e.ClassCode, 1, 4)
        Into right1 = Group _
        From c In right1.DefaultIfEmpty

I want to return all of e and one column from c called tClassCode. I was wondering what the syntax would be. As you can see I'm using vb.net. Thanks.

Update.. Here is the query doing join where i get the error _message = "Object reference not set to an instance of an object."

 Dim Os = From e In oExcel
             Group Join c In oClassIndexS On c.tClassCode Equals Mid(e.ClassCode, 1, 4)
             Into right1 = Group _
             From c In right1.DefaultIfEmpty
        Select e, c.tClassCode

If i remove the c.tClassCode from the select the query runs without error. So i though perhaps i needed to do a select new but i don't think i was doing that correctly either.

+1  A: 

EDIT: you need to check c for null, specifically the c after your grouping. See my updates below.

You need to do a null check on tClassCode c in your select statement. What type is tClassCode? You should be able to do a null check on the value c and if it's null cast a nullable of the respective type and returned it, otherwise return the actual value.

Since I am not sure what tClassCode is let's assume it's an integer, in which case the cast would be to a nullable integer (Integer?). With that in mind your select statement, to be added at the end of what you have so far, should resemble:

Since tClassCode is a string your code would resemble:

Select _
    e, _
    Code = If(c Is Nothing, Nothing, c.tClassCode)

Depending on what you need to do if c is null you could return String.Empty instead of Nothing:

Select _
    e, _
    Code = If(c Is Nothing, String.Empty, c.tClassCode)

Of course you are free to further expand the selection of "e" to project its specific columns by name.

The important thing to realize is that you must check c for null before using any of its properties since it might be null depending on the left outer join result for a particular result (row). Back to my earlier example, if you had another field named Priority that was an integer you would cast against a nullable:

Select _
    e, _
    Priority = If(c Is Nothing, CType(Nothing, Integer?), c.Priority)
Ahmad Mageed
With that i'm getting an error of "Cannot infer a common type because more than one type is possible. The ClassCode is a string type so i changed it to string but it doesn't like that either. Says Type string must be a value type or a type argument constrained to 'Structure' in order to be used with nullable. if you have a second to explain further that would be great.
jvcoach23
@jvcoach a string type accepts a null value, therefore there is no nullable version of string (i.e., you can't use `String?`). That said, I'm not sure why you would be having a problem since a string type should accept a null value. Can you edit your question to show your original select query attempt for `e` and `c.tClassCode`? Also please copy/paste the error you get when you use the original code that is not working.
Ahmad Mageed
I modified the post, hopefully you can educate me.
jvcoach23
@jvcoach I've updated my reply. Please read over it carefully since I have updated the code samples and struck through my older response that doesn't entirely apply.
Ahmad Mageed
Thanks for the response.. I think i understand what you are saying. I've tried the Code=(c is nothing, nothing, c.tClassCode) but i'm still getting the object reference error. When the "Code" column is added in there that is when this happens. So i was wondering if there is something more that needs to be done with the select, like the "new with". just not sure
jvcoach23
@jvcoach to try the `new with` use this piece of code: `Select New With { .E = e, .Code = If(c Is Nothing, Nothing, c.tClassCode) }` - let me know if that solves it. It's on one line but you can break it up with the underscores if you want to. In C# I actually need to project it with `new`, but in my VB sample I didn't. I tried `new with` as above and it works for me. Let me know if that solves anything for you.
Ahmad Mageed
A: 

Well i got it working... at least i get results without errors. Thanks for the help.. here it is.

 Dim Os = From e In oExcel
                 Group Join c In oClassIndexS On c.tClassCode Equals Mid(e.ClassCode, 1, 4)
                 Into right1 = Group _
                 From jo In right1.DefaultIfEmpty()
        Select New With {.CivilServiceTitle = e.CivilServiceTitle, .Code = If(jo Is Nothing, Nothing, jo.tClassCode)}
jvcoach23