2009-09-25 17 views
9

Abbiamo un servizio WCF che viene utilizzato per eseguire una query su un archivio dati sottostante (in questo momento SQL Server 2005). Questo servizio può restituire quantità piuttosto grandi di dati; Oltre 60000 istanze della nostra classe di entità che contiene ~ 20 proprietà. Le proprietà sono per lo più primitive come string, int, DateTime con una coppia che punta ad altre entità che possono a loro volta puntare su altre; quelle gerarchie non sono molto profonde però.Le migliori pratiche per il servizio WCF con grandi quantità di dati?

Un'applicazione che sta consumando questo servizio tipicamente effettuerà query che restituiscono solo un numero ragionevole di entità (da poche istanze fino a un paio di migliaia). Ma occasionalmente farà una query che restituirà una grande quantità come detto sopra (e dovrà elaborare quei dati, quindi restringere i criteri di query non è un'opzione).

Quello che vogliamo fare è introdurre una sorta di funzionalità di "paging", in cui il client può chiamare il servizio e ottenere un certo numero di istanze indietro, quindi chiamare di nuovo e ottenere il blocco successivo e così via, fino a quando il il risultato completo viene recuperato. Non avendo lavorato molto con WCF, non sono abbastanza sicuro del modo migliore per raggiungere questo obiettivo.

Una cosa da tenere a mente è che i dati sottostanti possono cambiare molto bene durante il recupero dei blocchi. Non sono sicuro che questo sia un problema per noi o no (è necessario che lo invii un po '), ma potrebbe esserlo, quindi qualsiasi input sulla gestione di quella particolare situazione è anch'esso benvenuto.

Abbiamo iniziato a esaminare la risposta in streaming, ma vorrei vedere anche esempi di paging, poiché potremmo voler iniziare l'elaborazione dei dati prima che venga ricevuto il risultato completo.

Quindi, la domanda in breve: esiste una best practice per questo tipo di scenario (o qualsiasi no-no assoluto di cui dovremmo essere a conoscenza)?

+1

Fredrik- hai visto questo- http://stackoverflow.com/questions/741413/implementing-pager-through-wcf-service- un po 'essenziale però – RichardOD

+0

@RichardOD: grazie per il link. Penso che dobbiamo attaccarlo a un livello più basso di quello, ma gli darò un po 'di tempo per la sperimentazione. –

risposta

9

L'utilizzo di una configurazione di binding streaming su client e server con un MessageContract che ha solo un flusso [MessageBodyMember] (e qualsiasi altro metadata inviato come [MessageHeader]) consente di eseguire l'intera operazione in un'unica chiamata senza preoccuparsi del paging (basta utilizzare un enumeratore sul lato server per alimentare lo stream ed elaborare le singole entità come appaiono sul client), ma è necessario eseguire il rolling del proprio framing all'interno dello stream (ad esempio serializzare/deserializzare le entità manualmente sullo stream con DataContractSerializer o qualsiasi altra cosa). L'ho fatto e funziona benissimo, ma è un po 'un dolore.

Se si desidera eseguire il paging, il modo più semplice è utilizzare un canale WCF sessionful in combinazione con una transazione snapshot (se si sta utilizzando SQL Server o qualcos'altro che li supporta come origine dell'entità). Avvia lo snapshot tx alla prima richiesta, quindi lega la vita del tx alla sessione, in modo che tu stia guardando un'immagine stabile dei dati tra le richieste di pagina - il tx verrà rilasciato quando la sessione è chiusa (o volte fuori, se il client si disconnette in modo imprevisto). Quindi il client richiede l'ultimo valore chiave che ha visto + quanti record desidera (attento a maxReceivedMessageSize- lascia un sacco di spazio). Dato che sei in uno snapshot, non devi preoccuparti delle modifiche: vedrai una vista coerente per la durata del dump. Se non è possibile eseguire un'istantanea dei dati di origine per evitare che cambi metà download, la vita è molto più difficile. Sempre fattibile, ma progettare per questo è molto specifico per i dati.

+0

Grazie per l'input. Guarderò nell'idea dell'operazione istantanea. Come sembra ora, è possibile che alcuni di questi servizi si spostino in Linq-to-sql per supportare il paging. Controllerò se queste idee possono essere combinate, il che sarebbe l'ideale. –

+0

Possono usare LINQ to SQL per tutto.L'unico trucco con l'istantanea è che avresti bisogno di toccare tutti i record (e dati correlati) una volta all'inizio, (ma in realtà non restituirlo al client) per farlo includere nell'istantanea. Un comando SQL discreto sarebbe probabilmente meglio per questo. – nitzmahone

Problemi correlati