ra0o0f / arangoclient.net

ArangoDB .NET Client with LINQ support
Apache License 2.0
99 stars 37 forks source link

OData support #40

Open adamlubek opened 8 years ago

adamlubek commented 8 years ago

hey, we are trying to use library with OData WebApi controllers. It partially works for some of the OData query options but some are throwing exceptions.

Let's say we have following People collection in arango db:

[{"Id":1,"LastName":"a"},{"Id":2,"LastName":"b"},{"Id":3,"LastName":"c"}]

then, in C# we have

[CollectionProperty(CollectionName = "People")] public class Person { [Key] public int Id { get; set; } public string LastName { get; set; } }

which we expose on OData controller as

    [HttpGet]
    [EnableQuery]
    public IHttpActionResult Get(ODataQueryOptions<Person> queryOptions)
    {
        var db = new ArangoDatabase("http://127.0.0.1:8529", "DBName");
        IQueryable<Person> people= db.Query<Person>();

        return Ok(people);
    }

This works fine with OData top/skip/orderby query options e.g. http://localhost/people?$top=2&$skip=1$orderby=LastName

but we get exceptions when using other OData query options like count or select e.g

Count: OData query is: http://localhost/people?$count=true

exception is:

{ "message": "Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Int64' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly.\r\nTo fix this error either change the JSON to a JSON primitive value (e.g. string, number, boolean, null) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.\r\nPath 'Id', line 1, position 17.", "type": "ArangoDB.Client.Common.Newtonsoft.Json.JsonSerializationException",

When stepping through the code I got to the point which causes exception and same exception could be replicated by trying to execute following query:

db.Query().LongCount();

so it looks like LongCount() not working properly is root cause of this particular issue?

Select OData query is: http://localhost/people?$select=LastName

and exception is: "The expression 'IIF(([_1] == null), null, Convert([_1].Id))' (type: System.Linq.Expressions.ConditionalExpression) is not supported by ArangoDB LINQ provider."

Are we missing something or is OData not fully supported? I didn't paste in full stack traces as they're lengthy but let me know if you want it and I'll supply them.

ra0o0f commented 8 years ago

@adamlubek sorry for the delay i didn't test the client with the odata yet, i tested your code:

as you mentioned LongCount was not supported by linqprovider, it is now(in the source code, nuget packages will be updated soon). so http://localhost/people?$count=true should works now.

odata $select uses a IIF method for resolving members, that's why it's not supported by linqprovide, it wont be a quick fix to support it. i should look into it.

support for the OData would be a great feature, i will work more on it. but for now maybe you cant write all filters that you want, open a new issue for other failing filters

a note about client linq provider: it does not support all linq methods yet, the reason is methods like Any, All has no equivalent aql syntax or functions. however it should be an aql query( much uglier than db.Query.Any ) that can produce same result.

adamlubek commented 8 years ago

Many thanks for fix, that's really helpful :)