efcore: EF Core 3.0 DateTimeOffset.Date comparison inconsistent between client and server side evaluation.

When comparing against the DateTimeOffset.Date property, we’re seeing inconsistent results on client side vs server side evaluation.

Steps to reproduce

Given the entity:

    public partial class PreHire
    {
        public int PreHireId { get; set; }
        public DateTimeOffset StartDate { get; set; }
    }

And the following logic:

        DateTime startDate = DateTime.Now;

	//Pulls preHire with a start date of '2019-11-25 14:42:54.0833333 +00:00'
	PreHire clientComparePreHire = context.PreHire.Where(x => x.PreHireId == 22407).FirstOrDefault();
	if(clientComparePreHire.StartDate.Date >= startDate.Date)
	{
		Console.WriteLine("This works.");
	}

	List<PreHire> serverComparePreHires = context.PreHire.Where(q => q.StartDate.Date >= startDate.Date).ToList();
         if(serverComparePreHires.Count == 0)
         {
                 Console.WriteLine("This doesn't. This shouldn't be empty.");
         }

We get the following logs:

info: Microsoft.EntityFrameworkCore.Database.Command[20100]
      Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT TOP(1) [p].[PreHireID], [p].[StartDate]
      FROM [TBL].[PreHire] AS [p]
      WHERE [p].[PreHireID] = 22407
This works.
info: Microsoft.EntityFrameworkCore.Database.Command[20100]
      Executing DbCommand [Parameters=[@__startDate_Date_0='2019-11-25T00:00:00' (DbType = DateTimeOffset)], CommandType='Text', CommandTimeout='30']
      SELECT [p].[PreHireID], [p].[StartDate]
      FROM [TBL].[PreHire] AS [p]
      WHERE CONVERT(date, [p].[StartDate]) >= @__startDate_Date_0
This doesn't. This shouldn't be empty.

This shows that serverComparePreHires is empty, but if I run the above query manually I get my expected result:

	SELECT [p].[PreHireID], [p].[StartDate]
	FROM [TBL].[PreHire] AS [p]
	WHERE CONVERT(date, [p].[StartDate]) >= '2019-11-25T00:00:00'

PreHireID	StartDate
22407	2019-11-25 14:42:54.0833333 +00:00

To summarize, When processing this specific linq query server side, EF Core generates a valid SQL Query but fails to return the matching PreHire entry.

Further technical details

EF Core version: 3.0.0 (Same result with 3.0.1) Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.0 (Migrating from 2.1) Operating system: Windows 10 IDE: Visual Studio 2019 16.3.7

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 21 (10 by maintainers)

Commits related to this issue

Most upvoted comments

We also ran into this issue, in migrating. Removing .Date worked for us. It seems in your case this is a business rule to get the Current Date the Employee or Prehire Started? You would expect .Date to evaluate correctly. That’s interesting that EFCore generated a query, that works when you execute it. I suspect you didn’t see this before, because client side evaluation is turned off now.

If this isn’t a bug, its some weird obscure thing EF does for you. Waiting for the EFCore team to respond 😃

Thank you everyone for looking into this, and @smitpatel for the fix! Do we have a time frame as to when this fix would be released? Hopefully not 5.0.0.

The issue is following https://github.com/aspnet/EntityFrameworkCore/blob/098785af82c52edeee8ff5c262a8c7e53b9655c5/src/EFCore.SqlServer/Query/Internal/SqlServerDateTimeMemberTranslator.cs#L59-L64

DateTimeOffset.Date returns a datetime but we are incorrectly assigning typeMapping as DateTimeOffset. When we generate the parameter for it, it contains offset but by using date on server side, offset was removed. (SqlServer upcast everything to datetimeoffset(7) when comparing) So we are comparing 2 same date but one has offset and other one does not so they fail comparison based on offset’s direction.

@AlbertoMonteiro 3.1.3 is tentatively scheduled for later this month.