2009-07-13 15 views
7

Uso VS 2008 & .NET 3.5 SP1:WCF, Entity Framework e dati Contratti

sto usando WCF per consentire ai client di connettersi a un servizio che legge e scrive le voci del database che utilizzano Entity Framework. Per impostazione predefinita, le entità generate automaticamente dal database hanno l'attributo DataContract applicato.

Sfortunatamente molti dei campi esposti non sono destinati al consumo da parte del cliente (ad esempio - record di chi accede a quali dati, ecc.) E per motivi di sicurezza preferisco che non vengano esposti. Esiste un modo per evitare che le classi Entity Framework vengano esposte in questo modo?

Nota: Questo non è un duplicato di How to prevent private properties in .NET entities from being exposed as public via services?. In questa domanda l'utente desidera visualizzare in modo selettivo determinati campi, mentre vorrei che l'entità non venisse mai esposta come un DataContract.

Grazie in anticipo.

+0

Questo potrebbe essere simile a un altro messaggio a cui non è stata data una risposta completa: "Wcf e ADO entity framework", http://stackoverflow.com/questions/828302/wcf-and-ado-entity-framework – Malcolm

+0

Sono d'accordo con rispondi al link "wcf e ADO entity framework" che hai fornito. O potresti implementare una sorta di modello di repository. – NikolaiDante

+1

@Nath - Sono assolutamente d'accordo con la risposta sul "wcf e ADO entity framework", ma sfortunatamente non risolve il mio problema. Il primo punto della risposta è "Auto generate entità entità entità", che esporrà i dati che desidero mantenere privati ​​come DataContracts. Un modello di repository avrebbe lo stesso problema se fosse supportato da un modello EF generato in questo modo - a meno che non manchi qualcosa? – Malcolm

risposta

13

Sei consapevole che il tuo entità non hanno bisogno di mappare 1-1 con il database? In particolare, puoi omettere colonne o anche interi tavoli che non sono rilevanti.

Il modello di entità è pensato per essere un modello concettuale. È possibile creare facilmente un insieme di entità per l'esposizione a un set di client (servizi Web, forse) e un altro set, mappando allo stesso database, destinato a un client diverso (un'applicazione Web, forse).

D'altro canto, consiglio sempre di non esporre mai oggetti Entity Framework attraverso un servizio web. Microsoft sfortunatamente espone le proprietà dipendenti dall'implementazione contrassegnandole con [DataMember]. Ho appena provato questo con un semplice servizio restituendo un SalesOrderHeader da AdventureWorks.Il mio cliente ha ricevuto le versioni procura dei seguenti tipi EF:

  • EntityKeyMember
  • StructuralObject
  • EntityObject
  • EntityKey
  • EntityReference
  • RelatedEnd

Queste non sono cose che i vostri clienti bisogno di sapere.

Preferisco esporre oggetti Data Transfer e copiare le proprietà da una all'altra. Ovviamente, questo è fatto meglio attraverso la riflessione o la generazione di codice, che a mano. L'ho fatto attraverso la generazione del codice in passato (modelli T4).

Un'opzione che non ho provato è AutoMapper.

+0

Grazie per la risposta, John. Sì, sono a conoscenza del fatto che le entità non devono necessariamente mappare l'uno-a-uno e possono modellare un sottoinsieme del modello concettuale, ma non penso che ciò mi dia il risultato che spero. Ecco un esempio: Supponiamo di avere una tabella dei conti in un sistema di contabilità e voglio verificare quali operazioni vengono eseguite su quali account. Devo esporre i campi dalla tabella degli account, ma non voglio che il mio potenziale truffatore possa vedere quali informazioni sto seguendo delle sue azioni. Continua nel prossimo commento ... – Malcolm

+0

... Continua dal commento precedente. Quando il client chiama una funzione, voglio creare un record e inserirlo nella mia tabella di controllo per il monitoraggio e l'analisi. Mi piacerebbe avere entrambi accessibili tramite EF (se sono nello stesso contenitore o entità separate non è importante per me). Sfortunatamente tutto ciò che definisco come parte del modello di dati viene esposto come un DataContract. – Malcolm

+0

Quindi, non esporre quel modello di dati. Esporre un modello di dati più piccolo - quello che vuoi esposto. Non esporre lo stesso modello al potenziale truffatore come fai con il sistema di auditing. –

3

Utilizziamo classi separate per gli oggetti DataContract. Abbiamo un'interfaccia con un metodo, ToContract(), e tutte le nostre entità implementano questa interfaccia in un file di classe parziale. È un lavoro in più, ed è un piatto d'acqua, ma sembra il modo più semplice per ottenere la separazione e la granularità del controllo di cui abbiamo bisogno.

2

Io fondamentalmente vedere due cose che puoi fare:

  1. O si rimuovono gli elementi che non si desidera esporre dal DataContract rimuovendo manualmente l'attributo [DataMember] su tali elementi; in tal caso, WCF non serializzerà le proprietà fuori
  2. Si definiscono le proprie classi DataContract WCF con solo i membri desiderati e si ottiene una logica di conversione dalle entità EF al proprio DataContract WCF, utilizzando ad es. qualcosa come AutoMapper per eliminare (o almeno limitare) le noiose operazioni di assunzioni tra entità EF e WCF.

Marc

+0

Grazie, marc_s. Rispetto al precedente punto 1, come faccio a rimuovere manualmente l'attributo [DataMember] da quegli elementi che vengono generati automaticamente dal database? Ciò richiederà una rielaborazione manuale ogni volta che aggiorno il modello dal database? – Malcolm

+0

Sfortunatamente, sì, temo che non ci sia un modo automatico per sopprimere quegli attributi [DataMember] di cui sarei a conoscenza. Quindi l'idea di classi WCF separate che controlli completamente. –