Why is IEnumerable<object> not null after LINQ query? - c#

I have a List which holds > 10.000 items. I am doing a LINQ query on this
IEnumerable<Term> terms = from t in regionCollection
where t.Name == strRegion
select t;
if (terms != null)
{
m.RegId = Convert.ToInt32(terms.FirstOrDefault().CustomProperties["dbId"]);
}
If (terms !=null) is always not null! I have a feeling that the query is executed only if i try to access the single object inside the IEnumarable. Is this correct and if yes how can i check if my IEnumarable is not null?

Variable term will always have a value, it will never be null, because if query returns no results then terms will be empty enumerable. In your case you can update the code like this:
// Get first item of query or default value
var firstTerm = terms.FirstOrDefault();
// If there were no items, then firstTerm is null
if (firstTerm != null)
{
// This code block is only executed if the query had at least 1 item in results
m.RegId = Convert.ToInt32(firstTerm.CustomProperties["dbId"]);
}

Related

Cosmos DB read call

I'm making a call to Azure Cosmos DB where I know the data I'm querying does NOT exist.
I was expecting to get a null value but instead I'm getting:
Enumeration yielded no results
How do I test whether I received a value or not? I was testing for null which doesn't work because the outcome is not null.
My code looks something like this:
var result = await _client.ReadQuery<myObject>(AccountsCollection, sql, pa);
if(result == null)
return null;
Instead of just checking on result == null you should use the LINQ extension method .Any() to see if there are any items that match a condition (in your case the condition is just anything existing in the collection):
if(result == null || !result.Any())
{
return null;
}

Object reference not set to an instance while not being null

I'm getting some unexpected behavior in my process. I'm doing the following.
IEnumerable<Thing> things = ...;
IEnumerable<Thing> subset = things.Where(a => a.SomeFlag);
String info = "null: " + (subset == null);
The above works and info tells me that the object isn't null. So I wish to check the number of the elements in subset by this.
IEnumerable<Thing> things = ...;
IEnumerable<Thing> subset = things.Where(a => a.SomeFlag);
String info = "null: " + (subset == null);
String count = subset.Count();
Now I get an exception giving me the error message:
Object reference not set to an instance of an object.
What do I miss?!
It's possible that one of the Thing's in subset is null. You can try this:
IEnumerable<Thing> subset = things.Where(a => a != null && a.SomeFlag);
Note that due to the way Linq's lazy evaluation, you won't get any exception you call .Where because all it's doing at that point is setting up a condition for filtering the elements of things. Only later when you call .Count is it actually evaluating the results.
Update: With the new null-condition operator in C# 6 (also called the safe navigation or 'Elvis' operator), we can do the same thing a bit more succinctly:
IEnumerable<Thing> subset = things.Where(a => a?.SomeFlag);
An IEnumerable<Thing> implies deferred execution.
In your first fragment subset and things are never enumerated.
In the second fragment, it is the call to Count() that enumerates the lists and only then it comes to light that one of the a is null in a => a.SomeFlag.
You can see what really happens here with a bit simplified example.
Test class:
public class Test
{
public int Value { get; set; }
}
And LINQ query on IEnumerable<Test>:
IEnumerable<Test> source = new List<Test>() {
new Test { Value = 10 },
null,
new Test { Value = 20 }
};
IEnumerable<Test> filteredSource = source.Where(x => x.Value > 10);
// return false
Console.WriteLine(filteredSource == null);
// throws NullReferenceException
Console.WriteLine(filteredSource.Count());
Why does it happens? Because filteredSource == null does not cause collection enumeration, so Where predicate is not being fired on any source collection element.
However, when you call Count() on filteredSource the predicate is being called on every item from source collection, and when it comes to an item which is null: null.Value > 10 throws the exception.
How to make it work? Extend the predicate with x != null check:
IEnumerable<Test> filteredSource = source.Where(x => x != null && x.Value > 10);
Ok, so suppose you had the following items in things:
Thing A SomeFlag = true
Thing B SomeFlag = false
null
Thing C SomeFlag = true
First you count all the items in things. So you iterate over 4 objects, find 4 objects, and know that the result is 4. Easy.
Now you want to count all of the items in subset which means you need to figure out which items are in subset in the first place. So you go about counting them:
Thing A .... A.SomeFlag is true, so count it
Thing B .... B.SomeFlag is not true, so don't count it
null .... null.SomeFlag NULLREFERENCEEXCEPTION
And that's where your error comes from.
Note that even if all of the elements in things are not null, you can still get a NullReferenceException if the .SomeFlag get accessor has a side effect that could cause a NullReferenceException.

why null values not return in when apply != in linq

I use this code
var items2 = from item in context.Images
where item.Reported != true
select item;
But not return null values in "Reported" column why?
true or false is not the same value as null. If you need both to be returned then you will want to change your query to this:
var items2 = from item in context.Images
where item.Reported != true || item.Reported == null
select item;
Entity Framework, when translating your query to SQL, generates code similar to
select * from images
where reported <> true
Any operator in SQL used on null value returns false (null <> true too), thats why you do not get images with reported null values in your result set.
You could try using Object.Equals for the effect you expect, like so:
var items2 = from item in context.Images
where !Equals(item.Reported, true)
select item;
It should work like you've described, returning false and and null entries.

linq where clause causes exception

var nextItem = ql.Fragments.Where(x => x.AddedToFinal.Equals(false));
x.AddedToFinal is bool and ql.Fragments is not null
this linq statement sporadically get this exception:
System.NullReferenceException: Object reference not set to an instance
of an object.
at System.Linq.Enumerable.WhereListIterator1.MoveNext() at
System.Linq.Enumerable.Count[TSource](IEnumerable1 source)
There is a question already that should have answered this( linq where clause and count result in null exception) but this is impossible since the field is a not null Boolean, and this isn't a database object it is a list
Just added:
The code where I populate the list is multi-threaded. different fragments add items to the list after they have retrieved the items from the db:
.....
xe = XElement.Parse(result);
XmlFragment xf = new XmlFragment();
xf.Fragment = xe;
xf.LetterQueueOID = lq.LetterQueueOID;
xf.ParentGroupNodeName = ParentGroupNodeName;
xf.LinkingField = GroupNode.LinkingField;
xf.GroupNodeName = GroupNode.GroupNodeName;
lock (queuedLetters[lqOID])
{
if (lq.Fragments == null)
lq.Fragments = new List<XmlFragment>();
lq.Fragments.Add(xf);
}
ql.Fragments itself isn't null, but one of the elements in the enumeration is null. I'm guessing that is a problem in and of itself, but you could modify the statement to be:
var nextItem = ql.Fragments.Where(x => x != null &&
x.AddedToFinal.Equals(false));
Although that doesn't solve the problem of why one of the elements in the collection was null to begin with.
x.AddedToFinal is bool and ql.Fragments is not null this linq statement sporadically get this exception:
Then one of the elements of ql.Fragments is null so that
x.AddedToFinal
is throwing a NullReferenceException for some value of x in ql.Fragments. You could say
var nextItem = ql.Fragments
.Where(x => x != null)
.Where(x => !x.AddedToFinal);
but you should probably find out why there are null elements in your collection.
I would check if x is null
var nextItem = ql.Fragments.Where(x => x != null && x.AddedToFinal.Equals(false));
Are you sure all rows have a value for AddedToFinal ?!!
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Linq.Enumerable.WhereListIterator1.MoveNext() at System.Linq.Enumerable.Count[TSource](IEnumerable1 source)
As you can see in exception Iterator can't move or read next row.
Be sure all rows have a value for this field.

Null check ObservableCollection before querying it

Is this code good enough:
if (MyCollection.Where(p => p.SomeID == idstring).Any())
{
selectedval = MyCollection.Where(p => p.SomeID == idstring).FirstOrDefault().MyField;
}
My doubt is about the fact that I make the same query twice: first for null check and then to actually get data.
Maybe there is a better way to do this type of things?
Yes.
var item = MyCollection.FirstOrDefault(p => p.SomeID == idstring);
if (item != null)
selectval = item.MyField;
This avoids double querying the collection, which will certainly make a difference in big collections or if your collection performs a DB query.
There is. You can use the FirstOrDefault method which takes a predicate and returns null if the item is not found.
var result = MyCollection.FirstOrDefault(p => p.SomeID == idstring);
if( result != null )
{
// item was found
}

Categories

Resources