2010-10-13 12 views
20

che sto cercando di capire come realizzare l'equivalente di:Come utilizzare OData Expand come un join SQL?

select * 
from Users u 
inner join Comments c on c.UserId = u.Id 
where Id = 1569 

(alias di tabella per una migliore leggibilità SQL)

... sull'endpoint StackOverflow OData. Come sarebbe costruito questo url? Sto osservando la documentazione per Expand su OData.org e avrei pensato che fosse qualcosa del genere:

https://odata.sqlazurelabs.com/OData.svc/v0.1/rp1uiewita/StackOverflow/Users?$Expand=Comments&$filter=UserId eq 1569 ma non è giusto.

in LINQ, sarebbe questo (credo), ma non è supportata Join:

Users.Where(u=>u.Id==1569).Join(Comments, u=>u.Id, c=>c.UserId, (a,b)=>a.Id==b.UserId)

Non ho bisogno di conoscere questo in LINQ rigorosamente, sto solo cercando per capire come costruire l'url della query. In sostanza, come posso tradurre il predicato di join SQL in un URL OData e farlo in una sola chiamata?

+9

Questa sembra essere la 1 milionesima domanda di Stack Overflow, congratulazioni! – jwaddell

+2

Bene, se contate domande che non sono state cancellate fino al momento in cui è stata posta questa domanda. – jjnguy

+0

@jwaddell Ho inviato un millisecondo dopo l'effettiva milionesima domanda, quindi suppongo che sia 1e6 + 1 –

risposta

15

Il modo giusto per fare questo sarebbe qualcosa di simile:

http://odata.stackexchange.com/stackoverflow/atom/Users(1569)?$expand=Comments 

Il problema è che non sembrano esserci gli utenti nell'origine dati (non so perché), quindi la query precedente restituirà a 404. Ma è la sintassi giusta.

L'idea è che se si desidera ottenere informazioni su un solo utente, è possibile "navigare" utilizzando lo /Users(1569) (il materiale in paresi è la chiave primaria del set di entità). Quindi se si desidera includere anche tutti i commenti, è sufficiente aggiungere $expand=Comments. Se desideri solo i commenti e non le informazioni sull'utente, puoi fare /Users(1569)/Comments.

Si noti che il servizio utilizzato non definisce le proprietà di navigazione, pertanto quanto sopra non funzionerà in quanto i "join" non sono realmente supportati. Ma l'endpoint odata di stackexchange ha le proprietà di navigazione definite.

Fondamentalmente i join sono definiti sul server/servizio in modo che il client non debba sapere quale colonna è una chiave esterna a quale chiave primaria.

Aiuta anche con le origini dati che non utilizzano database relazionali come memoria, in quanto non li obbligano a creare chiavi esterne false.

È possibile espandere ulteriormente "strati" del grafico. Se l'entità restituita nell'espansione definisce anche ulteriori proprietà di navigazione, è possibile specificare un elenco separato da virgole delle proprietà di navigazione.

Ecco un esempio per un servizio confezionato, si noti che questo espande ogni cliente nella raccolta, che è simile a un join multiplo.

.../Customers?$expand=Orders,OrderDetails 
+0

In che modo questa sintassi dell'URL esprime la relazione tra Users.Id e Commenti.UserId? In che modo questi campi si conoscono? È identificata questa relazione lato server? –

+2

In OData non ci sono "join" come nel server SQL. Le relazioni sono rappresentate come le cosiddette proprietà di "navigazione": fondamentalmente proprietà con valore di una o più entità (o collegamenti a tali entità). Quindi sì, se i dati sono supportati da una tabella SQL, il join esatto deve essere definito su server Ho aggiornato la risposta precedente per notare che il modello di esempio non aveva le proprietà di navigazione in esso, ma quello su stackexchange ne ha effettivamente. –

+0

Sono preoccupato per la tua nota aggiuntiva, il successo o il fallimento di questa query si basa sull'implementazione di OData? Questa query non è garantita dalle specifiche? –