使用 Entity Framework Core 在 LINQ 查询中将字符串转换为日期时间

AFr*_*act 1 c# linq sql-server date entity-framework-core

使用 EF Core 5 和 SQL Server,我试图弄清楚如何转换存储为 LINQ 查询中的字符串的日期(在 SQL Server 端)。

我已经搜索过,EF.Functions但我无法找到这种日期解析的正确方法。

我也试过Convert.ToDateTimeand DateTime.Parse,但它们似乎都没有 LINQ 翻译。

直接的 SQL 等效项是Convert(datetime, mycolumn, 102). 如果微软没有做任何事情来支持像原生 SQL 这样简单易用的东西,我会很惊讶,所以如果我错过了一些明显的东西,我很抱歉,但我已经在网上搜索过,并在投降之前做了一些尝试。

PS:请注意,我知道在应用 Where() 或修改数据库(或创建视图)以更改列类型之前调用 ToList() 等解决方法。

我的问题主要是:如何用EF调用 Convert(datetime, mycolumn, 102)

Iva*_*oev 6

您可以使用 EF Core 标量函数映射相对轻松地添加所需的不受支持的方法。

例如,添加以下类(使用必要的用途):

namespace Microsoft.EntityFrameworkCore
{
    public static class SqlFunctions
    {
        public static DateTime? ToDateTime(this string s, int format) => throw new NotSupportedException();

        public static ModelBuilder AddSqlFunctions(this ModelBuilder modelBuilder)
        {
            modelBuilder.HasDbFunction(() => ToDateTime(default, default))
                .HasTranslation(args => new SqlFunctionExpression(
                    functionName: "CONVERT",
                    arguments: args.Prepend(new SqlFragmentExpression("date")),
                    nullable: true,
                    argumentsPropagateNullability: new[] { false, true, false }),
                    type: typeof(DateTime),
                    typeMapping: null));

            return modelBuilder;
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

第二种方法是为了方便起见并进行实际映射。

现在您只需要从OnModelCreating覆盖调用它:

if (Database.IsSqlServer()) modelBuilder.AddSqlFunctions();

Run Code Online (Sandbox Code Playgroud)

然后在 LINQ to Entities 查询中使用它:

var query = db.Set<MyEntity>()
    .Where(e => e.MyProp.ToDateTime(102) > DateTime.Today
    .ToQueryString();
// SELECT ..... WHERE Convert(date, [e].[MyProp], 102) > CONVERT(date, GETDATE())
Run Code Online (Sandbox Code Playgroud)


AFr*_*act 6

谈到奇怪的解决方案,我注意到使用

(DateTime)(object)t.Date 
Run Code Online (Sandbox Code Playgroud)

在查询中完成这项工作。

例如 :

dbContext.Table.Max(t => (DateTime)(object)t.Date);
Run Code Online (Sandbox Code Playgroud)

会完美工作。我想这背后有一些黑魔法,它只适用于大多数“直接”日期格式和文化转换。稍后我将使用 SQL 探查器或其他解决方案检查它发出的 SQL 类型。

  • 是的,我所说的“双重转换技巧”(您可以在我的其他帖子中找到它)是另一种(也是更通用的)方法,它转换为 SqlServer *default* 数据​​类型转换,通常可能不是格式将数字/日期/时间数据存储为文本时使用。 (2认同)