ra0o0f / arangoclient.net

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

Error in generated AQL when upserting a generic document #124

Open isen-ng opened 5 years ago

isen-ng commented 5 years ago

I'm trying to upsert a document that involves a generic. The document collection has not been created yet, and I assume the collection will be automatically created like in the Insert method (please correct me if I'm wrong).

This is the code I have:

private async Task<TState> Store(string key, TState state)
{
    using (var db = _arangoDb.CreateWithSetting())
    {
        var wrapped = Wrapper.Wrap(key, state);

        await Task.Run(() => db.Query()
            .Upsert(_ => new { _key = key },
                    _ => wrapped,
                   (_, old) => wrapped)
            .In<Wrapper<TState>>()
            .Execute());
    }

    return state;
}

Upon executing, I received an exception:

ArangoDB.Client.ArangoServerException: AQL: syntax error, unexpected integer number near '1` ' at position 1:56 (while parsing). ErrorNumber: 1501 HttpStatusCode: 400
   at ArangoDB.Client.BaseResultAnalyzer.ThrowIfNeeded(BaseResult baseResult)
   at ArangoDB.Client.Cursor.CursorAsyncEnumerator`1.SetCurrent()
   at ArangoDB.Client.Cursor.CursorAsyncEnumerator`1.MoveNextAsync()
   at ArangoDB.Client.Utility.TaskUtils.ResultSynchronizer[T](Task`1 task)
   at ArangoDB.Client.Cursor.CursorEnumerator`1.MoveNext()
   at System.Collections.Generic.List`1.AddEnumerable(IEnumerable`1 enumerable)
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at ArangoDB.Client.Data.Cursor`1.ToList()
   at ArangoDB.Client.QueryableExtensions.Execute[T](IAqlModifiable`1 source)
   ...

The generated AQL from doing .GetQueryData().Query is:

upsert  @P1  insert  @P2  update  @P3  in `Wrapper`1`  return   `_`

The generated AQL is wrong as there is an extra back tick in Wrapper`1.

I'm not sure about this, but Wrapper1 seems wrong as well, because different types for the generic will be mapped to the same collection. Assuming typeof(TState) is object, the collection should have been Wrapper_object (or with any other delimiter).

isen-ng commented 5 years ago

This happens on insert as well:

Code:

var wrapped = Wrapper.Wrap(key, state);
var result = await db.InsertAsync<Wrapper<TState>>(wrapped)

Exception:

ArangoDB.Client.ArangoServerException: collection or view not found: Wrapper`1. ErrorNumber: 1203 HttpStatusCode: 404
   at ArangoDB.Client.BaseResultAnalyzer.ThrowIfNeeded(BaseResult baseResult)
   at ArangoDB.Client.Http.HttpCommand.RequestMergedResult[T](Object data)
   at ArangoDB.Client.Collection.ArangoCollection.InsertAsync(Object document, Nullable`1 waitForSync, Action`1 baseResult)
   at ArangoDB.Client.Collection.ArangoCollection`1.InsertAsync(Object document, Nullable`1 waitForSync, Action`1 baseResult)
   at ArangoDB.Client.ArangoDatabase.InsertAsync[T](Object document, Nullable`1 waitForSync, Action`1 baseResult)
   ...
isen-ng commented 5 years ago

In fact, running the simplest of insertion script throws collection not found:

var result = db.Insert<State>(new State());

throws

ArangoDB.Client.ArangoServerException: collection or view not found: State. ErrorNumber: 1203 HttpStatusCode: 404
   at ArangoDB.Client.BaseResultAnalyzer.ThrowIfNeeded(BaseResult baseResult)
   at ArangoDB.Client.Http.HttpCommand.RequestMergedResult[T](Object data)
   at ArangoDB.Client.Collection.ArangoCollection.InsertAsync(Object document, Nullable`1 waitForSync, Action`1 baseResult)
   at ArangoDB.Client.Collection.ArangoCollection`1.InsertAsync(Object document, Nullable`1 waitForSync, Action`1 baseResult)
   at ArangoDB.Client.ArangoDatabase.InsertAsync[T](Object document, Nullable`1 waitForSync, Action`1 baseResult)
   ...
isen-ng commented 5 years ago

Basically, I cannot get your example code on your website to run:

    // insert new document and creates 'Person' collection on the fly
    db.Insert<Person>(person);

this doesn't seem to be true.

isen-ng commented 5 years ago

It seems like auto create collection was dropped in ArangoDb 3.0, which means your documentation is still based on the old version.

If that's the case, then there needs to be a db.CreateCollection<T> to create a the collection based on the type. This is important because all of your other APIs depend on using the type to identify the collection.

isen-ng commented 5 years ago

It seems like your collection name resolution is also causing problems with generics. type.Name will return things like Wrapped`1.

If you'd prefer, I will be able to send PRs for these issues.

ra0o0f commented 5 years ago

@isen-ng sorry for late response, unfortunately name resolving for generic types are not handled, this should be fixed in next versions

endeffects commented 5 years ago

When do you plan to support generic types?