2010-10-26 7 views
14

Questa è un'idea puramente concettuale e di progettazione correlata a EF4.Modifica di un modello di Entity Framework in fase di esecuzione

L'esempio/scenario è un sistema di tipo ERP o CRM di grandi dimensioni in cui le aziende potrebbero dover aggiungere tradizionali "campi definiti dall'utente" per acquisire dati aggiuntivi.

So che l'EF ha alcune funzionalità per estendere il modello a un database in fase di esecuzione ma la domanda è davvero possibile utilizzare EF per modificare un modello e aggiornare l'archivio dati in tempo reale?

In altre parole, se fornisco all'utente un meccanismo per aggiungere una colonna definita dall'utente, il tipo di dati associato ei requisiti nulli possono essere fatti al volo con EF e quindi ricordati per tutte le sessioni future?

È là fuori, ma penso che tutti vedrete cosa sto ottenendo.

Brent

+0

Quindi hai finito con quale soluzione? – Guillaume

+0

Non l'ho fatto. Non è mai stato in grado di testare o ottenere qualcosa da lavorare. Alla fine ho finito col code-first, comunque. –

risposta

14

Mi è stata posta questa domanda alcune volte in passato. Non esiste un modo ovvio o facile. È possibile che non ci sia modo ma siamo sviluppatori e c'è sempre un modo! So di cosa si tratta? No. Posso immaginare qualche idea? .... Mmmm .. in fase di esecuzione, il modello si basa su classi fortemente tipizzate dal metadataworkspace. Puoi crearli al volo. Ma poi è necessario modificare l'xml del file edmx. C'è LINQ su XML o xpath per quello. Modifica dello schema del database ... come fa il modello prima di costruire dbs ... crea sql e poi lo si esegue. Dovresti creare sql (come? Shrug) ed eseguirlo (objectcontext.executestorecommand()). Fattibile? Possibile? Non ho idea. Davvero la risposta è no ... non c'è niente in VS o .NET 4 (EF API) per abilitarla facilmente per quanto ne so. Sicuramente qualcuno più intelligente e paziente di quanto ho speso (sprecato ??) un sacco di tempo (cercando di) outsmart EF per tirarlo fuori. Basandosi, tuttavia, sulla tua risposta al suggerimento sul post del blog di Jeremy, stai cercando qualcosa di costruito/utile. È più facile rispondere con un "no".

Julie

+7

Benvenuti in SO, Julie! – Yakimych

+0

Penso che una combinazione di codice prima con "ExpandoObject" potrebbe farlo. Ma piuttosto che reificare i campi definiti dall'utente, ha più senso considerarli comunque non standard. +1 a Yakimych; benvenuto! –

+0

Concordo sul fatto che sarebbe molto più semplice con il codice prima e NESSUN modello, uno strato in meno di complessità e le regole da affrontare Ma un sacco di lavoro –

1

Jeremy Miller discute un set up simile a this article. Sta usando nibernate, ma potrebbe darti qualche idea.

+0

Sì, mi dà alcune idee, nessuna delle quali è semplice. Sono sorpreso che questo requisito non è comune con NHibernate o EF per quella materia. Qualche altra risorsa o idea? Non ha davvero risposto alla domanda, ha appena fornito un riferimento, difficile chiudere la domanda per questo. –

+0

ho pensato di farlo ma il mio scenario significa che devo consentire all'utente di aggiungere "dipendente" in primo luogo prima di definire i campi personalizzati ... in un certo senso anche la tabella è personalizzata. – War

11

ci sono spesso più di un modo per risolvere un problema, e questo non è un'eccezione. In questo caso, ciò che stai cercando è consentire agli utenti di aggiungere nuovi campi all'app e al database e utilizzare tali campi dall'app. Alcuni modi per farlo sono:

a) Permettere agli utenti di modificare lo schema del database.
b) Creare una struttura separata per definire "campi definiti dall'utente" e memorizzare i dati in essi.
c) Creare campi "riservati" nullable nelle tabelle in cui è più probabile che gli utenti abbiano bisogno dei propri campi.

Preferisco l'approccio (b) e talvolta l'approccio (c) ogni volta che sono necessari campi personalizzati definiti dall'utente in un'app. Ecco alcuni dei vantaggi/svantaggi per ciascuno dei tre:

Modifica schema

Risky: Se si consente agli utenti di modificare lo schema del database, dove si disegna la linea? Se possono aggiungere campi, possono anche decidere di cambiare la definizione dei campi esistenti, aggiungere o rimuovere indici, ecc. Ciò può portare a un incubo di supporto con bug, problemi di prestazioni ecc. Innescati da modifiche dello schema fatte dagli utenti.
Performant: la memorizzazione dei nuovi campi definiti dall'utente in linea nelle tabelle esistenti avrà solitamente un vantaggio in termini di prestazioni rispetto a una struttura separata, ma solo fino a quando non si esagerano con le modifiche.
Clunky: EF determina lo schema in fase di progettazione, quindi per eseguire questa operazione in fase di esecuzione sarà necessario generare nuove classi di entità in fase di runtime con i membri che rappresentano i nuovi campi e sarà necessario aggiornare i metadati di mapping in runtime. Le classi di entità generate dal runtime possono ereditare dalle classi generate in fase di progettazione, quindi è sufficiente aggiungere membri e associazioni per i nuovi campi definiti dall'utente. Anche se possibile, è goffo. Il codice che utilizza le classi generate dal runtime dovrà utilizzare la reflection per accedere ai nuovi membri creati in fase di runtime.

struttura separata

User-friendly: Creando una struttura separata per la memorizzazione di campi personalizzati, è possibile costruire la logica app per gli utenti di aggiungere/rimuovere quelle campi ecc Essi non hanno bisogno di pasticciare con il database, invece puoi avere moduli di manutenzione all'interno dell'app per aggiungere nuovi campi.
EF-friendly: non è necessario fare confusione con le classi di entità e mappare i metadati in fase di runtime. Tutto è definito in fase di progettazione e i campi definiti dall'utente sono solo dati.
Leggermente meno performante: Avere tabelle separate per la definizione e la memorizzazione dei campi definiti dall'utente può rendere le ricerche leggermente più costose a causa di ulteriori roundtrip o join aggiuntivi.

Separate table structure for user defined fields

campi riservati

abbastanza: In molte situazioni, i campi personalizzati vengono utilizzati solo per uno o alcuni campi aggiuntivi. La prenotazione di un paio di colonne coprirà spesso il 99% delle esigenze degli utenti. Anche un campo generico di "osservazioni" in ogni tabella è spesso sufficiente nelle app LOB.
Limitato: Se gli utenti desiderano più campi di quelli prenotati o altri tipi di dati di quelli prenotati, ciò può costituire una limitazione.
Performant: Colonne in linea, recuperate senza ulteriori viaggi di andata o ritorno.
Definito in fase di progettazione: Nessun errore di runtime in merito a definizioni o mappature del tipo di entità.

Reserved fields

2

Brent mi ha fatto un rumore metallico su Twitter oggi (quasi 2 anni dopo questo post) per vedere se qualcosa è cambiato. Questo scenario non è ancora supportato da EF. Tuttavia Rowan Miller ha un post interessante su come farlo con Code First http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/

Questo può o non può fare quello che ti serve, ma vale la pena dare un'occhiata.

0

Questa è una versione di Reserved fields dalla risposta di @KristoferA che ho usato in passato.

È possibile aggiungere una colonna XML aggiuntiva (o JSON) su ogni tabella che è probabile che richieda dati personalizzati e quindi la lettura/scrittura da db utilizzando EF.Dopo aver letto deserializzare XML (JSON) e passarlo al meccanismo che dovrebbe gestire i mapping, quindi presentarlo all'utente. Lo stesso vale per la scrittura dei dati che leggi dall'interfaccia utente -> mappa su oggetto -> serializza su XML (JSON) -> e scrivi su questi campi aggiuntivi.

Problemi correlati