Checking for nulls in distinct - c#

I have tried a bunch of different ways to do this but every time I try this it throws a null reference exception.
I am trying to filter the values in a field to have a list of the unique values inside that field. It works on fields with no missing values but when i use it on fields that i know to have null values it throws an exception so im assuming that is what i should be filtering for.
The original way i was doing this was just looping through the values and checking if the list of unique values contained the value yet but this was taking a long time and i wanted to harness the power of Linq
List<Graphic> ReturnedGraphics = e.FeatureSet.Features as List<Graphic>;
IEnumerable<string> ValueSet = (
from g in e.FeatureSet.Features
where !uniquevalues.Contains((g.Attributes[_selectedField] == null ? "blank" : g.Attributes[_selectedField].ToString()))
select g.Attributes[_selectedField] == null ? "blank" : g.Attributes[_selectedField].ToString()
) as IEnumerable<string>;
if (ValueSet.Any())
{
uniquevalues.AddRange(ValueSet);
}
I should also add that the reason im adding a range to the list is because there are 5000 values coming in from the server which has a limiter on values to return, however it works for this and shouldn't have an effect on what im trying to do here.

You can't .ToString() null values. Looks like you might be trying to. Candidates for null include lstbxFields.SelectedValue, g.Attributes[someVal]
How about rationalizing your code so that the errors are easier to trap and you're not repeating yourself all over the place?
var selVal = lstbxFields.SelectedValue;
if(selVal == null)
{
//act on this
return; //or throw
}
var selectedValue = selVal.ToString();
var query=
e.FeatureSet.Features
.Select(feature => feature.Attributes[selectedValue])
.Select(attr => attr == null
? "blank"
: attr.ToString())
.Where(attrVal => !uniquevalues.Contains(attrVal));

Your data model is almost certainly "wrong" in the sense that it's very error prone and hard to work with. You should not be converting everything to string but working on the strongly typed objects directly. Doing so will likely fix this bug automatically as it's very likely the NullReferenceException is being thrown when you attempt to ToString a null value.
Not only is it much safer to work on the typed objects, it's also much faster and will result in shorter code.

Related

Why Linq Substring() ignore null value

I just realized that when I request this
Orders.Where(y => y.Sub_Item_Id.Substring(0, 10) != y.Sub_Item_Site_Id.Substring(0, 10))
The query ignore all my null value that may exist in y.Sub_Item_Site_Id. So when I have a value in Sub_Item_Id and null in Sub_Item_Site_Id the query does NOT consider this as !=.
Why?
I also tested the same query with SQL
select
*
from
orders as o
where
LEFT(o.sub_item_id, 10) <> LEFT(o.sub_item_site_id, 10)
And I get the same result. I have all my different value but NOT when I have a value in o.sub_item_id and null in o.sub_item_site_id.
Could you explain how and why SQL and Linq is working like this.
Substring() doesn't ignore null, in your query if one of the strings will be null you will get NullPointerException and if one of the string is shorter than 10 symbols, you will get ArgumentOutOfRangeException:
https://msdn.microsoft.com/library/aka44szs(v=vs.110).aspx
Check your data nad your query.
You may want to add a tag indicating that your LinQ in the background connects to a database to execute SQL there. Without that information, Maksim is correct. In plain Linq-to-Objects C# you would get the appropriate exceptions.
However, as your LinQ is translated and executed as SQL, you just met a surprisingly unintuitive SQL feature: NULL is never equal to anything else. Not even NULL. And NULL is never not equal to anything else. No even a value or another NULL. It just never yields true in a comparison, whatever you compare it to.
You can use the IS syntax to ask if something is NULL. Or you can replace your NULL with a default value before doing your statement. But comparing existing values and NULL will always yield false because NULL is not equal to anything, not even NULL itself.
Relational expressions involving NULL actually yield NULL again. In order to filter null values, you need to use the IS NULL and IS NOT NULL. You can find an answer here.

Get a specific column value from a table when query through linq

var Sent = request.Transactions.First(x => x.isSent == "4");
When the above query runs it gets the complete list of a table row
when condition meets. I just want a specific column value
Date_Sent.
Can I also create a if statement to check if the Date_Sent is null
or not?
TheFirst returns an item of the collection's type. Simple access it's property.
var sent = request.Transactions.FirstOrDefault(x => x.isSent=="4")?.Data_Sent;
If(sent == null) { }
See 2 things:
I suggest you use FirstOrDefault instead. It will not throw an exception if no item in sequence match predicate.
Use the ?. to access the property. It is called Null Propagation
If you do want to use the .Select then thr nicer way without creating temporary anonymous objects or breaking it into separate commands is to use the query syntax instead like this:
var sent = (from item in request.Transactions
where item.isSent =="4"
select Sent_Data).FirstOrDefault()
By the way I'd recommend looking into naming conventions in C#

Linq skip query if string is Null

I am trying to implement a search function, but am running into problems when some of the fields are not filled in by a user.
string country = searchCountry.Text.ToLower();
string state = searchState.Text.ToLower();
var searchLocation= (from h in db.Locations where (!string.IsNullOrWhiteSpace(country) ? h.Country.ToLower().Contains(country):false)
&& (!string.IsNullOrWhiteSpace(state) ? h.State.ToLower().Contains(state) : false)
select h);
The problem is that when one of the strings is empty the searchLocation returns nothing and only works when both fields are filled in. I Have tried replacing the && with || but then it will get results, even if one of the search terms is not in the db.
Is there a way to do this, besides Filtering out null values in a linq search
This will return any locations where either the country is empty or it matches, and either the state is empty or it matches.
var searchLocation= (from h in db.Locations
where (string.IsNullOrWhiteSpace(country) || h.Country.ToLower().Contains(country))
&& (string.IsNullOrWhiteSpace(state) || h.State.ToLower().Contains(state))
select h);
It would help to have a bit more description of what you'd like to put in and get out, but this seems logical to me.
Either field would be optional, but it would filter results to include anything that matched all (one or two) filled in fields.
Of course, if you run this without any filters, it will return all locations. So keep that in mind if you're making requests to the database. If that's desired behavior, it might make sense to just pull all your data into a list beforehand, rather than querying every time anything is typed.
I believe you're overthinking this. Just validate the fields before searching:
string country = searchCountry.Text.ToLower();
string state = searchState.Text.ToLower();
if(string.IsNullOrWhitespace(state) || string.IsNullOrWhitespace(country))
{
//MessageBox.Show...
return;
}
var searchLocation= //query with validated fields
It's a very good idea to validate your input before trying to perform actions against it. And it makes your code more readable than combining the two.

Check for items inside a Entity Framework linq result

I am trying to check to see if any results were returned from an entity framework query before acting upon it, I'm trying to use the code :-
var shoppingCartSessions = from c in context.ShoppingCartSessions where c.UserId == gUserID select c;
if (shoppingCartSessions.First() != null)
{
}
However I get the error
Sequence contains no elements
I have checked around stack and found that I can replace .First with .FirstOrDefault however I wanted to check if this is the correct way to be checking for existence of elements. Is there a better way rather than trying to fetch the item and then checking it?
Use Any():
var shoppingCartSessions = from c in context.ShoppingCartSessions
where c.UserId == gUserID
select c;
if (shoppingCartSessions.Any())
{
//not empty
}
Have you tried checking .Count() > 0 ?
EDIT:
As stated by Mahmoud Gamal, using Any() should render slightly better performance, since it will execute an EXISTS query, rather than a COUNT() on the DB, and you ultimately don't care about the exact amount.

Why is this if/then statement returning as true?

I have a rather ugly service job that runs through a legacy database and compares it to our production database:
if (vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number) != null) {
var oldDbContractItem = vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number).First();
// check to see if there were changes
if (oldDbContractItem.DateStamp != vendorContractItem.Date_Stamp)
{
oldDbContractItem.Update(vendorContractItem);
}
}
I will get an error on var oldDbContratItem, "Sequence contains no elements", yet I just did a != null check. This must be simple, what's going on?
If I could teach people just one thing about LINQ it's this: the value of a query expression is an object that represents the query, not the results of the query. Fundamentally that's your problem; you're treating the query as its results. A query isn't a result any more than a restaurant is a club sandwich. A restaurant is a device which produces club sandwiches; a query is a device that produces results.
This is the test against null you are doing:
vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number) != null
That will always be true; That will always return at least an empty sequence... never a null.
You might be meaning to test that its length is greater than 0?
There's an easier way, though, IMO. Call FirstOrDefault() instead of First() and leave out the pre-test completely. Then instead, test if the result of FirstOrDefault() is null.
var oldDbContractItem = vendorContract.Item
.Where(x => x.ItemNumber == contractItem.Item_Number).FirstOrDefault();
if(oldDbContractItem != null) //would be null if there are no items
{
// check to see if there were changes
if (oldDbContractItem.DateStamp != vendorContractItem.Date_Stamp)
{
oldDbContractItem.Update(vendorContractItem);
}
}
}
Because your query returned a container, it just happened to be empty, the null check is on the return not what the return contains.
try this instead...
if (vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number).Any())
{
.....
}
Don't run the query twice. It's inefficient and may introduce a race condition into your code. Also, your logic is much better supported by either using IEnumerator<T> directly, or with a foreach loop.
Use either:
var result = vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number).GetEnumerator();
if (result.MoveNext) {
var oldDbContractItem = result.Current;
// ...
}
or
foreach (var oldDbContractItem in vendorContract.Item.Where(x => x.ItemNumber == contractItem.Item_Number)) {
// ...
break;
}
A sequence with no elements is still an object.
Where can return a non-null value, but still resolve to a sequence containing no elements. In your failing statement you are using something else, which is Where().First(). That will be null if the sequence from Where is indeed empty.
There is difference between null and an empty sequence (e.g. something similar to new List<T>()). What you want to do is to use Any() to check whether the sequence contains any elements, or rather replace First() with FirstOrDefault(), which returns null if the sequence contains no element. (If you use that, make sure that null is not a valid value that could be returned by First()).
After using a fix from the accepted answer, you can further debug the LINQ situation (if need be) by using the following steps. LINQ is an exciting technology but takes a while to wraps ones' head around it - a bit of a paradigm shift I would say. Eric's answer hit the nail on the head because he likely helped build the stuff!
Debugging Steps for LINQ
To deal with the issue of no results from the second statement change .First() to .FirstOrDefault() If nothing is found it will return the default value of the data type - if the data type is a class it will return a null value. Your second statement should then work with a null check too and without error.
Then you can debug your LINQ statement to find out why it's doing what it does.
if using LINQ to SQL, Intellisense in Visual Studio 2010 will show you the SQL generated when you hover over a query variable (not the result of a query). If you need the visualizer for VS 2008 it's here
Similarily if you're using LINQ to Entity Framework, you can get the generated SQL using the visualizer plugin here.
I always take the generated SQL from these tools, paste it directly into a query window and run it there. It will show you the empty set you're getting back and if that's a problem you can further debug it in this manner of visualizing the generated statements.

Categories