如何使用实体框架解析linq中的文本json

问题描述 投票:0回答:1

我有一个表

SliceStatements
(数据库:PostgreSQL),其中包含字段
Payload
。该字段的类型是
String
,但字符串是json格式。 json 具有字段
rows
,它是一个对象数组。已知每个物体都有场
locationM

我需要编写一个 linq 查询来获取前 1000 行 json 对象(不是 SliceStatements),按

locationM
排序。

我知道我可以通过首先使用

asEnumerable
或类似的东西加载数据来轻松完成此操作,但是数据太多,应用程序会因
OutOfMemoryException
而崩溃。

那么我该如何编写 linq 查询呢?

这是我的代码:

await _context.SliceStatements.AsNoTracking()
            .SelectMany(s => (JArray)JObject.Parse(s.Payload)["rows"], (s, row) => new { row })
            .OrderBy(r => r["locationM"])
            .Take(1000)
            .ToListAsync();

可悲的是,

The LINQ expression 's => (JArray)JObject.Parse(s.Payload).get_Item("rows")' could not be translated.

我知道我可以通过

fieldName::json
使用 SQL 查询将文本解析为 json,但我不知道如何使用 linq 来做到这一点。

我不想将整个查询写成 SQL,因为我的代码占整个查询的 10%,其中包含多个 Join 和Where。

c# json postgresql entity-framework linq
1个回答
0
投票

您遇到“无法翻译 LINQ 表达式”错误的原因是 Entity Framework Core (EF Core) 无法将 JObject.Parse 方法转换为 SQL。结果,查询无法在数据库端执行,EF Core 会尝试在内存中执行,从而导致 OutOfMemoryException 问题。

要克服这个问题,您需要找到一种替代方法,允许 EF Core 将查询转换为 SQL。实现此目的的一种方法是使用 EF Core for PostgreSQL 中提供的 EF.Functions.JsonbArrayElements 方法。

假设您使用 EF Core 5.0 或更高版本,您可以像这样重写 LINQ 查询:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;

// ...

var query = _context.SliceStatements.AsNoTracking()
    .SelectMany(s => EF.Functions.JsonbArrayElements(s.Payload)["rows"], (s, row) => new { row })
    .OrderBy(r => r.row["locationM"])
    .Take(1000);

var result = await query.ToListAsync();

在上面的代码中,我们使用 EF.Functions.JsonbArrayElements 方法从 JSON 中的“rows”数组中提取元素,这相当于原始代码中的 JArray。这种方法可以翻译成SQL,让EF Core在数据库端处理查询,避免内存问题。

请确保包含必要的 using 指令,并确保您使用的是 EF Core 5.0 或更高版本,并安装了 Npgsql.EntityFrameworkCore.PostgreSQL 包以支持 PostgreSQL。

© www.soinside.com 2019 - 2024. All rights reserved.