首页 > 解决方案 > 如何使用 EF Core 2.2 将 JSON_VALUE 转换为 DateTime?

问题描述

我正在使用How to write DbFunction's translationJSON_VALUE中的技术进行映射。由于并非 JSON 中的所有值都是字符串,因此有时需要进行转换。

转换为 时int,一切都很好:

var results = context.Set<SampleTable>()
    .Where(t1 => Convert.ToInt32(
        JsonExtensions.JsonValue(t1.SampleJson, "$.samplePath.sampleInt")) > 1);
    .ToList();

生成的 SQL 是:

SELECT *
FROM [SampleTable] AS [t1]
WHERE (CONVERT(int, JSON_VALUE([t1].[SampleJson], N'$.samplePath.sampleInt')) > 1)

但是,当转换为 时DateTime,它不起作用:

DateTime date = new DateTime(2019, 6, 1);
var results = context.Set<SampleTable>()
    .Where(t1 => Convert.ToDateTime(
        JsonExtensions.JsonValue(t1.SampleJson, "$.samplePath.sampleDate")) >= date);
    .ToList();

不是被映射,而是JsonValue直接调用,这会导致以下异常:

System.NotSupportedException HResult=0x80131515 消息=不支持指定的方法。StackTrace:在 JsonExtensions.JsonValue(String column, String path) at System.Linq.Enumerable.WhereEnumerableIterator 1.MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.<_TrackEntities>d__172.MoveNext() 在 Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()

为什么DateTime行为与 不同int?我该怎么做才能DateTime正常工作?

标签: c#jsonsql-serverentity-framework-coreef-core-2.2

解决方案


问题是并非所有Convert方法都受支持。

事实上,它们都不受标准支持 - EF Core 允许数据库提供者添加 CLR 方法和成员翻译器以用于他们喜欢的任何内容。例如 SqlServer 提供程序当前支持 ToByteToDecimalToDoubleToInt16ToInt32和。ToInt64ToString

这意味着没有数据库不可知的方式来执行服务器端转换。

由于您似乎正在使用 SqlServer,作为解决方法,我可以建议通过使用我对类似帖子的回答中的“双重转换”技术来利用隐式数据转换(目前由 SqlServer 提供程序支持),例如

.Where(t1 => (DateTime)(object)JsonExtensions.JsonValue(t1.SampleJson, "$.samplePath.sampleDate") >= date);

(object)cast 用于避免 C# 编译器错误。在查询转换期间,两个强制转换都将被删除,SQL Server 隐式数据转换最终将完成这项工作。


推荐阅读