C# Query - Non Static Method Requires a Target - c#

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

Related

linq null reference error with orderby but firstordefault works

I have the following code:
IEnumerable<VariantChild> children = src.Variants
.Where(v => !v.ExcludeFromWebsite && !v.ExcludeFromEcommerce)
.SelectMany(v => v.Children)
.Where(c => c.Price > 0 && !c.ExcludeFromWebsite && !c.ExcludeFromEcommerce);
if (children.Any())
{
VariantChild child = children.OrderBy(c => c.Price).FirstOrDefault(); // this line is throwing a null reference error
if (child != null)
{
dest.Price = child.Price;
}
}
But it is throwing a null refence exception on the line highlighted. If I remove the orderby, the code works so I thought it may be to do with the price being null - but it can't be as it is a double.
Having stepped through the code, the .Any() returns true, but if I change that to .Count(), I get the null exception
If I step through and check the children object - I can see the results view is null so shouldn't .Any() return false (although why does FirstOrDefult() return a variant child?
Anyone any ideas what is causing the null exception?
Here is a screenshot of the code as I stepped into it:
Keep in mind that linq expressions are not evaluated when created but only when necessary (ex: ToList, or in your case, OrderBy then FirstOrDefault. See deferred execution.). So the null reference exception can be in the evaluation of children.
Supposing that ExcludeFromWebsite and ExcludeFromEcommerce are booleans and can't be null and Price is a double and can't be null. Only remain Children witch is an IEnumerable (because used in SelectMany) so it can be null.
Furthermore, in your screen shot, the stack trace refer to the SelectManyIterator.
You should check for Children to not be null :
IEnumerable<VariantChild> children = src.Variants
.Where(v => !v.ExcludeFromWebsite && !v.ExcludeFromEcommerce)
.SelectMany(v => v.Children ?? Enumerable.Empty<T>()) // T is the type of element in Children
.Where(c => c.Price > 0 && !c.ExcludeFromWebsite && !c.ExcludeFromEcommerce);

Cannot compare elements of type 'System.Collections.Generic.ICollection`1 Only primitive types, enumeration types and entity types are supported

I have written this code
IQueryable<Site> sites = context.MainTable.Include("RelatedTable");
if (!string.IsNullOrEmpty(param1)) {
sites = sites.Where(s => s.RelatedTable != null && s.RelatedTable.Any(p => p.Name == param1.ToLower() && p.PolicyType == "primary"));
}
foreach (string secondaryPolicy in secondaryPolicies)
{
sites = sites.Where(s => s.RelatedTable != null && s.RelatedTable.Any(p => p.Name == secondaryPolicy.ToLower() && p.PolicyType == "secondary"));
}
return sites.ToList();
However at the ToList line I am getting the exception
Cannot compare elements of type
'System.Collections.Generic.ICollection`1[[Project1, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null]]'. Only primitive types,
enumeration types and entity types are supported.
You can't compare a related table to null directly. Instead, compare against your foreign key member (assuming that PrimaryTable reference RelatedTable using a member called RelatedTableId.
sites.Where(s => s.RelatedTableId != null && s.RelatedTable.Any(
p => p.Name == param1.ToLower() && p.PolicyType == "primary"));
You may even be able to get away with removing the null check completely. Since this query is run against the database, you won't get a NullReferenceException and it may work. You'll have to double check on that though.
It is because that you have a null check in the where clause.
The error can occur if navigation collection compared with null. It should be checked if Any record exist. In the particular example Any is used anyway, so check collection to null is redundant
Incorrect
dbContext.MainTable.Where(c => c.RelatedTable==null )
Correct
dbContext.MainTable.Where(c => !c.RelatedTable.Any() )
Collection field can be null in this case you get exception NullReferenceException
when use RelatedTables.Any()
If you add RelatedTables != null as in a question then you can get
Cannot compare elements of type
'System.Collections.Generic.ICollection`1[[Project1, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null]]'. Only primitive types,
enumeration types and entity types are supported.
If you get the NullReferenceException exception, lazy loading is not turned off and you are good with lazy loading for the field then to prevent exception mark field with virtual keyword to allow lazy loading for the field
virtual ICollection<Table> RelatedTables{ get; set; }
I don't have a Foreign Key field configured because the relationship between MainTable and RelatedTable in my case is 1 to 1. However for a 1 to many relationship if you don't have foreign key but you have a navigation property to the MainTable model in the RelatedModel model the following solution also works.
1 to 1
var result = from s in context.Sites
join r in context.RelatedTable on s.Id equals r.Id
select s;
return result;
1 to many
var result = from s in context.Sites
join r in context.RelatedTable on s.Id equals r.Site.Id
into rs
where rs.RelatedTable.Any(p => p.Name == param1.ToLower() && p.PolicyType == "primary")
select s
I also have the same situation. It then passed by comparing null with FirstOrDefault(). In your case, I applied as per below
sites = sites.Where(s => s.RelatedTable.FirstOrDefault() != null && s.RelatedTable.Any(p => p.Name == param1.ToLower() && p.PolicyType == "primary"));
It work me , I just remove the null check;
correct:
result=
db.EmpTable.FirstOrDefault().ProjectsAssign.Name,
InCorrect :
result=
db.EmpTable!=null && db.EmpTable.FirstOrDefault().ProjectsAssign!=null ?
db.EmpTable.FirstOrDefault().ProjectsAssign.Name : null,

LINQ check if FirstOrDefault is null and use it

I'm writing a query that uses FirstOrDefault after an OrderBy query, which should check if it isn't null first then use some data in it. Is there a better way than writing it like this:
int count = db.Items.Count(i =>
i.Assignments.OrderByDescending(a =>
a.DateAssigned).FirstOrDefault() != null
&&
i.Assignments.OrderByDescending(a =>
a.DateAssigned).FirstOrDefault().DateReturned == null)
What this code does is there are items that has many assignments, I take the latest assignment by date, then check if it exist, then run a condition on a property (DateReturned). As you see, this query is long, and most of my queries seem to look like this where I check for null first then run a second query on it using their properties. Is there a better way of doing this?
Just call .Any(a => a.DateReturned == null) to check whether there are any items that meet the condition.
If you only want to check the latest assignment, add .Take(1) before the .Any().
My take:
int count =
itemsQuery.Select(i => i.Assignments.OrderByDescending(a => a.DateAssigned))
.Count(i => i.FirstOrDefault() != null &&
i.First().DateReturned == null);
You can put the result in a variable to avoid doing the same thing twice:
int count = itemsQuery.Count(i => {
var f = i.Assignments.OrderByDescending(a => a.DateAssigned).FirstOrDefault();
return f != null && f.DateReturned == null;
});

StrongTypingException in Linq

Anybody can tell why the ToList() throws an exception?
var duplicates =
from typeMappings in _liveTable.Where(r =>
(r.ProviderId == providerId) && (r.ExchangeId == exchangeId))
join dataDictionary in _liveDataSet.DataDictionary.Where(r =>
(r.DataDictionaryTypeId == dataDictionaryTypeId))
on typeMappings.DataDictionaryId equals dataDictionary.DataDictionaryId
select typeMappings.ConfigId;
if (duplicates.ToList().Count > 0)
{ ... }
The Exception message is:
'duplicates.ToList()' threw an exception of type 'System.Data.StrongTypingException' System.Collections.Generic.List {System.Data.StrongTypingException}
Thanks
From MSDN:
StrongTypingException
The exception that is thrown by a strongly typed DataSet when the user accesses a DBNull value.
So the problem occurs because one of the properties you access in the query is null. Check which properties of your DataTable are allowed to be null, and check it with a call to IsNull before you try to get the value.
Try to use that to eleminate Null value
var duplicates =
from typeMappings in _liveTable.Where(r =>
(r.ProviderId == providerId) && (r.ExchangeId == exchangeId))
join dataDictionary in _liveDataSet.DataDictionary.Where(r =>
(r.DataDictionaryTypeId == dataDictionaryTypeId))
on typeMappings.DataDictionaryId equals dataDictionary.DataDictionaryId
select new
{ ConfigId = typeMappings.ConfigId = null ? "anyValueyouwhant" : typeMappings.ConfigId};
juste to test without null value

LINQ to SQL lambda where [nullable object must have a value error]

I'm getting the error
[nullable object must have a value]
And it's point at the following part of the code
.Min(x => x.Time)
Here's the whole function.
public DateTime GetFirstRecord(long userId)
{
DateTime firstRecordDate;
using (DeviceExerciseDataDataContext context = new DeviceExerciseDataDataContext())
{
firstRecordDate = (DateTime)context.Datas.Where(x => x.UserID.Equals(userId)).Min(x => x.Time);
}
return firstRecordDate;
}
Also, how can I debug this functions lambda? When I hover over the x's, It shows no value. When when I try to print in the immediate window, it says "the name 'x' does not exist in the current context"
Edit:
So I've updated my code to this:
public DateTime? GetFirstRecord(long userId)
{
DateTime? firstRecordDate;
firstRecordDate = DateTime.Now;
using (DeviceExerciseDataDataContext context = new DeviceExerciseDataDataContext())
{
var test = context.Datas.Where(x => x.UserID.Equals(userId));
if (test != null)
firstRecordDate = (DateTime)test.Min(x => x.Time);
else
firstRecordDate = null;
}
return firstRecordDate;
}
But I'm still getting the save error.
In the DB, There are no null value's anywhere. Oh, and it doesn't go to the else, in the if/else block.
There is a good chance that context.Datas could be null or any of the Data's userId could be null or x.Time is null and you are trying to cast it as (DateTime) instead of (DateTime?).
You will have to add conditions to capture these null values in your assignment statement something like:
DateTime? datevalue = context.Datas == null
? null
: (DateTime?)context.Datas.Where(x => x.UserId != null && x.UserID.Equals(userId))
.Min(x => x.Time);
If it is possible for firstRecordDate to be null, the .Min isn't allowed.
Can you try this?
firstRecordDate = (DateTime)context.Datas.Where(x => x.UserID.Equals(userId));
if (firstRecordDate.Count() > 0) firstRecordDate = firstRecordDate.Min(x => x.Time);
if that works, then that's your problem. There are probably more elegant ways to deal with this but at least you will have a workaround to start with.
If you can be assured that at least one row has a valid time you could filter out the entries that have null as Time (or handle the case that DateTime.MaxValue is returned)
firstRecordDate = context.Datas.Where(x => x.UserID == userId)
.Select( x=> x.Time ?? DateTime.MaxValue)
.Min();
Try
(DateTime)context.Datas.Where(x => x.UserId != null && x.UserID.Equals(userId)).Min(x => x.Time)
The userID != null should evaluate first which will prevent nulls when you get to the Min. I haven't tested that but I think I remember doing stuff like it in the past.
The Min function is attempting to return the minimum value, and I've encountered this message before when no elements were being returned from the IQueryable - you need to check for the existance of elements before invoking, or declare firstRecordDate as a DateTime?.
Debugging lambda's is not supported in the watch window. If you want to debug it, I would suggest instead making it a long form lambda over multi line in order to debug
.Where(x =>
{
return x.ToString();
});
You would be able to debug the inner method code then.
You will get that error if context.Datas.Where(x => x.UserID.Equals(userId)) does not return any values.
If you use DateTime? instead of DateTime it will avoid this error by returning null.

Categories

Resources