System.Linq.Dynamic.Core
System.Linq.Dynamic.Core copied to clipboard
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