8

我最近重构了一个WPF应用程序,以便它不再包含DbContext在using子句中的每次使用(请参阅this question)。相反,我的应用程序始终使用相同的DbContext单例。有没有办法重置DbContext而不处理并重新实例化它?

这工作很好,除了一个小问题。我有一个例程从头开始重建数据库并插入一些默认数据。此例程直接使用ADO.NET(而不是DbContext),因此DbContext不知道数据库现在完全不同。

有没有方法来重置DbContext而不处理它?我希望尽可能避免处置,因为这会在整个应用程序中破坏对原始单身人士的几处引用。

回答

7

我没能拿出来重置全局的DbContext的方法。然而,我可以通过将DbContextLocator注入任何需要DbContext而不是传递DbContext本身的类来解决我的问题。

我的目标是维护全局的DbContext,但允许在需要时重置它(例如在数据库重建或导入之后)。

我的解决方案使用抽象基类和具体类。

基类

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(); 
    } 
} 

具体类

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(); 
     } 
    } 
} 

用法

获取当前的DbContext:

var dbContext = dbContextLocator.Current; 

重置的DbContext:

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

编辑

基于摆振的反馈,我做了DbContextLocatorBase为通用。 (我现在也实现IDisposable

基类

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(); 
    } 
} 

具体类(可选的,因为基类不再是抽象的)

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

我想说'DbContextLocator'是一个泛型类,即'DbContextLocator where TContext:DbContext',那么你不必做派生类,或者你可以让派生类只是为了减少冗长而不声明任何东西它,见示例[这里](http://pastebin.com/KRqQvAie) – Shimmy 2012-05-03 22:06:51

+0

好主意......我想我从来没有优化到这一点,因为我只倾向于写每个项目的具体类之一。 – devuxer 2012-05-03 22:28:18

+0

一旦你习惯了泛型,这不是一个优化,这是默认的代码设计:) – Shimmy 2012-05-03 22:55:57

4

保持ObjectContext在应用程序的整个生命周期中保持打开状态通常是一个坏主意。

ObjectContext(或本例中的DbContext)用于工作单元。

Entity Framework and Connection Pooling

+0

谢谢您回答。请参阅我的回应您的评论在这里: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 2011-04-13 07:26:15

相关问题