8

Recientemente refactoré una aplicación WPF para que ya no implique cada uso del DbContext en una cláusula using (consulte this question). En cambio, mi aplicación solo usa el mismo singleton de DbContext en todas partes.¿Hay alguna manera de restablecer un DbContext sin desecharlo y volver a instalarlo?

Esto funciona muy bien, excepto por un pequeño problema. Tengo una rutina que reconstruye la base de datos desde cero e inserta algunos datos predeterminados. Esta rutina usa ADO.NET directamente (no el DbContext), por lo que el DbContext no sabe que la base de datos ahora es completamente diferente.

¿Hay algún método para restablecer el DbContext sin desecharlo? Me gustaría evitar deshacerme si es posible porque esto rompería varias referencias al singleton original en toda la aplicación.

Respuesta

7

yo no era capaz de llegar a un método para restablecer el DbContext global. Pude resolver mi problema, sin embargo, inyectando un DbContextLocator en cualquier clase que necesita un DbContext en lugar de pasar el DbContext.

Mi objetivo era mantener un DbContext global, pero permitir que se restablezca cada vez que sea necesario (como, por ejemplo, después de una reconstrucción o importación de la base de datos).

Mi solución utiliza una clase base abstracta y una clase concreta.

base de la Clase

using System.Data.Entity; 

namespace CommonLibrary.Database 
{ 
    public abstract class DbContextLocator 
    { 
     private DbContext _dbContext; 

     public DbContext Current 
     { 
      get { return _dbContext; } 
     } 

     public DbContextLocator() 
     { 
      _dbContext = GetNew(); 
     } 

     public virtual void Reset() 
     { 
      _dbContext.Dispose(); 
      _dbContext = GetNew(); 
     } 

     protected abstract DbContext GetNew(); 
    } 
} 

clase concreta

using System.Data.Entity; 
using CommonLibrary.Database; 
using ExperimentBase.EntityModels; 

namespace MainProject.Models  
{ 
    public class MainDbContextLocator : DbContextLocator 
    { 
     public new MainDbContext Current 
     { 
      get { return (MainDbContext)base.Current; } 
     } 

     protected override DbContext GetNew() 
     { 
      return new MainDbContext(); 
     } 
    } 
} 

Uso

Obtener el DbContext actual:

var dbContext = dbContextLocator.Current; 

Restablecer la DbContext:

dbContextLocator.Reset(); 
//Note: normally followed by code that re-initializes app data 

Editar

base en la retroalimentación de vibración excesiva, hice DbContextLocatorBase en un genérico. (Estoy ahora también la implementación de IDisposable.)

base de la Clase

public class DbContextLocator<TContext> : IDisposable 
    where TContext : DbContext, new() 
{ 
    private TContext _dbContext; 

    public TContext Current 
    { 
     get { return _dbContext; } 
    } 

    public DbContextLocator() 
    { 
     _dbContext = GetNew(); 
    } 

    public virtual void Reset() 
    { 
     _dbContext.Dispose(); 
     _dbContext = GetNew(); 
    } 

    protected virtual TContext GetNew() 
    { 
     return new TContext(); 
    } 

    public void Dispose() 
    { 
     _dbContext.Dispose(); 
    } 
} 

clase concreta (opcional, ya que la clase base abstracta ya no lo es)

public class MainDbContextLocator : DbContextLocator<MainDbContext> { } 
+0

Diría que el 'DbContextLocator' es una clase genérica, es decir' DbContextLocator donde TContext: DbContext', entonces no es necesario crear una clase derivada, o puede hacer que la clase derivada solo reduzca la verbosidad sin declarar nada en it, ver ejemplo [aquí] (http://pastebin.com/KRqQvAie) – Shimmy

+0

Buena idea ... Supongo que nunca optimicé hasta ese punto porque solo tiendo a escribir una de las clases concretas por proyecto. – devuxer

+0

Una vez que te acostumbras a los genéricos, esto no es una optimización, este es el diseño de código predeterminado :) – Shimmy

4

Mantener un ObjectContext abierto durante el tiempo de vida de la aplicación generalmente es una mala idea.

ObjectContext (o DbContext en este caso) es para una unidad de trabajo.

Ver Entity Framework and Connection Pooling

+0

Gracias por su responder.Consulte mi respuesta a su comentario aquí: http://stackoverflow.com/questions/5533917/how-do-you-minimize-the-performance-hit-when-upgrading-to-ef-4-1-from-linq -to-sql/5632059 # 5632059. – devuxer

Cuestiones relacionadas