CreateDocumentQuery выдает исключение при использовании с LINQ, нормально с SQL

Я пытаюсь получить один объект, хранящийся в моем Azure DocumentDb. Я обнаружил, что мой код только работает, когда я отправляю запрос с помощью SQL, как показано ниже:

var query = String.Format("SELECT * FROM UserDetail u WHERE u.id = '{0}'", id);
return _client.CreateDocumentQuery<TEntity>(_selfLink, query).AsEnumerable().FirstOrDefault();

Однако при использовании выражения LINQ, как в следующих двух примерах, возникает ошибка с исключением:

// EXCEPTION
return _client.CreateDocumentQuery<TEntity>(_selfLink).Where(u => u.Id.ToString() == id).AsEnumerable().FirstOrDefault();

// EXCEPTION
return (from u in _client.CreateDocumentQuery<TEntity>(_selfLink)
    where u.Id.ToString() == id
    select u).AsEnumerable().FirstOrDefault();

Довольно чудовищная трассировка стека возникшего исключения:

System.AggregateException: One or more errors occurred. ---> Microsoft.Azure.Documents.Linq.DocumentQueryException: Unhandled expression type: 'Call'
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarExpression(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitBinary(BinaryExpression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarExpression(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarLambda(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitWhere(ReadOnlyCollection`1 arguments, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitMethodCall(MethodCallExpression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.Translate(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.SQLTranslator.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.HandleMethodCallExpression(MethodCallExpression expression, QueryType defaultQueryType, QueryType& queryType)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.Evaluate(Expression expression, QueryType defaultQueryType, QueryType& queryType)
   at Microsoft.Azure.Documents.Linq.DocumentQueryExecutionContext.<ExecuteAllAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.Azure.Documents.Linq.DocumentQuery`1.<GetEnumeratorTAsync>d__10.MoveNext()
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at Microsoft.Azure.Documents.Linq.DocumentQuery`1.GetEnumerator()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at Cherish.Domain.Repositories.Implementation.DocumentRepository`1.FindById(String id) in \\psf\home\Documents\Visual Studio 2013\Projects\Cherish\Cherish.Domain\Repositories\Implementation\DocumentRepository.cs:line 82
---> (Inner Exception #0) Microsoft.Azure.Documents.Linq.DocumentQueryException: Unhandled expression type: 'Call'
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarExpression(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitBinary(BinaryExpression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarExpression(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitScalarLambda(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitWhere(ReadOnlyCollection`1 arguments, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.VisitMethodCall(MethodCallExpression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.Translate(Expression inputExpression, TranslationContext context)
   at Microsoft.Azure.Documents.Linq.ExpressionToSql.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.SQLTranslator.TranslateQuery(Expression inputExpression)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.HandleMethodCallExpression(MethodCallExpression expression, QueryType defaultQueryType, QueryType& queryType)
   at Microsoft.Azure.Documents.Linq.DocumentQueryEvaluator.Evaluate(Expression expression, QueryType defaultQueryType, QueryType& queryType)
   at Microsoft.Azure.Documents.Linq.DocumentQueryExecutionContext.<ExecuteAllAsync>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Microsoft.Azure.Documents.Linq.DocumentQuery`1.<GetEnumeratorTAsync>d__10.MoveNext()<---

Для справки, это класс UserDetail (нерелевантные свойства и методы удалены):

public class UserDetail : IIdentifiableEntity
{
    [JsonProperty(PropertyName = "id")]
    public Guid Id { get; set; }

    [JsonProperty(PropertyName = "fn")]
    public string Firstname { get; set; }

    [JsonProperty(PropertyName = "ln")]
    public string Lastname { get; set; }

    [JsonProperty(PropertyName = "contribs")]
    public IList<ContributorRelation> Contributors { get; set; }
}

Я знаю, что могу использовать метод формата SQL, однако в качестве личного предпочтения я хотел бы использовать лямбда-выражения и не могу понять, почему мой код не работает должным образом. Нужен ли мне другой тип приведения типов из Guid?


person Rory McCrossan    schedule 05.11.2014    source источник
comment
Похоже, это ошибка в процессе исправления: social.msdn.microsoft.com/Forums/sqlserver/en-US/   -  person Raphaël Althaus    schedule 05.11.2014
comment
@ RaphaëlAlthaus Большое спасибо - похоже, это ошибка. Надеюсь, обновление скоро выйдет. Если вы опубликуете это как ответ, я помечу его как принятый.   -  person Rory McCrossan    schedule 05.11.2014


Ответы (1)


Вызов метода ToString не поддерживается внутри запросов linq. Попробуйте разобрать идентификатор на guid и выполнить простое равенство, подобное этому:

return _client.CreateDocumentQuery<TEntity>(_selfLink).Where(u => u.Id == Guid.Parse(id)).AsEnumerable().FirstOrDefault();
person Arnab Chakraborty    schedule 18.01.2015