2014-11-03 7 views
13

Ich habe Probleme beim Abfragen meines Azure DocumentDb-Speicherkontos beim Versuch, einen einzelnen Datensatz abzurufen. Das ist mein WebAPI Code:Azure DocumentDb-Fehler "Abfrage muss IEnumerable entsprechen"

// 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); 
    } 
} 

Es ist diese FindById Methode, die das folgende Problem verursacht:

eine Ausnahme vom Typ 'Microsoft.Azure.Documents.Linq.DocumentQueryException' aufgetreten in Microsoft.Azure .Documents.Client.dll wurde aber in Benutzercode nicht behandelt

Zusätzliche Informationen: Abfrage Ausdruck ungültig ist, Ausdruck Rückgabetyp
Foo.Models.DocumentDbEntities.UserDetail wird nicht unterstützt. Die Abfrage muss nach IEnumerable ausgewertet werden.

Ich verstehe nicht, was dieser Fehler bedeutet, oder wie ich es behebe. Ich möchte weder eine IEnumerable noch eine abgeleitete Klasse zurückgeben, da diese Methode entweder 0 oder 1 Datensätze zurückgibt. Es funktioniert, wenn ich die SingleOrDefault Klausel entferne, und ändere den Rückgabetyp zu IQueryable, aber das ist nicht was ich will.

Antwort

28

SingleOrDefault() wird noch nicht im LINQ-Anbieter unterstützt.

Ändern Sie diese zu .Where(u => u.Id.ToString() == id).AsEnumberable().FirstOrDefault();

+0

Perfekt, danke für Ihre Hilfe. –

+0

Hmmm. Es hat heute Morgen funktioniert, aber ich muss jetzt 'AsEnumerable' vor dem' Where' verwenden, sonst bekomme ich Fehler. Nichts hat sich sonst verändert. Das scheint merkwürdig. Aktueller Arbeitscode: 'return Client.CreateDocumentQuery (DocumentsLink) .AsEnumerable(). Wobei (u => u.Id.ToString() == id) .FirstOrDefault();' Dies ist aufgrund der Leistungseinbußen nicht ideal Abruf aller Sammlungen und Filterung auf der Anfrageseite. –

+0

Das ist in der Tat seltsam. Sie wollen definitiv nicht das AsEnumerable vor dem Where. Welche Fehler bekommst du, wenn du es so bildest, wie ich es oben habe? –

1

Ich kann nicht sagen, warum Ryan Syntax für Sie aufgehört zu arbeiten, aber Sie sollten < unter Verwendung eines CreateDocumentQuery getroffen um es ohne die zusätzliche Leistung arbeiten können>() Überlast mit einem explizit definierte Query-String anstelle von .Where():

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

Sie müssen möglicherweise mit der Abfrage ein wenig spielen, aber etwas von dieser Form sollte arbeiten.

+0

Danke für die Antwort. Ich habe festgestellt, dass das Problem ist, weil ich Guids verwende, die Probleme mit LINQ Lambdas in DocumentDb im Moment haben. Durch die Auswahl mithilfe der SQL-Syntax wird das Problem behoben. Die Lösung von Ryans hat auf jeden Fall anfänglich funktioniert, ich kann nur annehmen, dass dies ein Problem mit LINQ ist. –

+0

Wie genau konvertieren Sie die GUID in eine Zeichenfolge? Ich denke, DocumentDB spielt besser mit Guid.ToString ("N") als der Standard Guid.ToString(). Sie haben wahrscheinlich recht, dass es wegen des Fehlers im linq-Abfrage-Provider ist, aber es könnte einen Versuch wert sein .ToString ("N"). –

+0

Wenn Sie Probleme mit GUIDs haben, stellen Sie sicher, dass Sie das neueste .NET SDK auf NuGet ausführen. 0.9.1-Vorschau. In dieser neuen Version gab es einige Korrekturen speziell für GUIDs und LINQ –

Verwandte Themen