Как использовать Generics для создания нескольких / вложенных объединений SelectMany в Linq для DocumentDB - PullRequest
0 голосов
/ 09 июня 2018

Я пытаюсь добавить метод в общий репозиторий для документа Db.

Я хотел бы, чтобы он генерировал SQL, похожий на этот (но общий):

SELECT VALUE c FROM c
JOIN versions IN c["versions"] 
JOIN groups IN versions["userGroups"] 
JOIN users IN groups["users"] 
WHERE c.type = "Approval" and users["userId"] = "xxx"

Iпробовал это ...

public async Task<ListResult<TResult>> SelectManyAsync<TEntity1, TEntity2, TEntity3, TEntity4, TResult>(Expression<Func<TEntity1, bool>> condition01, Expression<Func<TEntity1, IEnumerable<TEntity2>>> condition02, Expression<Func<TEntity2, IEnumerable<TEntity3>>> condition03, Expression<Func<TEntity3, IEnumerable<TEntity4>>> condition04, Expression<Func<TEntity4, bool>> condition05) where TEntity1:class
        {
            var feedOptions = GetFeedOptions();

            var query = DocumentDbContext.Client.CreateDocumentQuery<TEntity1>(DocumentDbContext.DocumentCollection.DocumentsLink, feedOptions)
                .Where(condition01)
                .SelectMany(condition02)
                .SelectMany(condition03)
                .SelectMany(condition04)
                .Where(condition05)
                .AsDocumentQuery();

// .. removed code for brevity

}

, что приводит к чему-то вроде этого:

SELECT VALUE tmp FROM root 
JOIN tmp IN root["versions"] 
JOIN tmp IN tmp["userGroups"] 
WHERE (true AND (tmp["userId"] = "xxx"))

, но я получаю ошибку:

Имя входного набораили псевдоним 'tmp' указан более одного раза в предложении FROM.

Можно ли создать что-то подобное с помощью шаблонов и как мы можем указать разные значения для "tmp".или это не правильный подход?

1 Ответ

0 голосов
/ 09 июня 2018

Не уверен, если эта ошибка или нет, ошибка такой запрос не будет работать.Вам нужно использовать вложенные selectMany.

Следующий пример должен работать:

public async Task<IEnumerable<TRes>> Query<T, TRes>(
        string docCollection,
        string partitionKey,
        Func<IOrderedQueryable<T>, IQueryable<TRes>> func,
        string continuationToken = null)
    {
        var queryable =
            CosmosClient.CreateDocumentQuery<T>(
                CollectionUri(docCollection),
                new FeedOptions
                {
                    MaxItemCount = 100,
                    RequestContinuation = continuationToken,
                    EnableCrossPartitionQuery = false,
                    PartitionKey = new PartitionKey(partitionKey),
                    PopulateQueryMetrics = true,
                });

        return await func(queryable).AsDocumentQuery().ExecuteNextAsync<TRes>();
    }


await Query<Doc, string>("collection", "pk",
            (IOrderedQueryable<Doc> x) => x.SelectMany(p => p.Versions.SelectMany(d => d.UserGroups.SelectMany(k => k.Users.Select(u => u.Name)))));
...