[英].NET Core Npgsql.EntityFrameworkCore ILikeExpression
[英]How to query against a column that has a JSON Array in Npgsql.EntityFrameworkCore
笔记:
它有两列:
Car 类看起来像这样:
public class Car
{
public string LicenseNumber {get;set;}
public List<Kitchen> KitchenIntegrations {get;set;}
}
Kitchen.cs 看起来像这样:
public class Kitchen
{
public int Id {get;set;}
public string KitchenName {get;set;}
}
最后我的 CarContext.cs 看起来像这样:
public class CarContext : DbContext
{
public DbSet<Car> Cars { get; set; }
public CarContext()
{
}
public CarContext(DbContextOptions<CarContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql("ConnectionStringGoesHere");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("public");
modelBuilder.Entity<Car>(
builder =>
{
builder.HasKey(i => i.LicenseNumber);
builder.Property(i => i.KitchenIntegrations).HasColumnType("jsonb").IsRequired(false);
}
);
}
}
在Cars表中,我只需要获取 Id = 1 的 KitchenIntegration。
我可以在 PSQL 中轻松完成此操作,但是在尝试查询 JSON 数组时遇到问题。
我试过:
var integrations = context.Cars.Select(i => i.KitchenIntegrations.First(o => o.Id == 1)).ToList();
但是遇到无法转换为 SQL/PSQL 的问题。
所以我的问题是如何遍历 EntityFrameworkCore 中的 JSON 数组或列表? (如果可能的话,只将它作为服务器端而不是客户端来做)。
谢谢! 任何帮助是极大的赞赏!
我的 2 美分。 假设您有一个具有以下结构的桌子fixtures
。 (Id, JsonProperty)
。 假设您在数据库中有一条像这样的记录。
1, [{"Name": "Test", "Value": "123"}, {"Name": "Test2", "Value": "pesho"}]
2, [{"Name": "Test", "Value": "321"}, {"Name": "Test2", "Value": "pesho"}]
3, [{"Name": "Test", "Value": "1123"}, {"Name": "Test2", "Value": "pesho"}]
然后使用EF Core 3.1
和Npgsql.EntityFrameworkCore.PostgreSQ 3.14
你可以这样做:
var search = "[{\"Value\": \"123\"}]";
var result = dbContext.Fixtures
.FirstOrDefault(s => EF.Functions.JsonContains(s.JsonProperty, search));
var search2 = "[{\"Name\": \"Test\"}]";
var multipleResults = dbContext.Fixtures
.Where(s => EF.Functions.JsonContains(s.JsonProperty, search2));
我认为这是因为 Entity Framework Core 中的延迟加载。
这可以通过var integrations = context.Cars.Select(c => c.KitchenIntegrations).Select(l => l.First(o => o.Id == 1)).ToList();
. 它会抛出:
从“VisitLambda”调用时,重写“System.Linq.Expressions.ParameterExpression”类型的节点必须返回相同类型的非空值。 或者,覆盖“VisitLambda”并将其更改为不访问此类子项。
但是,我尝试使用var integrations = context.Cars.Include(c => c.KitchenIntegrations).ToList();
Eager Loading (和ThenInclude
),但它抛出错误:
Include 中使用的 Lambda 表达式无效。
我必须将所有Cars
预加载到内存中才能使其工作:
var integrations = context.Cars
.ToList() // Eager load to memory
.Select(i => i.KitchenIntegrations.First(o => o.Id == 1))
.ToList();
我觉得应该有一种更好(或更正确)的方式来进行急切加载。
(当前)不支持将其转换为 SQL - 对数据库 JSON 列的操作是有限的,请参阅文档以获取支持的翻译列表。
在这种特殊情况下,不清楚如何(有效)将其转换为 SQL。 有关类似问题,请参阅https://github.com/npgsql/efcore.pg/issues/1534 。
您确实可以按照@han-zhao 的建议在客户端执行投影。 但是,使用 AsEnumerable 来触发客户端评估而不是 ToList:
var integrations = context.Cars
.AsEnumerable()
.Select(i => i.KitchenIntegrations.First(o => o.Id == 1))
.ToList();
这确实具有下载大量不需要的厨房实例的缺点,只是在客户端将它们过滤掉。 如果在性能上有问题,请考虑使用原始 SQL (尽管同样,您想要做的并不是微不足道的)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.