2014-11-03 19 views
13

Si verificano problemi durante il tentativo di interrogare il mio account di archiviazione Azure DocumentDb quando si tenta di recuperare un singolo record. Questo è il mio codice WebAPI:Errore DocumentDb di Azure "Query deve valutare su IEnumerable"

// Controller... 
public AccountController : ApiController { 
    // other actions... 

    [HttpGet] 
    [Route("Profile")] 
    public HttpResponseMessage Profile() 
    { 
     var userId = User.Identity.GetUserId(); 
     var rep = new DocumentRepository<UserDetail>(); 
     var profile = rep.FindById(userId); 

     if (profile == null) 
      return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Profile not found"); 

     return Request.CreateResponse(HttpStatusCode.OK, profile); 
    } 
} 

// Repository 
public class DocumentRepository<TEntity> : IDocumentRepository<TEntity> where TEntity : IIdentifiableEntity 
{ 
    private static DocumentClient _client; 
    private static string _databaseName; 
    private static string _documentsLink; 
    private static string _selfLink; 

    public DocumentRepository() 
    { 
     _client = new DocumentClient(new Uri(ConfigurationManager.AppSettings["DocumentDbEndpointUrl"]), ConfigurationManager.AppSettings["DocumentDbAuthKey"]); 
     _databaseName = ConfigurationManager.AppSettings["DocumentDbDatabaseName"]; 
     var _database = ReadOrCreateDatabase(); 

     var collection = InitialiseCollection(_database.SelfLink, EntityName); 
     _documentsLink = collection.DocumentsLink; 
     _selfLink = collection.SelfLink; 
    } 

    // other methods... 

    public TEntity FindById(string id) 
    { 
     return _client.CreateDocumentQuery<TEntity>(_documentsLink).SingleOrDefault(u => u.Id.ToString() == id); 
    } 
} 

E 'questo metodo FindById che provoca il seguente problema:

Un'eccezione di tipo 'Microsoft.Azure.Documents.Linq.DocumentQueryException' si è verificato in Microsoft.Azure .Documents.Client.dll ma non è stata gestita nel codice utente

Ulteriori informazioni: espressione di query non è valido, il ritorno espressione tipo
Foo.Models.DocumentDbEntities.UserDetail non è supportato. La query deve essere valutata su IEnumerable.

Non capisco cosa significhi questo errore o come lo risolvo. Non desidero restituire un IEnumerable o qualsiasi classe di discendenti poiché questo metodo restituirà i record 0 o 1. Funziona se rimuovo la clausola SingleOrDefault e cambi il tipo di ritorno in un IQueryable, tuttavia questo non è quello che voglio.

risposta

28

SingleOrDefault() non è supportato, tuttavia nel provider LINQ.

Cambiare questo per .Where(u => u.Id.ToString() == id).AsEnumberable().FirstOrDefault();

+0

Perfetto, grazie per il vostro aiuto. –

+0

Hmmm. Ha funzionato stamattina, tuttavia ora ho bisogno di usare 'AsEnumerable' prima del' Where' altri errori ottengo errori. Niente è cambiato diversamente. Questo sembra strano. Codice di lavoro corrente: 'return Client.CreateDocumentQuery (DocumentsLink) .AsEnumerable(). Where (u => u.Id.ToString() == id) .FirstOrDefault();' Questo non è l'ideale a causa della performance hit di recupero di tutte le collezioni e filtrazione sul lato richiesta. –

+0

Questo è davvero strano. Sicuramente non vuoi l'AsEnumerable prima del Where. Quali errori ottieni se lo metti come sopra? –

1

non posso dire il motivo per cui la sintassi di Ryan ha smesso di funzionare per voi, ma si dovrebbe essere in grado di lavorare intorno ad esso senza la performance migliore colpito utilizzando un CreateDocumentQuery <>() di sovraccarico con una esplicitamente definito stringa di ricerca invece di utilizzare .Dove():

string query = string.Format("SELECT * FROM docs WHERE docs.id = \"{0}\"", id); 
return _client.CreateDocumentQuery<TEntity>(DocumentsLink, query).AsEnumerable().FirstOrDefault(); 

potrebbe essere necessario giocare con la query un po ', ma qualcosa di quella forma dovrebbe funzionare.

+0

Grazie per la risposta. Da allora ho trovato il problema è perché sto usando Guids, che hanno problemi con LIND lambda in DocumentDb al momento. La selezione tramite la sintassi SQL risolve il problema. La soluzione di Ryans ha sicuramente funzionato inizialmente, posso solo supporre che questo sia un problema dei problemi con LINQ. –

+0

Come si converte esattamente il guid in una stringa? Penso che DocumentDB funzioni meglio con Guid.ToString ("N") rispetto a Guid.ToString() predefinito. Probabilmente hai ragione che è dovuto al bug nel provider di query di linq, ma potrebbe valere la pena provare .ToString ("N"). –

+0

Se si riscontrano problemi con GUID, assicurarsi di eseguire l'ultimo SDK .NET su NuGet. 0.9.1-preview. Ci sono state alcune correzioni in questa nuova versione specificatamente per GUID e LINQ –

Problemi correlati