tags:

views:

119

answers:

4

My Question is how do I handle a null set returned from a linq query if I am loading it into a custom class.

example

queryResults = queryResults.Select(p => new specialItems(p.ID, p.SECTION, p.PROGRAM, p.EVENT).ToList<specialItems>();

...

public class specialItems
{
    public string Id { get; set; }
    public string Section { get; set; }
    public string Program { get; set; }
    public string Event { get; set; }

    public courseItems(string id, string section, string program, string event)
    {
        this.Id = id;
        this.Section = section; 
        this.Program = program;
        this.Event = event;
    }
}

Currently this query works great until the result set is empty, then I get: "Object reference not set to an instance of an object."

I need the query to return an empty List if the result set is empty.

UPDATE - Asided from the invalid redeclaration of a variable (fixed) I did find that the issue was higher up in the initial construction of the linq query. This became apparent when I received several good suggestions and removed the error. Once I fixed the original query things worked swimmingly.

+2  A: 

Use the null coalescing operator (??).

List<specialItems> queryResults = queryResults.Select(p => new specialItems(p.ID, p.SECTION, p.PROGRAM, p.EVENT).ToList<specialItems>() ?? new List<specialItems>();

EDIT: Yeah, looking at what you have there a little closer, it's the ToList that's blowing up when this happens. You might have to split it up a bit.

var temp = queryResults.Select(p => new specialItems(p.ID, p.SECTION, p.PROGRAM, p.EVENT);

List<specialItems> results = temp == null ? new List<specialItems>() : temp.ToList<SpecialItems>();

Have to do it this way, because there's no good spot to put the null coalescing operator in this case.

Robaticus
I am still getting the error.
LeRoy
Added another approach.
Robaticus
Both of these options actually yielded results. I realized after your second suggestion failed that maybe I had problem higher up the chain and sure enough I had a bad property being inserted into my query. Thanks for your help.
LeRoy
+3  A: 

Robaticus is mostly right, use the null coalescing operator (??). Howerver, since you didn't include the stack trace, I assume your code is throwing because queryResults is initially null. By the time you get to the ?? operator, you've already thrown the exception, because you tried to dereference queryResults.

Also, the code you have doesn't make a ton of sense, because queryResults is already defined within that scope by the time you get to that line. You can't redefine a variable that has already been declared locally in that scope.

List<SpecialItems> queryResults = GetSomeResults();
queryResults = (queryResults ?? new List<SpecialItems>())
    .Select(p => new SpecialItems(p.ID, p.SECTION, p.PROGRAM, p.EVENT))
    .ToList<SpecialItems>();

If you can get the function or line that spits out the original version of queryResults to return an empty list instead of null, then try to do that, or coalesce the results on that line. That's probably better than having all that code on the query line :)

List<SpecialItems> queryResults = GetSomeResults() ?? new List<SpecialItems>();
queryResults = queryResults
    .Select(p => new SpecialItems(p.ID, p.SECTION, p.PROGRAM, p.EVENT))
    .ToList<SpecialItems>();
Merlyn Morgan-Graham
I realized after the fact that it was the embedded ToList<string>() that was probably throwing the exception.
Robaticus
@Robaticus - I would say he should add a stack trace, but it would still just mention the line. To debug this, he should really split up the code into a new line/statement on every ".". Then the stack trace would point to exactly which operation caused the error.
Merlyn Morgan-Graham
Sorry about the redefinition. That is what I get for trimming down code for submission. You were absolutely right I had an issue higher up in the code. Thank you for your suggestion on debug.
LeRoy
+3  A: 

Linq returns an empty list if there are no results, never null. Therefore, the problem is certainly not that queryResults.Select() returns null.

What is probably going on is that we're looking at a lazily evaluated linq-to-objects 'query'. ToList() triggers the evaluation of it, and probably the nullreference exception occurs in a lambda expression higher up the chain.

jeroenh
+1, It must be as you say.
David B
+1  A: 

Neither Enumerable.Select, nor Queryable.Select, nor Enumerable.ToList return null.

The query is not realized until ToList enumerates it. During that enumeration, a null reference exception is occuring due to code you have not posted in the question.

Consider this code with and without the commented line:

List<int> source = Enumerable.Range(1, 10).ToList();
IEnumerable<int> query = null;
try
{
  query = source.Where(i => 1 / i > 0);
}
catch(Exception ex)
{
  Console.WriteLine("Exception was caught {0}", ex.Message);
}
// source.Add(0);
List<int> result = query.ToList();

Consider this code with and without the commented line:

DataContext myDC = new DataContext();
string name = null;
IQueryable<Person> query = myDC.Persons.Where(p => p.Name.StartsWith(name));
// name = "Zz";
List<Person> result = query.ToList();
David B