bde*_*ere 5 c# entity-framework-core
我们有一个列,其中JSON数据存储为字符串.读取此JSON数据并通过实现将其转换为IDictionary<string, object>.这一切都正常,直到我想要过滤它.仅在从数据库获取数据后才应用过滤.我们将拥有数百万条记录,因此这是不可接受的.我的过滤器被EF Core完全忽略为WHERE子句,因为它可能不知道如何解析MethodCallExpressions.
我正在寻找一种方法来尽可能接近我在下面使用表达式树的SQL查询.
我需要转换这个:
.Call System.Linq.Queryable.Where(
.Constant<QueryTranslator`1[Setting]>(QueryTranslator`1[Setting]),
'(.Lambda #Lambda1<System.Func`2[Setting,System.Boolean]>))
.Lambda #Lambda1<System.Func`2[Setting,System.Boolean]>(Setting $$it)
{
((System.Nullable`1[System.Int32]).If (
$$it.Value != null && .Call ($$it.Value).ContainsKey("Name")
) {
($$it.Value).Item["Name"]
} .Else {
null
} > (System.Nullable`1[System.Int32]).Constant<Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Int32]>(Microsoft.AspNet.OData.Query.Expressions.LinqParameterContainer+TypedLinqParameterContainer`1[System.Int32]).TypedProperty)
== .Constant<System.Nullable`1[System.Boolean]>(True)
}
Run Code Online (Sandbox Code Playgroud)
进入:
SELECT *
FROM [Setting]
WHERE JSON_VALUE([Value], 'lax $.Name') > 1; -- [Value_Name] > 1 is also fine
Run Code Online (Sandbox Code Playgroud)
随着ExpressionVisitor我已经成功地得到尽可能靠近WHERE [超值] ="东西",但字符串这只是工作和键名是缺乏.
在获得"官方"支持之前,您可以JSON_VALUE使用EF Core 2.0引入的数据库标量函数映射进行映射.
例如,在上下文派生类中或在单独的静态类中添加以下静态方法,如下所示:
public static class MyDbFunctions
{
[DbFunction("JSON_VALUE", "")]
public static string JsonValue(string source, string path) => throw new NotSupportedException();
}
Run Code Online (Sandbox Code Playgroud)
如果它在单独的类中,请将以下内容添加到上下文OnModelCreating覆盖中(如果方法在上下文中则不需要):
modelBuilder.HasDbFunction(() => MyDbFunctions.JsonValue(default(string), default(string)));
Run Code Online (Sandbox Code Playgroud)
现在,您可以在LINQ to Entities查询中使用它EF.Functions.请注意该函数返回string,因此为了欺骗编译器将其"转换"为数字,您可以使用下面显示的双重投射技术(在EF Core 2.1.2中测试和工作):
var query = db.Set<Setting>()
.Where(s => (int)(object)MyDbFunctions.JsonValue(s.Value, "lax $.Name") > 1);
Run Code Online (Sandbox Code Playgroud)
这转化为所需的
WHERE JSON_VALUE([Value], 'lax $.Name') > 1
Run Code Online (Sandbox Code Playgroud)
另一种(可能类型更安全)执行转换的Convert方法是使用类方法(SqlServer EF Core提供程序令人惊讶地支持):
var query = db.Set<Setting>()
.Where(s => Convert.ToInt32(MyDbFunctions.JsonValue(s.Value, "lax $.Name")) > 1);
Run Code Online (Sandbox Code Playgroud)
转化为
WHERE CONVERT(int, JSON_VALUE([Value], 'lax $.Name')) > 1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
643 次 |
| 最近记录: |