From f6988cd55a3e87ca723f59cd8c8a36968b4495d6 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Wed, 11 May 2022 14:04:23 -0700 Subject: [PATCH] Query: Use type mapping from IDbFunction while translating (#27995) Resolves #27954 Resolves #27524 --- .../RelationalMethodCallTranslatorProvider.cs | 6 ++- .../Query/SimpleQueryRelationalTestBase.cs | 52 +++++++++++++++++++ .../Query/SimpleQuerySqlServerTest.cs | 18 +++++++ 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs index c6cbb1598ed..ca8ba28bd61 100644 --- a/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs +++ b/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs @@ -81,14 +81,16 @@ public RelationalMethodCallTranslatorProvider(RelationalMethodCallTranslatorProv arguments, dbFunction.IsNullable, argumentsPropagateNullability, - method.ReturnType.UnwrapNullableType()) + method.ReturnType.UnwrapNullableType(), + dbFunction.TypeMapping) : _sqlExpressionFactory.Function( dbFunction.Schema, dbFunction.Name, arguments, dbFunction.IsNullable, argumentsPropagateNullability, - method.ReturnType.UnwrapNullableType()); + method.ReturnType.UnwrapNullableType(), + dbFunction.TypeMapping); } return _plugins.Concat(_translators) diff --git a/test/EFCore.Relational.Specification.Tests/Query/SimpleQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/SimpleQueryRelationalTestBase.cs index cdb443edeae..b6777516a13 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/SimpleQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/SimpleQueryRelationalTestBase.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; +using System.ComponentModel.DataAnnotations.Schema; using NameSpace1; namespace Microsoft.EntityFrameworkCore.Query @@ -49,6 +51,56 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) mb.ToTable((string)null); } } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task StoreType_for_UDF_used(bool async) + { + var contextFactory = await InitializeAsync(); + using var context = contextFactory.CreateContext(); + + var date = new DateTime(2012, 12, 12); + var query1 = context.Set().Where(x => x.SomeDate == date); + var query2 = context.Set().Where(x => MyEntity.Modify(x.SomeDate) == date); + + if (async) + { + await query1.ToListAsync(); + await Assert.ThrowsAnyAsync(() => query2.ToListAsync()); + } + else + { + query1.ToList(); + Assert.ThrowsAny(() => query2.ToList()); + } + } + + protected class Context27954 : DbContext + { + public Context27954(DbContextOptions options) + : base(options) + { + } + + public DbSet MyEntities { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder + .HasDbFunction(typeof(MyEntity).GetMethod(nameof(MyEntity.Modify))) + .HasName("ModifyDate") + .HasStoreType("datetime") + .HasSchema("dbo"); + } + } + + protected class MyEntity + { + public int Id { get; set; } + [Column(TypeName = "datetime")] + public DateTime SomeDate { get; set; } + public static DateTime Modify(DateTime date) => throw new NotSupportedException(); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs index b0255e10d1b..8a9abf8b137 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs @@ -391,4 +391,22 @@ WHERE [c].[SomeNullableDateTime] IS NULL ) AS [t0] ON [p].[Id] = [t0].[ParentId] WHERE [t0].[SomeOtherNullableDateTime] IS NOT NULL"); } + + public override async Task StoreType_for_UDF_used(bool async) + { + await base.StoreType_for_UDF_used(async); + + AssertSql( + @"@__date_0='2012-12-12T00:00:00.0000000' (DbType = DateTime) + +SELECT [m].[Id], [m].[SomeDate] +FROM [MyEntities] AS [m] +WHERE [m].[SomeDate] = @__date_0", + // + @"@__date_0='2012-12-12T00:00:00.0000000' (DbType = DateTime) + +SELECT [m].[Id], [m].[SomeDate] +FROM [MyEntities] AS [m] +WHERE [dbo].[ModifyDate]([m].[SomeDate]) = @__date_0"); + } }