2012-02-29 10 views
23

Ho problemi con il framework di entità che restituisce proxy quando desidero l'effettiva classe di entità. La prima volta che eseguo il mio codice, tutto funziona correttamente (nessun proxy), ma dopo ogni iterazione uno dei miei DbSet restituisce sempre proxy anziché il tipo effettivo.Perché EF restituisce una classe proxy anziché l'entità effettiva?

Dispongo del contesto dopo ogni iterazione, quindi non capisco perché la prima volta che funziona funziona, e ogni volta dopo non lo fa.

Il mio codice non funziona su questa linea. Tutti i miei POCO hanno l'attributo Table impostato, ma poiché restituisce una classe proxy non esiste un attributo table.

TableAttribute attrib = (TableAttribute)attributes.Single(); 

C'è qualche magia dietro le quinte nel DbContext che vive dopo aver distrutto l'oggetto?

mi muovo i miei oggetti in memoria, con la seguente

MajorClasses = ctx.MajorClasses.ToArray(); 

Ho anche provato

MajorClasses = ctx.MajorClasses.AsNoTracking().ToArray(); 

Nel mio OnModelCreating ho il seguente set

base.Configuration.ProxyCreationEnabled = false; 
      base.Configuration.LazyLoadingEnabled = false; 

risposta

38

È possibile impostare ObjectContext.ContextOptions.ProxyCreationEnabled su falso. Ciò ti impedirà di utilizzare alcune delle fantasiose funzionalità di EF come il caricamento lento e credo che il rilevamento delle modifiche.

Per quanto riguarda la tua app, dovrebbe essere in grado di trattare i proxy come i tipi che rappresentano. C'è un problema specifico che stai avendo?

Modifica

Abbiamo alcuni codice che richiede il tipo POCO anziché il tipo di proxy e facciamo quanto segue per rilevare se il tipo di corrente è un proxy.

if (entityType.BaseType != null && entityType.Namespace == "System.Data.Entity.DynamicProxies") 
{ 
    entityType = entityType.BaseType; 
} 
+0

Ho aggiunto più dettagli alla mia domanda. Ho avuto questa impostazione impostata e nessuna mia applicazione non può trattare i proxy come il POCO. –

+0

È nella domanda aggiornata. Rifletto la classe per ottenere attributi da essa. –

+0

@ MalcolmO'Hare Ho pubblicato il codice che usiamo per ottenere il tipo POCO dal tipo proxy. – cadrell0

2

Per impostazione predefinita, usi EF Change Tracking e utilizza una cache in memoria di tutte le entità. È possibile utilizzare diverse opzioni di unione quando si lavora con EF. Per impostazione predefinita, EF 4.1 è impostato su AppendOnly Merge Option. Come ho capito, questo significa che se hai già interrogato un'entità, le query successive otterranno l'entità dalla cache (se non ci sono cambiamenti rilevati nel database). Quindi potresti vedere l'entità memorizzata nella cache che ritorna.

In EF 4.1, è possibile utilizzare l'opzione di unione NoTracking. Questo andrà al database per ogni chiamata.

+0

Su ogni iterazione del mio programma (la sua interrogazione di un database, quando si inserisce un record di fare un lavoro in un altro database) creo un nuovo contesto e caricare tutti i miei dati in memoria. Quando tutto il mio lavoro è finito, tutti i dati caricati + il contesto viene eliminato. Se eseguo la stessa esportazione due volte, la seconda volta che vengono eseguiti alcuni record vengono restituiti come proxy, cosa che non è avvenuta la prima volta che è stata eseguita. Inoltre sto usando 4.3 ora (aggiornato per vedere se ha risolto il problema). –

+0

Sì, sembra strano che si otterrebbe un oggetto proxy basato su quello. Tuttavia, è possibile impostare NoTracking solo per escludere la cache. –

+1

@ MalcolmO'Hare I proxy sono proprietà virtuali di altre entità? Forse stai semplicemente vedendo il caricamento pigro di EF. Se non si utilizza (carica) l'entità impostata come virtuale, potrebbe apparire come un proxy. –

6

Per disattivare la creazione di proxy in Entity Framework 5 è possibile utilizzare il seguente,

_dbContext.Configuration.ProxyCreationEnabled = false; 

Basta impostare questa proprietà una volta prima di utilizzare il contesto per estrarre i dati.

1

In EF 6.1.3 è possibile ottenere il giusto tipo utilizzando

using (var context = new BloggingContext()) { 
    var blog = context.Blogs.Find(1); 
    var entityType = ObjectContext.GetObjectType(blog.GetType()); 
} 

Si noti che se il tipo di passato a GetObjectType è un'istanza di un tipo di entità che non è un tipo di proxy quindi il tipo di l'entità è ancora restituita.Questo significa che puoi sempre usare questo metodo per ottenere il tipo di entità reale senza altri controlli per vedere se il tipo è un tipo proxy o no.

Da MSDN

+2

Vuole l'entità reale, invece del suo tipo. – Tito

Problemi correlati