Matthew Matthew - 2 months ago 16
C# Question

Checking decimal for NULL in LINQ query

In the assignment part of my LINQ query I need to check if the value is null and assign a default value if it is. The value type coming back is decimal and when I compare to null I get the warning


The result of the expression is always 'false' since a value of type 'decimal' is never equal to 'null' of type 'decimal?'


If I try to compare it to see if the value is 0 then I get the error


The cast to value type 'System.Decimal' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.


What is the best way to check to see if
HoursWorked2
is null or not and assign a default value to it if it is null?

Edit:
I did not think all the code for everything would be needed but since others think it is needed here is all the code related to it:

// AJAX: /TimeOverviewGrid
[Route("TimeOverviewGrid", Name = "Time Overview Grid")]
public ActionResult TimeOverviewGrid()
{
var PayPeriod = TimeCardHelper.GetCurrentPayPeriod();
var WeekBeforePayPeriod = PayPeriod.AddDays(-7);

try
{
var EmployeeID = EmployeeHelper.GetEmployeeID(User.Identity.Name);

using (var db = new JobSightDbContext())
{
var TimeOverviewData = (from th1 in db.TimeCardHeaders
join e in db.Employees on th1.EmployeeID equals e.ID
join so1 in db.StatusOptions on th1.CurrentStatusID equals so1.ID
join leftth2 in db.TimeCardHeaders.Where(timeCardHeader => timeCardHeader.WeekEndingDate == PayPeriod)
on th1.EmployeeID equals leftth2.EmployeeID into leftjointh2
from th2 in leftjointh2.DefaultIfEmpty()
join so2 in db.StatusOptions on th2.CurrentStatusID equals so2.ID into leftjoinso2
from th2Final in leftjoinso2.DefaultIfEmpty()
where th1.WeekEndingDate == WeekBeforePayPeriod && (e.ID == EmployeeID || e.ManagerID == EmployeeID)
orderby e.FirstName
select new DashboardTimeOverviewVM()
{
EmployeeID = e.ID,
Employee = string.Concat(e.FirstName, " ", e.LastName),
WeekOfDate1 = th1.WeekEndingDate,
HoursWorked1 = th1.TotalHoursWorked,
Status1 = so1.Name,
WeekOfDate2 = (th2.WeekEndingDate == null) ? PayPeriod : th2.WeekEndingDate,
HoursWorked2 = (th2.TotalHoursWorked == null) ? 0 : th2.TotalHoursWorked,
Status2 = (string.IsNullOrEmpty(th2Final.Name)) ? "New" : th2Final.Name,
PTO = e.PTORemaining
}).ToList();

return Json(TimeOverviewData, JsonRequestBehavior.AllowGet);
}
}
catch (Exception ex)
{
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { responseText = "Error getting data, please try again later" }, JsonRequestBehavior.AllowGet);
}
}

public static DateTime GetCurrentPayPeriod()
{
var KnownPayPeriodDate = DateTime.Parse("2007-11-10");
while (KnownPayPeriodDate.CompareTo(DateTime.Today) < 0)
{
KnownPayPeriodDate = KnownPayPeriodDate.AddDays(14);
}

return ((KnownPayPeriodDate - DateTime.Today).Days < 7) ? KnownPayPeriodDate : KnownPayPeriodDate.AddDays(-14);
}

public static int GetEmployeeID(string adUserName)
{
adUserName = adUserName.Remove(0, 9);

using (var db = new JobSightDbContext())
{
return db.Employees.Where(employee => employee.ADUserName == adUserName).Select(employee => employee.ID).First();
}
}

public class DashboardTimeOverviewVM
{
public int EmployeeID { get; set; }
public string Employee { get; set; }
public DateTime WeekOfDate1 { get; set; }
public decimal HoursWorked1 { get; set; }
public string Status1 { get; set; }
public DateTime WeekOfDate2 { get; set; }
public decimal HoursWorked2 { get; set; }
public string Status2 { get; set; }
public decimal PTO { get; set; }
}

public class TimeCardHeader
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }

public int EmployeeID { get; set; }
public DateTime WeekEndingDate { get; set; }
public decimal TotalHoursWorked { get; set; }
public int CurrentStatusID { get; set; }
public decimal OtherPay { get; set; }
public int? ApprovedByID { get; set; }
public DateTime? DateSubmitted { get; set; }
public DateTime? DateApproved { get; set; }

[Column(TypeName = "varchar(MAX)")]
public string ManagerNotes { get; set; }

[ForeignKey("EmployeeID")]
public Employee Employee { get; set; }

[ForeignKey("ApprovedByID")]
public Employee ApprovedBy { get; set; }

[ForeignKey("CurrentStatusID")]
public StatusOption CurrentStatus { get; set; }
}

public class Employee
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }

[Required]
public string FirstName { get; set; }

[Required]
public string LastName { get; set; }

[Required]
public string ADUserName { get; set; }

[Required]
public string Email { get; set; }

public int? ManagerID { get; set; }

[Required]
public string EmploymentType { get; set; }

[Required]
public string PhoneNumber { get; set; }

[Required]
public string OfficeLocation { get; set; }

public string MobilePhoneNumber { get; set; }
public decimal PTORemaining { get; set; }
public decimal PTOAccrualRate { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int ADPFileNumber { get; set; }
public int AirCardLateCheckinCount { get; set; }
public int VehicleLateCheckinCount { get; set; }
public int WexCardDriverID { get; set; }
public int? UpdatedByEmployeeID { get; set; }
public DateTime? DateUpdated { get; set; }

[ForeignKey("ManagerID")]
public Employee Manager { get; set; }

[ForeignKey("UpdatedByEmployeeID")]
public Employee UpdatedBy { get; set; }
}

public class StatusOption
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }

[Required]
public string Name { get; set; }
}

Answer

Since your th2 variable is coming from a left outer join and the corresponding field is non nullable type (like decimal in your case), the easiest (and correct) way is to perform the null check on th2:

HoursWorked2 = th2 == null ? 0 : th2.TotalHoursWorked

Another way which works only with LINQ to Entities (and will generate NullReferenceException in LINQ to Objects) is to use cast to nullable type:

HoursWorked2 = (decimal?)th2.TotalHoursWorked ?? 0
Comments