I have a query like this :
result =
firstIdeaRepository.FindBy(
i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end)
.AsEnumerable()
.Select(j => new RptListOfCompanyBasedOnFirstIdeaState()
{
Name =
companyRepository.FindBy(i => i.UserId == j.UserId)
.FirstOrDefault()
DateOfMeeting =
calenderRepository.ConvertToPersianToShow(
meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id)
.FirstOrDefault()
.Date),
DateOfExit =
calenderRepository.ConvertToPersianToShow(j.DateOfExit.Value),
ReasonOfExit = j.ReasonOfExit,
}).ToList();
return result;
As you can see i use FirstOrDefault() and j.DateOfExit.Value and sometimes my Date doesn't have any values or sometime my other variables are null too because i use firstordefaut() like
companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault().
So my query throws a null exception and the result can't be created ,how can i handle this exception and for example if the .NET detects the null value ignores it by default or uses a default values for that ?
Best regards.
I would make the following changes:
result =
firstIdeaRepository.FindBy(
i => i.FirstIdeaState == FirstIdeaState && i.Date >= start && i.Date <= end)
.AsEnumerable()
.Select(j => new RptListOfCompanyBasedOnFirstIdeaState()
{
Name =
companyRepository.FindBy(i => i.UserId == j.UserId)
.FirstOrDefault()
DateOfMeeting =
callenderRepository.ConvertToPersianToShow(
meetingReposiotry.FindBy(s => s.FirstIdeaId == j.Id)
// project a new sequence first, before calling `FirstOrDefault`:
.Select(s => s.Date)
.FirstOrDefault(),
DateOfExit =
j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value) :
null,
ReasonOfExit = j.ReasonOfExit,
}).ToList();
When you use FirstOrDefault, there's a possibility that you'll get null back (in the case of reference types), and so you need to plan for that in your code.
For example, when assigning DateOfMeeting, you could project the results (using .Select) before using .FirstOrDefault, so that you're not ever accessing the Date property on what could be a null value.
As for DateOfExit, I've used the conditional operator to determine whether to call the calendarRepository's method at all. This assumes that DateOfExit is nullable.
Unrelated: "Calendar" is spelled with one "l" and not two.
Since you're using a nullable date, you can try filtering by values that have date, something like:
.FindBy(s => s.FirstIdeaId == j.Id && s.Date.HasValue)
This will ensure that you don't get any records with null date.
As I mentioned in comments, other cases need to be handled on case-by-case basis. Judging by the code you've shown, maybe you can handle Name as:
Name = companyRepository.FindBy(i => i.UserId == j.UserId).FirstOrDefault() ?? "anonymous";
and so on.
Another example:
If you do want to get the record even if DateOfMeeting is null, then add a check for HasValue in subsequent part or default it to some date:
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: (DateTime)null, // you need to make `DateOfExit` nullable and then handle that downstream
// or (default with current date)
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: callenderRepository.ConvertToPersianToShow(DateTime.Now),
// or (default with empty date)
DateOfExit = j.DateOfExit.HasValue ?
callenderRepository.ConvertToPersianToShow(j.DateOfExit.Value)
: callenderRepository.ConvertToPersianToShow(new DateTime()),
Moral of the story: figure out what the default value should be in case of null and then substitute that accordingly in the query when calling FirstOrDefault().
The broadest solution would be to use the idea of an null object with the DefaultIfEmpty<T>(T DefaultValue) method in your query. An example would be:
var defaultMeeting = new Meeting() { Date = new DateTime() };
var dateOfMeeting = meetingRepository.FindBy(s => s.FirstIdeaId == j.Id)
.DefaultIfEmpty(defaultMeeting)
.FirstOrDefault()
.Date;
Related
In my sql database WorkDay field is in string format and in model it is nullable DayOfWeek, i.e public DayOfWeek? WorkDay { get; set; }. While Converting database WorkDay field into model WorkDay field it will generate an error like:
Could not translate expression 'Table(StaffSchedule)' into SQL and
could not treat it as a local expression.
I have also tried to create three different linq statements which are as below.
1) Retrieve Data from StaffSchedule table.
2) Apply select operation on it.
3) Apply AddRange operation on selected data.
results.AddRange(dataContext.StaffSchedules
.Where(x => !x.Excluded)
.Where(x => x.DistrictID == districtId && x.District.Active && (x.Position == positionTeacher || x.Position == positionDirector || x.Position == positionAssistant || x.Position == positionAssistantDirector))
.Select(x => new Core.StaffSchedule()
{
ID = x.ID,
Staff = x.Staff.SelectSummary(),
Position = (StaffPosition)Enum.Parse(typeof(StaffPosition), x.Position, true),
Class = refs.Class,
District = x.District.SelectSummary(),
Time = null,
Reoccurring = false,
Inherited = true,
ReoccourringStart = x.ReoccourringStart,
ReoccourringEnd = x.ReoccourringEnd,
WorkDay = x.WorkDay == null ? (DayOfWeek?)null : (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x.WorkDay, true)
}));
This is the conversion code for string to nullable DayOfWeek field. Which cause an error in my case.
WorkDay = x.WorkDay == null ? (DayOfWeek?)null : (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x.WorkDay, true)
I have already gone through below link.
How to solve issue "Could not translate expression ...into SQL and could not treat it as a local expression."
Try to convert dataContext.StaffSchedules to IEnumerable by calling ToList()
method before making the query like this
results.AddRange(dataContext.StaffSchedules.ToList()
.Where(x => !x.Excluded)....the rest of you query
Search for difference between IEnumerable and IQueryable for more detailed explain
You can't translate any C# code to SQL so x.WorkDay == null ? (DayOfWeek?)null : (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x.WorkDay, true) won't work in Linq to Entities.
Try to select your data after the query execution by writing AsEnumerable() before Select. Don't do it at the beginning of the query because you will fetch all the data from a db table.
results.AddRange(dataContext.StaffSchedules
//everything (well almost) from this point is going to be translated into SQL
.Where(x => !x.Excluded)
.AsEnumerable() //everything from here is going to be executed after the query ends so it can be any C# code
.Select(x => new Core.StaffSchedule()
{
//now this should work
WorkDay = x.WorkDay == null ? (DayOfWeek?)null : (DayOfWeek)Enum.Parse(typeof(DayOfWeek), x.WorkDay, true)
});
Why would a nullable int give this error using linq?
public void test(int? variableId)
{
var date = _dbContext.Set<MyEvent>()
.Where(x => x.Calendar.id == (variableId.HasValue ? variableId : x.Calendar.id))
.ToList();
}
variableId.HasValue is false
variableId is null
You should write it as (variableId.HasValue ? variableId.Value : x.Calendar.id)
Assuming variableId is null, then you have a very funny expression .Where(x => x.Calendar.id == x.Calendar.id) that means - all records. The problem with your code is that having your original where expression most likely cause client side filtering but not sql side filtering. It is better to rewrite it like:
var date = variableId.HasValue
?_dbContext.Set<MyEvent>().Where(x => x.Calendar.id == variableId.Value))
:_dbContext.Set<MyEvent>();
I have this LINQ statement which returns null if the sequence is empty. I assign the result into a nullable DateTime. Later on I check if the DateTime.HasValue property and ReSharper tells me the expression is always true.
DateTime? latestUploadDateInBLSO = Documents.Where(d => d.DocumentLinkId == documentLinkId &&
d.UploadedInStage.StageNumber == 6 &&
d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId)
.Select(d => d.UploadedOnDate)
.DefaultIfEmpty()
.Max();
if (latestUploadDateInBLSO.HasValue) { // <-- Says this is always true
Documents.Single(d => d.DocumentLinkId == documentLinkId &&
d.UploadedOnDate == latestUploadDateInBLSO &&
d.UploadedInStage.StageNumber == 6 &&
d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId).IsLatestVersion = true;
}
Since latestUploadDateInBLSO can be null, how is that expression always true?
As UploadedOnDate isn't nullable, the result will always be a DateTime value and never null. If the list is empty, you'll get default(DateTime), which is DateTime.MinValue.
If you want it to return null, you'll need to cast your UploadedOnDate to DateTime?. You can omit the DefaultIfEmpty as per the docs Max will return null for an empty sequence if the type is nullable.
DateTime? latestUploadDateInBLSO = Documents
.Where(d => d.DocumentLinkId == documentLinkId && d.UploadedInStage.StageNumber == 6 && d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId)
.Select(d => (DateTime?)d.UploadedOnDate)
.Max();
If uploadedOnDate is also of DateTime type then it's not NULL. The default value for DateTime is equal to DateTime.MinValue. That is why your nullable will always have a value. If you want to change this you'll explicitly have to say via DefaultIfEmpty and return NULL as default value.
It's because of the DefaultIfEmpty call combined with a sequence of non-nullable elements (DateTime) - you're saying if the collection returned from the Where and Select is empty, to instead return a collection with a single defaulted DateTime within it, so it will never return null.
Here's a small sample with the output from LINQPad:
List<DateTime> l = new List<DateTime>();
DateTime x = l.DefaultIfEmpty().Max();
x.Dump();
var y = new DateTime();
y.Dump();
l.DefaultIfEmpty().Dump();
DefaultIfEmpty is probably initializing your DateTime object to its default value which is DateTime.MinValue so it's never null and thus HasValue will always return true.
Sometimes, when I try to lookup insurance name, if it is not found then I want my InsuranceName variable to have null value. But I always get NullReferenceException. I can get around it by putting into series of if statements checking for null, is there anyway to do it in one line?
string InsuranceName = db.Medicares.FirstOrDefault(p => p.MedicareId = 2).Insurances.FirstOrDefault(p => p.InsuranceId = 1).Name;
var medicare = db.Medicares.Include(m => m.Insurances).FirstOrDefault(p => p.MedicareId == 2);
string InsuranceName = medicare == null ? null : medicare.Insurances.FirstOrDefault(p => p.InsuranceId == 1).Name;
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
}