我有一个名为 MapInfo 的模型,其中包含 MapTags 字段。
我想带入一个List来查找数据库中是否有匹配的项,就像下面的SQL语法。
select * from "MapInfo"
where "MapInfo"."MapTags" @> ARRAY[0,1000];
我也想使用 LINQ 做同样的事情。
但是当我使用 LINQ 搜索数据时,我收到一条错误消息。
查询码
IQueryable<MapInfo> query = dbContext.MapInfo.AsNoTracking();
// Method 1
query = query.Where(map => map.MapTags != null && param.MapTags.All(tag => map.MapTags.Contains(tag)));
// Method 2
query = query.Where(map => param.MapTags.All(tag => map.MapTags.Any(t => t == tag)));
// Method 3
query = query.Where(map => map.MapTags != null);
foreach (var tag in param.MapTags)
{
query = query.Where(map => map.MapTags.Any(v => v == tag));
}
// Method 4
query = query.Where(map => map.MapTags != null);
foreach (var tag in param.MapTags)
{
query = query.Where(map => map.MapTags.Contains(tag));
}
错误信息
System.InvalidOperationException : The LINQ expression '__param_MapTags_0
.All(e => StructuralTypeShaperExpression:
MapInfo
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
.MapTags
.Contains(e))' could not be translated. Additional information: Translation of method 'System.Linq.Enumerable.Contains' failed.
数据模型
// setting in DbContext
modelBuilder.Entity<MapInfo>().Property(e => e.MapTags).HasConversion<List<int>>();
[Serializable]
public class MapInfo
{
[Key]
public Guid Guid { get; set; }
[Required]
public string UserId { get; set; } = null!;
public string Title { get; set; } = null!;
public List<MapTag> MapTags { get; set; }
public DateTime CreatedAt { get; set; }
}
public enum MapTag
{
Group1 = 1000,
Group2 = 1001,
Group3 = 1002,
}
尝试了很多方法查询还是失败。
我还阅读了https://www.npgsql.org/efcore/mapping/array.html并且
array1.All(i => array2.Contains(i))
应该可以工作。
我的代码或设置有什么问题吗?
更新
我发现模型设置错误。 正确的设置List方式是
modelBuilder.Entity<MapInfo>(info =>
{
info.PrimitiveCollection(c => c.MapTags).ElementType(e => e.HasConversion(typeof(EnumToNumberConverter<MapTag, int>)));
});
最后是框架版本问题导致的。
当我使用 EF CORE 8.0.1时它可以工作。
但升级到8.0.4后就不能再使用了。
我不确定这是 EFCORE 问题还是 Npgsql 问题。
我会向他们提出问题。