Linq Query Crash if Return Null - c#

I run this query And if The Query is return with empty values the programme is crashed.
var cust = db.Customers.FirstOrDefault(x => x.telephone == txtTel.Text);
if (cust.BlackList == 1)
{
MessageBox.Show("This customer is blacklisted, Do you wish to continue with this job?");
}
Please Suggest me Some Efficient solution
Thanks.

You are getting a null pointer because FirstOrDefault returns the default value of the object if the result is not found (in this case it is null):
var cust = db.Customers.FirstOrDefault(x => x.telephone == txtTel.Text);
if (cust != null && cust.BlackList == 1)
{
MessageBox.Show("This customer is blacklisted, Do you wish to continue with this job?");
}

You need to check for null because that's what FirstOrDefault returns if there is no record that satisfies your condition:
if(cust != null && cust.BlackList == 1)

FirstOrDefault will return a default value if there is no element in the list which satisfy the condition, in this case it will be null. As you call a property on the null value it will naturally cause an exception.
You should check if cust is null, like:
if(cust != null && cust.BlackList == 1)
Of course you can display another message if the user doesn't exist based on the logic of your application.

Related

linq: how to check if the value of one attribute exists

if statement to check the value of an attribute doesn't work.
if (element.Elements(ns + "list").Where(x => x.Attribute("name").Value == "myProject") != null)
Is there other way to check if the value of an attribute exists?
you can use firstordefault
var element = element.Elements(ns + "list").Where(x => x.Attribute == "myProject");
// return if null
if(element == null) return;
// do your stuff
Sorry for messy indentation as I'm typing on mobile :)

FirstOrDefault returns NullReferenceException if no match is found

Here is my code:
string displayName = Dictionary.FirstOrDefault(x => x.Value.ID == long.Parse(options.ID)).Value.DisplayName;
The code works fine if x.Value.ID matches options.ID. However, I get a NullReferenceException if it doesn't.
FirstOrDefault returns the default value of a type if no item matches the predicate. For reference types that is null. Thats the reason for the exception.
So you just have to check for null first:
string displayName = null;
var keyValue = Dictionary
.FirstOrDefault(x => x.Value.ID == long.Parse(options.ID));
if(keyValue != null)
{
displayName = keyValue.Value.DisplayName;
}
But what is the key of the dictionary if you are searching in the values? A Dictionary<tKey,TValue> is used to find a value by the key. Maybe you should refactor it.
Another option is to provide a default value with DefaultIfEmpty:
string displayName = Dictionary
.Where(kv => kv.Value.ID == long.Parse(options.ID))
.Select(kv => kv.Value.DisplayName) // not a problem even if no item matches
.DefaultIfEmpty("--Option unknown--") // or no argument -> null
.First(); // cannot cause an exception
You can use a combination of other LINQ methods to handle not matching condition:
var res = dictionary.Where(x => x.Value.ID == someID)
.Select(x => x.Value.DisplayName)
.DefaultIfEmpty("Unknown")
.First();
Simply use the question mark trick for null checks:
string displayName = Dictionary.FirstOrDefault(x => x.Value.ID == long.Parse(options.ID))?.Value.DisplayName ?? "DEFINE A DEFAULT DISPLAY NAME HERE";
That is because FirstOrDefaultcan return null causing your following .Value to cause the exception. You need to change it to something like:
var myThing = things.FirstOrDefault(t => t.Id == idToFind);
if(myThing == null)
return; // we failed to find what we wanted
var displayName = myThing.DisplayName;
To add to the solutions, here is a LINQ statement that might help
Utilities.DIMENSION_MemTbl.Where(a => a.DIMENSION_ID == format.ContentBrief.DimensionID).Select(a=>a.DIMENSION1).DefaultIfEmpty("").FirstOrDefault();
The result will be an empty string if the result of the query is a null..
This answer is for those of us who need a visual write up (like me :)
In the code screenshot below, a NullReferenceException will be thrown, the root cause is the ReferenceIdentification_02 property.
When debugging, we see that the orderLine.REF array, I am querying does not include a matching object whose ReferenceIdentificationQualifier_01 value == "RU", so at that point FirstOrDefault() return value is NULL
to prevent the NullReferenceException, I do a FirstOrDefault() on the orderLine.REF array first. If the returned value is not null then I retrieve the value.
i assume you are working with nullable datatypes, you can do something like this:
var t = things.Where(x => x!=null && x.Value.ID == long.Parse(options.ID)).FirstOrDefault();
var res = t == null ? "" : t.Value;
you can use with 'Where' statement with FirstOrDefault().
like this.
var modelItem = _dbcontext.ModelName.Where(n => n.NewsTagId == newsTag.Id).FirstOrDefault();
It returns first item if does not match query.
It is better practice to check the NULL after query.
if(modelItem == null)
{
return "Not Found."
}
else
{
// continue process
}

Is there a way I can check for null object in AddRange() method linq statement?

I want to check in the below code if no match is found it should not throw object reference null error.
itm.lstCustomziation.AddRange(
(from xx in db.vw_DressingCustomization
where xx.CatID == itm.HeaderName.Value && xx.ProductID == itm.ProductID
select new itmCustomization()
{
catId = (int)xx.CatID,
custType = customizationType.Dressing,
isCustomziationDisplay = xx.IsDefaultDisplay,
isFixLimit = (bool)xx.isDefaultLimit,
maxLimit = (short)xx.DefaultFreeCount,
itmName = xx.Description,
isItemDefault = xx.IsDefaultDisplay,
price = (double)xx.MainPrice,
proId = (int)xx.ProductID
}).ToList<itmCustomization>());
You should break it into multiple steps. First execute the query and get the results. Then you should check for null/count and based on that check call the add range method. It would be more readable as well.
Add check whether your nullable itm.HeaderName really has value before accessing that value:
where itm.HeaderName.HasValue && // check if value exists
xx.CatID == itm.HeaderName.Value && // otherwise here is the problem
xx.ProductID == itm.ProductID

getting Object reference not set to an instance of an object. exception

Server stack trace:
at
Tavisca.TravelNxt.Hotel.Core.Controllers.HotelSuppliersController.b__33(PassengerTypeQuantity
passengerInfo)
at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func2
predicate)
code:
if (passengers == null || passengers.Count == 0)
{
_serviceStatus.MissingItems.Add(Utility.GetXmlElementORAttributeName(type, property));
return false;
}
if (passengers.Any(passengerInfo => passengerInfo.Quantity == 0))
{
_serviceStatus.InvalidItems.Add(Utility.GetXmlElementORAttributeName(type, property));
return false;
}
Please try this
if (passengers == null || (passengers != null && passengers.Count == 0))
{
_serviceStatus.MissingItems.Add(Utility.GetXmlElementORAttributeName(type, property));
return false;
}
if (passengers.Any(passengerInfo => (passengerInfo == null) || (passengerInfo != null && passengerInfo.Quantity == 0)))
{
_serviceStatus.InvalidItems.Add(Utility.GetXmlElementORAttributeName(type, property));
return false;
}
Since the error is in linq, this means the problems is occurring on the line
if (passengers.Any(passengerInfo => passengerInfo.Quantity == 0))
and it is because one or more of the elements in passengers is null, thus the passengerInfo.Quantity part results in the object not set to an instance exception.
Try changing the line to the following to see if it resolves the error:
if (passengers.Any(passengerInfo => passengerInfo == null || passengerInfo.Quantity == 0))
(though of course, this change might in reality be masking the real problem of you having a null passengerInfo object)
Object reference not set to an instance of an object. means that you have an object that is null, hence it's not instantiated. You solve this by ensuring that the object is in-fact instantiated.
There are multiple ways to go by this, it all depends on what you want your application to do in a case of unexpected behavior (a null!).
Example of a null object
If you were to write the following:
Person filip = null;
Console.WriteLine(filip.Name);
Then the second line would give us a Object reference not set to an instance of an object. exception, because we in fact now know that filip is null.
So how do we solve this?
Either we can check if it is null before we print it:
Person filip = null;
if(filip != null)
{
Console.WriteLine(filip.Name);
}
Or if we are getting the Person from another metod, we can use ?? to ensure that it is not null and if it is, we just create a new one like this:
Person filip = GetFilip() ?? new Person();
It all depends on what you want to do in case of a null in your application.
As others have mentioned, you need to set a breakpoint and find where the error are occuring, when you find that, look for what object is null and make sure that it is handled properly.
You have good information in your stack trace that leads us to the LINQ statement.
In your case, you check if (passengers == null || passengers.Count == 0) but at the next line you have if (passengers.Any....) this means that even if passengers is null, it will still try to Any() on it which will throw an exception.
Maybe you are just looking for an else if?
The solution is to make check for all.
if (passengers == null || (passengers != null && passengers.Count == 0))
{
_serviceStatus.MissingItems.Add(Utility.GetXmlElementORAttributeName(type, property));
return false;
}
if (passengers.Any(passengerInfo => (passengerInfo == null) || (passengerInfo != null && passengerInfo.Quantity == 0)))
{
_serviceStatus.InvalidItems.Add(Utility.GetXmlElementORAttributeName(type, property));
return false;
}

c# dealing with all possible null and non null values

I have the following method:
public IQueryable<Profile> FindAllProfiles(string CountryFrom, string CountryLoc)
{
return db.Profiles.Where(p => p.CountryFrom.CountryName.Equals(CountryFrom,
StringComparison.OrdinalIgnoreCase));
}
What is the best way to write the where clause that would filter all the possible combinations of input parameters in one statement:
BOTH CountryFrom and CountryLoc = null
Only CountryFrom null
Only CountryLoc null
BOTH CountryFrom and CountryLoc are not null.
Soon .. I would need to filter out profiles by Age, Gender, Profession .. you name it.
I am trying to find a way to write it efficiently in C#. I know how to do it in a clean manner in TSQL. I wish I knew the way. Thanks for all the responses so far.
A good old binary XNOR operation will do the trick here:
db.Profiles.Where(p => !(p.CountryFrom == null ^ p.CountryTo == null))
It's effectively equating two booleans, though to me it's more direct, less convoluted even, than writing ((p.CountryFrom == null) == (p.CountryTo == null))!
I would use this simple LINQ syntax...
BOTH CountryFrom and CountryLoc = null
var result = from db.Profiles select p
where (p.CountryFrom == null) && (p.CountryLoc == null)
select p
Only CountryFrom null
var result = from db.Profiles select p
where (p.CountryFrom == null) && (p.CountryLoc != null)
select p
Only CountryLoc null
var result = from db.Profiles select p
where (p.CountryFrom != null) && (p.CountryLoc == null)
select p
BOTH CountryFrom and CountryLoc are not null.
var result = from db.Profiles select p
where (p.CountryFrom != null) && (p.CountryLoc != null)
select p
Hope it helps ;-)
I wouldn't call this elegant:
public IQueryable<Profile> FindAllProfiles(string CountryFrom, string CountryLoc)
{
return db.Profiles.Where(p =>
{
p.ContryFrom != null &&
p.CountryFrom.CountryName != null &&
p.CountryFrom.CountryName.Equals(CountryFrom, StringComparison.OrdinalIgnoreCase)
});
}
I may be missing something, but as written, your combination of operators will either let all values through or no values through depending on whether you use || or && to combine them together.
I'm in favor of not trying to cram too much logic into a linq expression. Why not contain your comparison logic in a separate function like this?
EDIT: I provided an example implementation of the MatchesCountry function.
class Example
{
public IQueryable<Profile> FindAllProfiles(string CountryFrom, string CountryLoc)
{
return db.Profiles.Where(p => p.MatchesCountry(CountryFrom, CountryLoc));
}
}
public static class ProfileExtensions
{
public static bool MatchesCountry(this Profile profile, string CountryFrom, string CountryLoc)
{
// NOTE: Your comparison logic goes here. Below is an example implementation
// if the CountryFrom parameter was specified and matches the profile's CountryName property
if(!string.IsNullOrEmpty(CountryFrom) && string.Equals(profile.CountryName, CountryFrom, StringComparison.OrdinalIgnoreCase))
return true; // then a match is found
// if the CountryLoc parameter was specified and matches the profile's CountryCode property
if (!string.IsNullOrEmpty(CountryLoc) && string.Equals(profile.CountryCode, CountryLoc, StringComparison.OrdinalIgnoreCase))
return true; // then a match is found
// otherwise, no match was found
return false;
}
}

Categories