Problem with Query over JObject, Filter with SubProperty not returning the correct value
I created this console application to reproduce my problem
static void Main(string[] args)
{
var obj = new object[] {
new { Id= 36,
Descricao= "Responsiva",
Tipo=new { Id= "1" },TipoId= "1" ,
Custo= 160
},
new {
Id= 31,
Descricao= "Log",
Tipo= new { Id= "1" },TipoId= "1" ,
Custo= 0
},
new {
Id= 32,
Descricao= "Multi-Idioma",
Tipo= new { Id= "2" },TipoId= "2" ,
Custo= 2
},
new {
Id= 33,
Descricao= "Tela Administrativa",
Tipo= new { Id= "2" },TipoId= "2" ,
Custo= 8
}
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
var dados = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject[]>(json);
var retorno = dados.AsQueryable()
.Select("new ( string(Id) as Id, string(Descricao) as Descricao,new ( string(Id) as Id) as Tipo, string(TipoId) as TipoId, string(Custo) as Custo)");
retorno = retorno.OrderBy("Descricao asc");
var retorno1 = retorno.Where("(TipoId = @0)", "1");
var retorno2 = retorno.Where("(Tipo.Id = @0)", "1");
Console.WriteLine(retorno.Count());
Console.WriteLine(retorno1.Count());
Console.WriteLine(retorno2.Count());
Console.ReadLine();
}
If you look at the results , the count should be the same, but for some reason, retorno2 is filtering for the Root Id of the object, and not the Tipo property and Id SubProperty
Hello @luizfbicalho ,
It's possible that new ( string(Id) as Id) as Tipo should be instead new ( string(Tipo.Id) as Id) as Tipo ?
var retorno = dados.AsQueryable()
.Select("new ( string(Id) as Id, string(Descricao) as Descricao,new ( string(Tipo.Id) as Id) as Tipo, string(TipoId) as TipoId, string(Custo) as Custo)");
Once we change it, it now filters the Tipo.Id as you initially wanted.
Best Regards,
Jon
Performance Libraries
context.BulkInsert(list, options => options.BatchSize = 1000);
Entity Framework Extensions • Entity Framework Classic • Bulk Operations • Dapper Plus
Runtime Evaluation
Eval.Execute("x + y", new {x = 1, y = 2}); // return 3
C# Eval Function • SQL Eval Function
Thanks @JonathanMagnan , I'll try that.
One thing before closing this If I remove the line
.Select("new ( string(Id) as Id, string(Descricao) as Descricao,new ( string(Id) as Id) as Tipo, string(TipoId) as TipoId, string(Custo) as Custo)");
Shoudn't it work inspecting the JObject? I changed it to dynamic and received this
"Target object is not an ExpandoObject"
Unfortunately, the library is not 100% compatible with JObject.
So the answer is no for the moment.
We might want to improve the code later to try to support more but there is no plan for now.
I didn't look deeply inside of the code, but is there some kind of translator that I could implement, for example There is a object to where that translates the objects properties to the where string, and I could implement one translator of JObject to where, and even one from dynamic to Where
I'm not sure if I was clear about it
I'm not exactly sure but this answer might help you: https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/410#issuecomment-678825890
This is possible for you to add some method that will be recognized by the library
I was thinking about something more transparent, I mean something like this
IReader<T>{GetProperties(T obj).......}
and in Where("t=>t.Property==@0",X) would use the DI or some array of readers kind of the way newtonsoft.json has the converters.
I imagine that this is a huge change in the way that this works today, if so, I'm just pointing some ideas to help in the future
I was more thinking in this direction:
Use it:
var array = JArray.Parse(@"[
{
""first"": 1,
""City"": ""Paris"",
""third"": ""test""
},
{
""first"": 2,
""City"": ""New York"",
""third"": ""abc""
}]");
var results = array.Where("City == @0", "Paris").ToDynamicArray();
foreach (var result in results)
{
Console.WriteLine(result.first);
}
Logic
public static JArray Where(this JArray source, JsonParsingConfig config, string predicate, params object?[] args)
{
Check.NotNull(source);
var array = new JArray();
if (source.Count == 0)
{
return array;
}
// Convert the JArray to a dynamic object array / queryable.
var enumerable = source.ToDynamicJsonClassArray(config.DynamicJsonClassOptions).AsQueryable();
// Apply the where clause.
var results = enumerable.Where(config, predicate, args);
// Convert the dynamic results back to a JArray.
foreach (var result in results)
{
array.Add(JObject.FromObject(result));
}
return array;
}
Will be solved by https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/789