Handling empty collections in Entity Framework - c#

I fill up a List in Entity Framework;
List<StockProperties> props = db.StockProperties
.Where(prop => prop.Stok_ID == stok.ID)
.ToList();
The problem here is if my query is null, it returns a
Non-static method requires a target.
error which is obvious since EF does that with empty sequences.My question is what is the most reasonable way to handle these null queries?I want my list to be empty if my query returns null sequences.

This:
List<StockProperties> props = db.StockProperties
.Where(prop => false)
Is returning a System.Linq.Enumerable.WhereListIterator<StockProperties> with 0 reccords it will never be null.
Your problem may be with prop => prop.Stok_ID == stok.ID
Do stok is declared?
Check here

You can supply a fall back option for null
var props =
db.StockProperties.Where(prop => prop.Stok_ID == stok.ID)
?? Enumerable.Empty<StockProperties>();
or
var props =
db.StockProperties.Where(prop => prop.Stok_ID == stok.ID).ToList()
?? new List<StockProperties>();

Related

LINQ not evaluating check for null object

I'm wondering why my linq statement doesn't properly evaluate the null check on the Agency object which is a property of the Users model.
var invalidUsers = this.DbContext.Users.Where(p => p.Agency != null).ToList();
var invalidUsersList = invalidUsers.Where(p => p.Agency != null).ToList();
When I run the code above, the first line returns a list of all Users, regardless of the Agency object being null or not. However, the second line executes and properly filters the list and returns a list that is correctly returning Users where Agency is not null.
Chances are since this appears to be a foreign key table you need to include it first in LINQ so it can query against it.
So something like.
var invalidUsers = await this.DbContext.Users
.Include(p => p.Agency)
.Where(p => p.Agency != null)
.ToListAsync();
Give that a try and see if it helps.

C# Query - Non Static Method Requires a Target

i am getting an error that says 'Non Static Method requires a target'
Here is the code that is causing me the error, could anyone possible shed some light on this?
//TODO: Error, Non static method requires a target.
var orderItem =
_context.PurchaseOrderItems.FirstOrDefault(
p => p.JobReference == item.JobReference && p.ItemNumber == item.ItemNumber);
return _context.DeliverySchedules.Include(d => d.PurchaseOrderItem)
.Where(d => d.PurchaseOrderItem.Id == orderItem.Id)
.ToList();
The FirstOrDefault method may return null value if no query results returned there:
var orderItem = _context.PurchaseOrderItems.FirstOrDefault(
p => p.JobReference == item.JobReference && p.ItemNumber == item.ItemNumber);
Since orderItem.Id throws NullReferenceException when orderItem is null, it will propagate to LINQ throwing TargetException as mentioned in question (see this post and this post for more info).
Hence, you need to check presence of null value from orderItem by modifying second LINQ query to this one:
return _context.DeliverySchedules.Include(d => d.PurchaseOrderItem)
.Where(d => (orderItem != null && d.PurchaseOrderItem.Id == orderItem.Id))
.ToList();
NB: Null checking must takes place before retrieving property Id of orderItem to prevent NullReferenceException.
As an alternative, if condition to check against null value may be used without modifying second query:
if (orderItem != null)
{
return _context.DeliverySchedules.Include(d => d.PurchaseOrderItem)
.Where(d => d.PurchaseOrderItem.Id == orderItem.Id)
.ToList();
}
Change the FirstOrDefault to Single because in the next line you will get to its properties and you dont want a NullReferenceException

LINQ Lambda only select if exists

I am using NHibernate which is abstracted away using Respositories and services. We are not allowed to Lazy Load properties, so they have to be selected in the query.
My issue is that I am trying to get the most recent response number from the Answers table, but in many cases the object might not exist, so I am stuck with getting Null Reference exceptions, or "Code should be unreachable" exceptions.
Here is what i'm doing with the approprtiate sections commented.
.
var leaders =
_storeService.GetAll()
.Where( p => p.Id.Equals(storeId) && p.Employees.Any() )
.SelectMany(p => p.Employees)
.Select(emp => new
{
LeaderId = emp.Id,
LeaderFirstName = emp.FirstName,
LeaderLastName = emp.LastName,
Followers = emp.Followers
.Select(followers => new
{
followers.FollowerEmployee.Id,
followers.FollowerEmployee.FirstName,
followers.FollowerEmployee.LastName,
DepartmentName = followers.FollowerEmployee.Department.Name,
//Problem Area
AssessmentResponse = followers.FollowerEmployee
.Answers
.First( a => a.Answer.Question.IsPrimary )
.Answer
.Number
//Null Reference Exception
} )
} ).ToList();
I've probably tried 15 iterations of this, not always using .First but sometimes .Single
I don't have access to the repository pattern or any of the NHibernate queries. Is there a way to avoid this null reference exception with LINQ? I can't lazy load, so it's a bit of an issue.
In EF/Linq-2-Sql, this can be made to work by casting to a nullable value since the underlying SQL does null-coalescing:
AssessmentResponse = (int?)followers.FollowerEmployee.Answers
.First(a => a.Answer.Question.IsPrimary).Answer.Number
I'm not sure what the behavior would be in NHibernate but it's worth a try. If the Number property is already nullable, you could try coalescing it:
AssessmentResponse = (int?)followers.FollowerEmployee.Answers
.First(a => a.Answer.Question.IsPrimary).Answer.Number ?? some default value
Finally, you could always do an explicity check:
AssessmentResponse = followers.FollowerEmployee.Answers.Any(a => a.Answer.Question.IsPrimary)
? followers.FollowerEmployee.Answers.First(a => a.Answer.Question.IsPrimary).Answer.Number ?? some default value
: null
Instead of this:
AssessmentResponse = followers.FollowerEmployee
.Answers
.First( a => a.Answer.Question.IsPrimary )
.Answer
.Number
//Null Reference Exception
Try this:
AssessmentResponse = followers.FollowerEmployee
.Where(a=>a.Answers != null && a.Answers
.Where(a=>a.Answer.Question.IsPrimary)
.Count > 0)
.Answers
.FirstOrDefault( a => a.Answer.Question.IsPrimary )
.Answer
.Number
//Null Reference Exception

Comparing a nullable column throws "Unable to cast the type..." exception

My entity NewsItem has a nullable foreign key property: LibraryID of type int?.
My issue is when I query the property and compare it with any value except null, I get exceptions.
Initially my code was:
int? lid = ...
var results = context.NewsItems
.Where(n => n.LibraryID == lid);
but it gives me no results at all, no matter what lid is.
So, I tried:
var results = context.NewsItems
.Where(n => n.LibraryID.Equals(lid));
gives exception:
Unable to create a constant value of type 'System.Object'. Only primitive types or enumeration types are supported in this context.
and then I tried:
var results = context.NewsItems
.Where(n => lid.Equals(n.LibraryID));
and got:
Unable to cast the type 'System.Nullable`1' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.
and this:
var results = context.NewsItems
.Where(n => object.Equals(lid, n.LibraryID));
gives same exception as the last one.
Now I was desperate, so I tried to complicate stuff (like other forums suggested, for example here):
var results = context.NewsItems
.Where(n => (lid == null ? n.LibraryID == null : n.LibraryID == lid));
but still getting same exception.
So... any SIMPLE workarounds?
How about
var results = context.NewsItems
.Where(n => lid.HasValue ? lid.Value == n.LibraryId.Value : (!n.LibraryId.HasValue) );
Hmm, that first snippet should work. I've used nullables like that many times. First thing I'd do is a sanity check just to make sure LibraryID is really int? and not long? or similar.
Other than that, you can try this:
var results = context.NewsItems
.Where(n => (lid.HasValue ? n.LibraryID == lid.Value : !n.LibraryID.HasValue));
Or to avoid the ?: within the query:
var results = lid.HasValue
? context.NewsItems.Where(n => n.LibraryID == lid.Value)
: context.NewsItems.Where(n => !n.LibraryID.HasValue);
It seems that EF does not find the correct operator overload. Therefore it produces wrong results if you set lid = null.
Use linq to objects by adding AsEnumerable() to your query and everything is fine:
var results = context.NewsItems.AsEnumeryble().Where(n => n.LibraryID == lid);
According to the MSDN docs (which I finally found), .Where() will only filter your collection. If you want to see if there are actually results, resolve by lazily executing the filtered query with .ToList(), GetEnumerator, or enumerating the collection with foreach;
This method is implemented by using deferred execution. The immediate
return value is an object that stores all the information that is
required to perform the action. The query represented by this method
is not executed until the object is enumerated either by calling its
GetEnumerator method directly or by using foreach in Visual C# or For
Each in Visual Basic.
http://msdn.microsoft.com/en-us/library/bb534803.aspx
int? lid = ...
var results = context.NewsItems
.Where(n => n.LibraryID == lid).ToList();
var results = context.NewsItems
.Where(n => n.LibraryID.HasValue && n.LibraryID.Value == lid.Value );
edit:
Previous filter was based on my understanding that you wanted to filter to entires having a particular value. Updated will filter to null or value.
var results = context.NewsItems
.Where(n => !n.LibraryID.HasValue || n.LibraryID.Value == lid.Value );

Where Predicates in LINQ

How can I specify conditions in Where predicates in LINQ without getting null reference exceptions. For instance, if q is an IQueryable how can I do like:
Expression<Func<ProductEntity,bool>> predicate = p => !search.CategoryId.HasValue || (search.CategoryId.HasValue && search.CategoryId == p.CategoryId);
var q2 = q.Where(predicate);
Here search is an object that holds possible search conditions that may or may not be set like search.CategoryId might not be set but if it is I want to get the products that are set by that condition.
When I do this I get null reference exceptions.
You can use the null-coalescing operator ?? to replace a possible null value with a default value. The following sets tries to match the search.Category if it exists or simply creates an "always true" expression. This will be optimized by any good Linq query provider (e.g. LinqToSql).
Expression<Func<ProductEntity,bool>> predicate = p => (search.CategoryId ?? p.CategoryId) == p.CategoryId);
var q2 = q.Where(predicate);
Another possibility would be to dynamically compose a query predicate using PredicateBuilder. That's the way I do it for searches with a similar pattern as you use:
var predicate = PredicateBuilder.True<Order>();
if (search.OrderId))
{
predicate = predicate.And(a => SqlMethods.Like(a.OrderID, search.OderID);
}
// ...
var results = q.Where(predicate);
Let's dissect the line:
Expression<Func<ProductEntity,bool> predicate = p => !search.CategoryId.HasValue
|| (search.CategoryId.HasValue && search.CategoryId == p.CategoryId)
var q2 = q.Where(predicate);
So how many ways can we get null problems?
search (your "captured" variable) could be null
p could be null, meaning there is a null in the list
you've handled the case of search.CategoryId being null (Nullable<T>)
but maybe p.CategoryId (the category on a record in the list) is null (Nullable<T>) - however, I'm not sure that this would cause a NullReferenceException
q (the list / source) could be null
So: out of 5 options you've eliminated 1; look at the other 4? There is also the definite possibility that the issue is caused by something invisible not shown in the code; for example the get could be:
public int? CategoryId {
get {return innerObject.CategoryId;}
}
and innerObject could be null; if you eliminate the other 4 (pretty easy to do), look at at this one as a last resort.

Categories

Resources