Skip to content

Add support for AT TIME ZONE #26199

Description

@omfgicbf

I'm trying to use HasDbFunction and HasTranslation to make use of the SQL AT TIME ZONE clause.

I have the following in OnModelCreating:

var methodInfo = typeof(Extensions).GetMethod(nameof(Extensions.ToTimeZone));

static string DelimitIdentifier(string identifier) => $"[{identifier.Replace("]", "]]")}]";

modelBuilder
    .HasDbFunction(methodInfo)
    .HasTranslation(x =>
    {
        var columnExpression = x.First() as ColumnExpression;

        var timeZoneExpression = x.Skip(1).First() as SqlConstantExpression;

        var columnIdentifier = $"{DelimitIdentifier(columnExpression.Table.Alias)}.{DelimitIdentifier(columnExpression.Name)}";

        var expression = new SqlFragmentExpression($"{columnIdentifier} AT TIME ZONE {timeZoneExpression.TypeMapping.GenerateSqlLiteral(timeZoneExpression.Value)}");

        Console.WriteLine($"Translation => {expression.Sql}");

        return expression;
    });

Which is intended to translate calls to the following extension method:

public static DateTimeOffset ToTimeZone(this DateTimeOffset value, string name)
    => throw new NotImplementedException("This should be implemented in HasDbFunction.");

If I try to query using this extension method like this:

var foos = from f in context.Foos
           select new
           {
               Created = f.Created.ToTimeZone("E. Australia Standard Time")
           };

Instead of the ToTimeZone method being translated, the method itself seems to be called and I get the following exception:

Unhandled exception. System.NotImplementedException: This should be implemented in HasDbFunction.
MRE.EFCore5.HasDbFunction.Extensions.ToTimeZone(System.DateTimeOffset, string) in Extensions.cs
Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable<T>.Enumerator.MoveNext() in SingleQueryingEnumerable.cs
MRE.EFCore5.HasDbFunction.Program.Main(string[]) in Program.cs

Even though the call to ToTimeZone isn't translated, the translation itself is being called (twice) and is generating the correct SQL fragment, however, the fragment is not included in the query and the exception from the extension method is thrown.

There is a minimal reproducible example here.

Technical Details

EF Core version: 5.0.10
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5.0
Operating system: Windows 10
IDE: Visual Studio 2019 16.11.3

Metadata

Metadata

Assignees

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions