EF Core 3.1 无法查询 Json 序列化对象

EF Core 3.1 Fail to query on Json Serialized Object

我使用 json 序列化将列表存储在字段中的 ids

型号:

public class Video
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual IList<int> AllRelatedIds { get; set; }
}

上下文:

modelBuilder.Entity<Video>(entity =>
{
    entity.Property(p => p.AllRelatedIds).HasConversion(
    v => JsonConvert.SerializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
    v => JsonConvert.DeserializeObject<IList<int>>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore })
    );
});

它工作正常,添加、编辑、删除项目很容易,在 SQL 数据库中它存储为 json 就像
[11000,12000,13000]

一切都很好但是!!一旦想查询此列表,我就会收到奇怪的回复。

其中:

_context.Set<Video>().Where(t=>t.AllRelatedIds.contains(11000)) returns null 但是如果我要求 return 所有 AllRelatedIds 项目一些记录有 11000 值 exp.

计数:

_context.Set<Video>().Count(t=>t.AllRelatedIds.contains(11000)) returns 无法翻译。以可以翻译的形式重写查询,或者通过插入对 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync() 的调用来显式切换到客户端评估。

EF Core 怎么了?我什至测试了 t=>t.AllRelatedIds.ToList().contains(11000) 但没有任何区别

我该怎么办?我不想有更多的表,我使用这种方法数百次,但似乎从未对它们进行过查询。

Json Serialization/Deserialization 发生在应用程序级别。 EF Core 将 IList<int> 对象序列化为值 [11000,12000,13000] ,然后 将其发送到数据库进行存储,并将值 [11000,12000,13000] 反序列化为 IList<int>对象 after 从数据库中检索它。数据库内部什么也没有发生。您的数据库无法将 [11000,12000,13000] 作为数字集合进行操作。对于数据库来说,就是一条数据。

如果您尝试以下查询 -

var videos = _context.Set<Video>().ToList();
var video = _context.Set<Video>().FirstOrDefault(p=> p.Id == 2);

你会得到预期的结果,EF Core 正在完美地完成它的工作。

问题是,当您查询类似 -

的内容时
_context.Set<Video>().Where(t=> t.AllRelatedIds.Contains(11000))

EF Core 无法将 t.AllRelatedIds.Contains(11000) 部分转换为 SQL。 EF Core 只能 serialize/deserialize 因为你告诉它(以及如何)。但正如我上面所说,您的数据库不能将 [11000,12000,13000] 作为整数集合进行操作。因此 EF Core 无法将 t.AllRelatedIds.Contains(11000) 转换为对数据库有意义的任何内容。

一个解决方案是获取所有视频的列表,以便 EF Core 可以将 AllRelatedIds 反序列化为 IList<int>,然后您可以对其应用 LINQ -

var allVideos = _context.Set<Video>().ToList();
var selectedVideos = allVideos.Where(t=> t.AllRelatedIds.Contains(11000)).ToList();

但不是每次都获取所有视频 unnecessary/overkill 还是从性能角度来看效率低下?是的当然。但正如评论所暗示的那样,您的数据库 design/usage 方法存在一些缺陷。