0

I'm trying to calculate the hours that fall during the week at a different rate than the ones worked during the weekend. This is how I was hoping to accomplish it:

private void SetTotalCharge()
        {
            int.TryParse(MDate.ToString("MM"), out int month);
            int.TryParse(MDate.ToString("yyyy"), out int year);

            TotalCharge = 
               Decimal.Round(Convert.ToDecimal(db.MyTable
               .Where(a => a.Date <= MDate & a.Date.Month == MDate.Month & (a.Date.Year) == year & (a.Date.DayOfWeek != DayOfWeek.Saturday && a.Date.DayOfWeek != DayOfWeek.Sunday))
               .Select(a => a.RepairHours).Sum() * RateWeek
               + db.MyTable
               .Where(a => a.Date <= MDate & a.Date.Month == MDate.Month & (a.Date.Year) == year & (a.Date.DayOfWeek == DayOfWeek.Saturday && a.Date.DayOfWeek == DayOfWeek.Sunday))
               .Select(a => a.RepairHours).Sum() * RateWeekend), 2, MidpointRounding.AwayFromZero);
        }

The error I'm getting:

System.NotSupportedException: "The specified type member 'DayOfWeek' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."

How can I get around this?

Cosmin
  • 565
  • 1
  • 8
  • 33
  • Does this answer your question? [The specified type member 'Date' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties](https://stackoverflow.com/questions/14601676/the-specified-type-member-date-is-not-supported-in-linq-to-entities-only-init) – Oliver Sep 26 '22 at 23:24
  • @Oliver no, not really. – Cosmin Sep 27 '22 at 21:15

1 Answers1

2

The DayOfWeek enum does not exist on the server side, which is the root cause of the exception. The following are two workarounds to solving the problem. The first uses a list of weekday ordinals (0 and 6), and the second checks the ordinals directly in the conditional (analogous to your original approach).

The examples below work for Entity Framework. For EFCore support, do a find and replace with DbFunctions.DiffDays and EF.Functions.DateDiffDay as the respective criteria.


private void SetTotalCharge()
{
    var dateTime = new DateTime(1899, 12, 31);
    var weekends = new List<int>{ 0, 6 };
    int.TryParse(MDate.ToString("MM"), out int month);
    int.TryParse(MDate.ToString("yyyy"), out int year);

    TotalCharge =
       Decimal.Round(Convert.ToDecimal(db.MyTable
       .Where(a => a.Date <= MDate & a.Date.Month == MDate.Month & (a.Date.Year) == year & !weekends.Any(r => r == DbFunctions.DiffDays(dateTime, a.Updated) % 7))
       .Select(a => a.RepairHours).Sum() * RateWeek
       + db.MyTable
       .Where(a => a.Date <= MDate & a.Date.Month == MDate.Month & (a.Date.Year) == year & weekends.Any(r => r == DbFunctions.DiffDays(dateTime, a.Updated) % 7))
       .Select(a => a.RepairHours).Sum() * RateWeekend), 2, MidpointRounding.AwayFromZero);
}

Or

private void SetTotalCharge()
{
    var dateTime = new DateTime(1899, 12, 31);
    int.TryParse(MDate.ToString("MM"), out int month);
    int.TryParse(MDate.ToString("yyyy"), out int year);

    TotalCharge =
       Decimal.Round(Convert.ToDecimal(db.MyTable
       .Where(a => a.Date <= MDate & a.Date.Month == MDate.Month & (a.Date.Year) == year & ((DbFunctions.DiffDays(dateTime, a.Date) % 7) != 0 && (DbFunctions.DiffDays(dateTime, a.Date) % 7) != 6))
       .Select(a => a.RepairHours).Sum() * RateWeek
       + db.MyTable
       .Where(a => a.Date <= MDate & a.Date.Month == MDate.Month & (a.Date.Year) == year & ((DbFunctions.DiffDays(dateTime, a.Date) % 7) == 0 || (DbFunctions.DiffDays(dateTime, a.Date) % 7) == 6))
       .Select(a => a.RepairHours).Sum() * RateWeekend), 2, MidpointRounding.AwayFromZero);
}
  • 1
    Thank you @Adam for your help. I tried both and couldn't get it to work: 1st approach !weekend is highlighted and says: "int[] does not contain a definition for 'Contains' and the best extension method overload 'Queryable.Contains(IQueryable, DayOfWeek) requires a receiver of type 'IQueryable,DayOfWeek>' 2nd one throws this error " Operator != cannot be applied to operands of type 'DayOfWeek' and 'int' " – Cosmin Sep 27 '22 at 17:24
  • 1
    @Cosmin - Give these a try. I can't test with your code, but it works for me on one of my EFCore contexts. If you need to support dates before 1899-12-31, just pick the earliest Sunday you need. –  Sep 27 '22 at 19:11
  • 1
    @Cosmin - In case you run into issues, are you use EF or EFCore? Just dawned on me that you would need to use DbFunctions if the former. If you have problems, let me know. –  Sep 27 '22 at 21:04
  • I'm using EntityFramework 6.2.0. Could you please modify your answer with the DbFuntion and if it works, then I can accept your solution as the answer? Many thanks. – Cosmin Sep 27 '22 at 21:15
  • I tried with EF.Functions and DbFunctions but it doesn't recognizes any of them. – Cosmin Sep 27 '22 at 21:31
  • I don't have EntityFramework handy, but I think the update I just made should do the trick. If it doesn't work, let me know and I'll figure it out when I get to an old machine later tonight. –  Sep 27 '22 at 21:32
  • 1
    Make sure you've got a a using statement to System.Data.Entity... https://learn.microsoft.com/en-us/dotnet/api/system.data.entity.dbfunctions.diffdays?view=entity-framework-6.2.0 –  Sep 27 '22 at 21:35
  • 1
    The 2nd approach worked smoothly. I appreciate all your support @Adam - you're the best. – Cosmin Sep 27 '22 at 21:47
  • 1
    NP @Cosmin. By second approach, do you mean one of the options in the answer worked and the other didn't? Just want to update the answer for the sake of being a good citizen if so. –  Sep 27 '22 at 21:59
  • Yes, that is correct. The first approach throws 'Cannot convert int? into int'. I'm sure it might be useful for some though. Again, awesome solution! – Cosmin Sep 27 '22 at 22:04
  • 1
    Thanks! Fixed so both work now. Glad I could help. –  Sep 27 '22 at 22:57
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/248395/discussion-between-adam-cohen-and-cosmin). –  Sep 27 '22 at 22:57