Sequence contains no matching element Error using Boolean - c#

bool Postkey =
statement
.ThreadPostlist
.First(x => x.ThreadKey == ThreadKey && x.ClassKey == classKey)
.PostKey;
This Ling query is giving me "Sequence contains no matching element" but I know I can use .FirstorDefault(). When I use .FirstorDefault() it will return me false, the default value for bool, when there are no matching records.
But I get a "Object not set to an instance of an object" error. I need to check the bool for null with .HasValue and .Value. I don't know how to do it.

Here is how you can use a nullable bool to solve this:
bool? postKey = null;
// This can be null
var post = statement.ThreadPostlist.FirstOrDefault(x=>x.ThreadKey == ThreadKey && x.ClassKey == classKey);
if (post != null) {
postKey = post.PostKey;
}
// Now that you have your nullable postKey, here is how to use it:
if (postKey.hasValue) {
// Here is the regular bool, not a nullable one
bool postKeyVal = postKey.Value;
}

You could do:-
bool? postkey = threadPostList
.Where(x=>x.ThreadKey == threadKey && x.ClassKey == classKey)
.Select(x => (bool?)x.PostKey)
.DefaultIfEmpty()
.First();
I think that better captures the intent of what you are trying to accomplish.

If you want to treat a null value as false (and don't want to use a nullable bool), you could just check if the resulting post is null before referencing the .PostKey property, like this:
var threadPost = statement.ThreadPostlist.FirstOrDefault(x =>
x.ThreadKey == ThreadKey && x.ClassKey == classKey);
bool PostKey = threadPost != null && threadPost.PostKey;
Or, a longer form would be:
bool PostKey;
if (threadPost != null)
{
PostKey = threadPost.PostKey;
{
else
{
PostKey = false;
}

Related

LINQ search filter logic

I have apartment entity and I want to get apartments based on my filters.
this is my search entity
public class Search
{
public bool isStudio {get;set;}
public bool isNoPlanning {get;set;}
public bool isMultiRoom {get;set;}
public int[] NumberOfRooms {get;set;}
}
this is my current search logic.
var apartments = buildRepost.Get(buildId).Where(condStates =>
(searchModel.NumberOfRooms != null
&& searchModel.NumberOfRooms.Contains(condStates.RoomsCount.ToString())
|| ((searchModel.IsStudio && condStates.IsStudio))
|| ((searchModel.IsNoPlanning && condStates.IsFreePlaning))
|| ((searchModel.IsMultiRoom && condStates.RoomsCount >= 4)));
The problem with this logic is that I got the wrong result when all fields are false and null. For example when isStudio, IsNoplaning and isMultiRoom are false and numberofRooms is null I should have got all apartments but instead, I got an empty array. Any help?
the searchModel.NumberOfRooms != null checker in the where clause causes the problem, you are not mathcing it with any of the condStates properties and the searchModel.Is..... properties
Make your searchModel as a checker in an if statement then build the query from the if searchModel conditions.
var query = buildRepost.Get(buildId).AsQueryable();
if (searchModel.NumberOfRooms != null)
{
query = query.Where(condStates => searchModel.NumberOfRooms.Contains(condStates.RoomsCount.ToString());
}
if (searchModel.IsStudio)
{
query = query.Where(condStates => condStates.IsStudio);
}
if (searchModel.IsNoPlaning)
{
query = query.Where(condStates => condStates.IsFreePlaning)
}
if (searchModel.IsMultiRoom)
{
query = query.Where(condStates => condStates.RoomsCount >= 4)
}
var results = query.ToList()
(searchModel.NumberOfRooms != null
&& searchModel.NumberOfRooms.Contains(condStates.RoomsCount.ToString())
This is always going to be false when the NumberOfRooms is null (due to the null check), and given that the other bool values are all false, you will get no results.
Instead if you change to:
(searchModel.NumberOfRooms == null
|| searchModel.NumberOfRooms.Contains(condStates.RoomsCount.ToString())
You will either get everything (when the NumberOfRooms is null, or just the records that match the RoomsCount (when the NumberOfRooms is not null).
Note that in this case, if NumberOfRooms is null you will still return everything regardless of your bool filters. Which seems to be what your code requires, but I'm not sure is what you actually require, so you might want to check that.

Null value in linq where clause

I'm having an issue where I want to return results where something matches and I get an error if one of the properties I'm trying to match is null.
if (!string.IsNullOrEmpty(searchString))
{
Infos = Infos.Where(
x =>
x.FirstName.ToLower().Contains(searchString) ||
x.LastName.ToLower().Contains(searchString) ||
x.ContractNum.ToLower().Contains(searchString) ||
x.VIN.ToLower().Contains(searchString) ||
x.Claim.InitiatedBy.ToLower().Contains(searchString)
).ToList();
}
If ContractNum or VIN, for example, are null then it throws an error. I'm not sure how to check if one of these are null inside of a linq query.
You can add explicit null checks:
Infos = Infos.Where(
x =>
(x.FirstName != null && x.FirstName.ToLower().Contains(searchString)) ||
(x.LastName != null && x.LastName.ToLower().Contains(searchString)) ||
(x.ContractNum != null && x.ContractNum.ToLower().Contains(searchString)) ||
(x.VIN != null && x.VIN.ToLower().Contains(searchString)) ||
(x.Claim != null && x.Claim.InitiatedBy != null && x.Claim.InitiatedBy.ToLower().Contains(searchString))
).ToList();
You have multiple options, first is to do an explicit check against null and the other option is to use Null propagation operator.
x.FirstName != null && x.FirstName.ToLower().Contains(searchString)
or
x.FirstName?.ToLower()?.Contains(searchString) == true
But I would suggest you to use IndexOf instead of Contains for case
insensitive comparison.
something like:
x.FirstName?.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase) >= 0)
Checking the property is null or empty before comparing it it's the only way I know
if (!string.IsNullOrEmpty(searchString))
{
Infos = Infos.Where(
x =>
(!String.IsNullOrEmpty(x.FirstName) && x.FirstName.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.LastName) && x.LastName.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.ContractNum) && x.ContractNum.ToLowerInvariant().Contains(searchString)) ||
(!String.IsNullOrEmpty(x.VIN) && x.VIN.ToLowerInvariant().Contains(searchString)) ||
(x.Claim != null && !String.IsNullOrEmpty(x.Claim.InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant().Contains(searchString))
).ToList();
}
EXTRA: I added a check on the Claim property to make sure it's not null when looking at InitiatedBy
EXTRA 2: Using the build in function IsNullOrEmpty to compare string to "" and nullso the code is clearer.
Extra 3: Used of ToLowerInvariant (https://msdn.microsoft.com/en-us/library/system.string.tolowerinvariant(v=vs.110).aspx) so the lowering action will act the same no matter of the culture.
You could use ?? to replace it with a acceptable value.
(x.ContractNum??"").ToLower()
I would use the null conditional operator ?, this will however, return a nullable bool? so you will need to handle that appropriately.
Some examples on how to do this:
x?.FirstName?.ToLower().Contains(searchString) == true;
x?.FirstName?.ToLower().Contains(searchString) ?? false;
An alternative method to keep the comparison logic in one place to use a sub collection of the properties and check on those:
Infos = Infos.Where(i=>
new[] {i.FirstName,i.LastName,i.ContractNum /*etc*/}
.Any(w=> w?.ToLower().Contains(searchString) ?? false))
.ToList();
(It does read out all properties, but that shouldn't cost much performance and gains much maintainability )

Null object in Func

I have a filter as below:
filter = project => project.Plan.ProgressStatus == progressStatus;
I am creating a filter based on progressStatus that is passed into method.
Then I pass this filter to a where operator.
var projects = _projectService.Where(filter);
I get back NRE since Plan is null.
How can I safely query objects whose Plan.ProgressStatus is equal to what i pass in as parameter?
Make your filter check if it is null:
filter = project => project.Plan != null && project.Plan.ProgressStatus == progressStatus;
If _projectService possibly contains null then add that check as well:
filter = project => project != null
&& project.Plan != null
&& project.Plan.ProgressStatus == progressStatus;
Add a null check to the project and/or project.Plan objects in your func.
filter = project =>
{
if(project == null || project.Plan == null)
return false;
return project.Plan.ProgressStatus == progressStatus;
};

more short code about if statement

i wanted to try the following code:
//all arrays are List<T> type.
if (m.terms[0] != null && m.terms[0].labels != null && m.terms[0].labels[0].title == "Part-of-speech")
{
result = true;
}
but it occured runtime error occasionly in following situation
i. m.terms == null
ii. m.terms != null, but m.terms[0] does not intialized.
iii. m.terms != null, and m.terms[0] has been exist but
m.terms[0].label does not initialized.
...
so i did modify it to like this:
if (m.terms[0] != null)
{
if (m.terms[0].labels != null)
{
if (m.terms[0].labels[0].title == "Part-of-speech") { result = true; }
}
}
is it the best way?
&& is a short circuiting operator, so the first way you wrote it and the second way will be functionally equivalent.
if (a && b && c)
{
// work
}
b will only be evaluated if a returns true. (Same goes for c).
In your code, checking m.terms[0].labels will not be a problem because you would have short-circuited out of the expression if m.terms[0] had been null.
To completely cover yourself, you'd want to possibly add checks for m and m.terms, however.
m != null && m.terms != null && m.terms.Count > 0 && m.terms[0] != null ...
As it evaluates from left to right, it will break on the first condition that doesn't pass and the rest will go unchecked.
int index = 0;
int labelIndex = 0;
string titleToCheck = "Part-of-speech";
if (m != null && m.terms != null && m.terms.Count > index)// or m.Length...
{
if (m.terms[index] != null && m.terms[index].labels != null &&
m.terms[index].labels.Count > labelIndex)
{
if (m.terms[index].labels[labelIndex].title == titleToCheck)
{
result = true;
}
}
}
This is all about readability. C# uses Short-circuit evaluation so in functionality there is no difference.
try this
if (m!=null && m.terms!= null && m.terms[0].labels!=null && m.terms[0].labels[0].title!=null && m.terms[0].labels[0].title == "Part-of-speech")
Yes, it would be better to split off each null check into a separate if statement.
The reason is that the second and third conditions require the first to not be null. If the first is null, then the second and third conditions will in turn throw errors because their parent is null yet is trying to be accessed.

Compare nullable types in Linq to Sql

I have a Category entity which has a Nullable ParentId field. When the method below is executing and the categoryId is null, the result seems null however there are categories which has null ParentId value.
What is the problem in here, what am I missing?
public IEnumerable<ICategory> GetSubCategories(long? categoryId)
{
var subCategories = this.Repository.Categories.Where(c => c.ParentId == categoryId)
.ToList().Cast<ICategory>();
return subCategories;
}
By the way, when I change the condition to (c.ParentId == null), result seems normal.
Other way:
Where object.Equals(c.ParentId, categoryId)
or
Where (categoryId == null ? c.ParentId == null : c.ParentId == categoryId)
The first thing to do is to put on logging, to see what TSQL was generated; for example:
ctx.Log = Console.Out;
LINQ-to-SQL seems to treat nulls a little inconsistently (depending on literal vs value):
using(var ctx = new DataClasses2DataContext())
{
ctx.Log = Console.Out;
int? mgr = (int?)null; // redundant int? for comparison...
// 23 rows:
var bosses1 = ctx.Employees.Where(x => x.ReportsTo == (int?)null).ToList();
// 0 rows:
var bosses2 = ctx.Employees.Where(x => x.ReportsTo == mgr).ToList();
}
So all I can suggest is use the top form with nulls!
i.e.
Expression<Func<Category,bool>> predicate;
if(categoryId == null) {
predicate = c=>c.ParentId == null;
} else {
predicate = c=>c.ParentId == categoryId;
}
var subCategories = this.Repository.Categories
.Where(predicate).ToList().Cast<ICategory>();
Update - I got it working "properly" using a custom Expression:
static void Main()
{
ShowEmps(29); // 4 rows
ShowEmps(null); // 23 rows
}
static void ShowEmps(int? manager)
{
using (var ctx = new DataClasses2DataContext())
{
ctx.Log = Console.Out;
var emps = ctx.Employees.Where(x => x.ReportsTo, manager).ToList();
Console.WriteLine(emps.Count);
}
}
static IQueryable<T> Where<T, TValue>(
this IQueryable<T> source,
Expression<Func<T, TValue?>> selector,
TValue? value) where TValue : struct
{
var param = Expression.Parameter(typeof (T), "x");
var member = Expression.Invoke(selector, param);
var body = Expression.Equal(
member, Expression.Constant(value, typeof (TValue?)));
var lambda = Expression.Lambda<Func<T,bool>>(body, param);
return source.Where(lambda);
}
My guess is that it's due to a rather common attribute of DBMS's - Just because two things are both null does not mean they are equal.
To elaborate a bit, try executing these two queries:
SELECT * FROM TABLE WHERE field = NULL
SELECT * FROM TABLE WHERE field IS NULL
The reason for the "IS NULL" construct is that in the DBMS world, NULL != NULL since the meaning of NULL is that the value is undefined. Since NULL means undefined, you can't say that two null values are equal, since by definition you don't know what they are.
When you explicitly check for "field == NULL", LINQ probably converts that to "field IS NULL". But when you use a variable, I'm guessing that LINQ doesn't automatically do that conversion.
Here's an MSDN forum post with more info about this issue.
Looks like a good "cheat" is to change your lambda to look like this:
c => c.ParentId.Equals(categoryId)
You need to use operator Equals:
var subCategories = this.Repository.Categories.Where(c => c.ParentId.Equals(categoryId))
.ToList().Cast<ICategory>();
Equals fot nullable types returns true if:
The HasValue property is false, and the other parameter is null. That is, two null values are equal by definition.
The HasValue property is true, and the value returned by the Value property is equal to the other parameter.
and returns false if:
The HasValue property for the current Nullable structure is true, and the other parameter is null.
The HasValue property for the current Nullable structure is false, and the other parameter is not null.
The HasValue property for the current Nullable structure is true, and the value returned by the Value property is not equal to the other parameter.
More info here Nullable<.T>.Equals Method
Or you can simply use this. It will also translate to a nicer sql query
Where((!categoryId.hasValue && !c.ParentId.HasValue) || c.ParentId == categoryId)
What about something simpler like this?
public IEnumerable<ICategory> GetSubCategories(long? categoryId)
{
var subCategories = this.Repository.Categories.Where(c => (!categoryId.HasValue && c.ParentId == null) || c.ParentId == categoryId)
.ToList().Cast<ICategory>();
return subCategories;
}
Linq to Entities supports Null Coelescing (??) so just convert the null on the fly to a default value.
Where(c => c.ParentId == categoryId ?? 0)

Categories

Resources