我有一个来自数据库的查询,我想根据表“ExtraProperties”中的列来过滤查询,该表在 Sql 中以 json 格式编写,但在获取查询时,它会映射到字典
var query = await repository.GetQueryableAsync();
query = query.Where(i => (bool)EF.Property<Dictionary<string, object?>>(i, "ExtraProperties")["AutoGenerated"] == true);
“ExtraPorperties”是属性,“AutoGenerate”是字典上的键,我知道该值的类型是“bool”。 但是这段代码给了我一个错误,说“Linq 查询无法翻译”,所以我的问题是,是否有其他方法可以根据键值字典“ExtraProperties”过滤记录?
请注意,该方法是通用的,C# 无法识别查询内实体内的任何属性。
鉴于
ExtraProperties
是一个 JSON 字符串,您可以尝试进行扩展以将字符串转换为内联字典Convert
:
static partial class Extensions
{
public static Dictionary<string, string> ToDict(this string json) =>
JsonConvert
.DeserializeObject<Dictionary<string, string>>(json ?? string.Empty)
?? new Dictionary<string, string>();
}
你可以这样使用它:
query = query
.Where(record =>
Convert
.ToBoolean(record.ExtraProperties.ToDict()["AutoGenerated"]))
.ToList();
这是我用来测试这个答案的控制台模拟。
using Newtonsoft.Json;
Console.Title = "Test ToDict() Extension";
var query =
Enumerable.Range(0, 10)
.Select(n => new MockItem{Id = n, })
.ToList();
Console.WriteLine($"Total item count = {query.Count}");
query = query
.Where(record => Convert.ToBoolean(record.ExtraProperties.ToDict()["AutoGenerated"]))
.ToList();
Console.WriteLine($"Reduced item count = {query.Count}");
Console.WriteLine(string.Join(Environment.NewLine, query.Select(record=>record.ToString())));
Console.ReadLine();
class MockItem
{
static Random _rando = new Random(1);
public MockItem()
{
// Generate random T/F for property and
// save as json formatted string.
ExtraProperties = JsonConvert.SerializeObject(
new Dictionary<string, object>
{
{ "AutoGenerated", _rando.Next(2).Equals(1) },
});
}
public int Id { get; set; }
public string ExtraProperties { get; }
public override string ToString() =>
$"{Id} ExtraProperties = {ExtraProperties}";
}
static partial class Extensions
{
public static Dictionary<string, string> ToDict(this string json) =>
JsonConvert
.DeserializeObject<Dictionary<string, string>>(json ?? string.Empty)
?? new Dictionary<string, string>();
}