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 方法存在一些缺陷。
我使用 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 方法存在一些缺陷。