Matthew Verstraete
Matthew Verstraete

Reputation: 6781

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; }
}

Upvotes: 1

Views: 9372

Answers (2)

Ivan Stoev
Ivan Stoev

Reputation: 205579

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

Upvotes: 4

Mrinal Kamboj
Mrinal Kamboj

Reputation: 11482

Decimal is a value type, so it cannot be Null

Your Options:

  1. Redefine TotalHoursWorked as decimal? - Nullable value type, then you can compare to null value

  2. Otherwise, make 0 as 0.0M, so that it can be compared to a decimal type at run-time, else you are comparing with an integer value

Upvotes: 1

Related Questions