object reference error in LINQ query - c#

var query1 = from a in inputDataRecords
from b in employeeDataRecords
.Where(badgeNumber => a.Responsi == badgeNumber.Badge)
.Where(badgeNumber => a.Auth == badgeNumber.Badge)
.Where(badgeNumber => a.ByN == badgeNumber.Badge)
.DefaultIfEmpty()
select new {a,
responsibleName = b.EmployeeName,
authName = b.EmployeeName,
createName = b.EmployeeName};
gives me an error of: Object reference not set to an instance of an object.
I know it's because I'm not referencing b.
But changing the select to:
select new {a, b,
responsibleName = b.EmployeeName,
authName = b.EmployeeName,
createName = b.EmployeeName};
doesn't help. QuickWatch on query1 shows that b is null.

b is null beacuse you specifically called out in your query that b should be null if the sequence is empty through your use of DefaultIfEmpty. If you don't want to have a null b item when that sequence is empty, omit that operation. If you do, then you need to support having a null b value in your query.

note that you're using a number of items from .Where clauses, which could be null in the collection and thus throw this exception from any one of those lambdas. Try using a .Where(o => o != null) on both of those collections, and that may clear up the error.

Related

C# EF DefaultIfEmpty with Where().Select()

Is there a way similar to what we can do with linq for left outer join with method based query syntax.
e.g.
var a = from m in context.MainClass
join r in context.RefClass on m.RefID equals r.ID into joinedent
from j in joinedent.DefaultIfEmpty()
select new { m.Name , j.TypeName }
Can I convert this into method based syntax with navigation property default if null
var a = context.MainClass.Select(x=> new {
m.Name
m.RefClass.TypeName // here need default if RefClass is null
})
I can do like (m.RefClass != null)?m.RefClass.TypeName:"" but would like to know if there is a proper way to do this like in above linq.
Thanks
Just use new initialization in DefaultIfEmpty parameter
var a = from m in context.MainClass
join r in context.RefClass on m.RefID equals r.ID on joinedent
from j in joinedent.DefaultIfEmpt(new RefClass())
select new { m.Name , j.TypeName }
Hope the problem will be solve
When EF executes the Linq against the database, the m.RefClass.TypeName would return #null, where the same statement against objects would throw a NullReferenceException.
m.RefClass?.TypeName should return string.Empty in both cases.
Update: As mentioned the ?. is not allowed in expression trees, however the following does work:
var a = context.MainClass.Select(x=> new {
m.Name
TypeName = m.RefClass.TypeName ?? ""
})
EF expressions will return #null for properties where the child reference is null rather than a null reference exception. However checking the RefClass for null would be safer in case the expression gets copied/moved in a way where it would be run against objects rather than through EF.
On a curious side note I did come across an interesting side-effect while testing this: This only works properly if the relationship between parent and child is mapped as optional. (Obviously) In my case I had an existing test relationship that was set up as "Required" or non-nullable. I'd changed the schema to make the child ID null-able and it did not throw any exceptions, it simply returned no rows
Can you try using Include?
var a = context.MainClass.Include("RefClass")
.Select(x => new {
m.Name
m.RefClass.TypeName // here need default if RefClass is null
})

LINQ C# Join with Left-Join result

I'm trying to do a left-join with the result of another left-join but in some cases it returns me null reference error (obviously), is there any way to do this without using foreach after select?
var result = from f in foo
from ex in exp.Where(w => w.id == f.idFoo).DefaultIfEmpty()
from te in tes.Where(w => w.id == ex.anyID).DefaultIfEmpty()
select new
{
var1 = f.something,
...
var2 = te.anything
};
That's happening because DefaultIfEmpty is returning a sequence with a single null element. Then you are trying to access properties on a null element.
Use the overload of DefaultIfEmpty to return a non-null default value (of the appropriate data type):
var result = from f in foo
from ex in exp.Where(w => w.id == f.idFoo)
.DefaultIfEmpty(new Exp())
from te in tes.Where(w => w.id == ex.anyID)
.DefaultIfEmpty(new Tes())
select new
{
var1 = f.something,
...
var2 = te.anything
};
That way you won't be trying to access properties on null elements.
Edit based on comments. In the query, one place that null elements arise is when a Where results in zero matches. For instance, in the third from the ex variable might be a sequence of one null element, and again in the select the te might also be such a sequence. In both cases, accessing a property will throw an exception.
Alternatively, you could do a null test every time you are going to access a property. That would become verbose fast.
Something like this:
var2 = te != null ? te.anything : null

LINQ sub list<> sometimes returns "NULL"

I have a LINQ query with a sublist in it which sometimes can return no returns, however can't manage to get the actual null instead of a error.
Any help in this would be appriciated.
var member_settings = from ml in _pMetaLanguages
join s in _settings
on ml.id equals s.setting_type_id
orderby ml.name descending
select new _class {
group_name = ml.name
, code = (ml.classes.Where(c => c.id == s.int_value)).FirstOrDefault().code
, name = (ml.classes.Where(c => c.id == s.int_value)).FirstOrDefault().name
, id = (ml.classes.Where(c => c.id == s.int_value)).FirstOrDefault().id
,
classUI = ml.metadataMUI
,
nameUI = ml.metadataMUI.Where(u => u.language_type_id.Equals(list_language_id))
.Select(i => new pMetaClasses
{
name = i.classes.Where(y => (y.bound_id.Equals(list_language_id))).FirstOrDefault().name
}).FirstOrDefault().name
, setting_type_id = s.setting_type_id
, int_value = s.int_value
};
EDITED
This part delivers the problems
nameUI = ml.metadataMUI.Where(u => u.language_type_id.Equals(list_language_id))
.Select(i => new pMetaClasses
{
name = i.classes.Where(y => (y.bound_id.Equals(list_language_id))).FirstOrDefault().name
}).FirstOrDefault().name
"metadataMUI" sometimes has records but not always, when no records it should be null (at least no error...
You have a collection of objects, it may or may not be empty. You want to pull out a property from the first item in that collection, if there is one. Currently whenever your query is face with this problem you are using this general approach:
sequence.FirstOrDefault().SomeMember
This code works fine if the sequence will always contain an item. It doesn't work if it may be empty. (Unless you can and want to get the member of the default value. For reference types, as you clearly are working with, this just results in null reference excpetions.) Fortunately there is a simple transformation to ensure that this works correctly. Simply use Select to transform the sequence into the sub-property that you are interested in and then get the first or default value of that sequence:
sequence.Select(item => item.SomeMember).FirstOrDefault();
This will work properly whether there are items or no items. The projection will never be called on default values using this approach.
Of course you do this in a lot of places, so you'll need to make this transformation throughout your query.

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

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