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

相關問題