2011-06-09 61 views
3

與大多數人一樣,我一直在關注Entity Framework的某些細節。其中一件事是上下文的生命週期。我正在使用一個存儲庫,並決定一個上下文將在請求的長度內生存。所以上下文需要從網絡層注入,無論使用哪個版本庫。重構的成熟 - .NET依賴注入

我寫了一些我肯定可以重構的代碼(其實絕對是!)。因此,基於上述概念,您將如何優化以下存儲庫幫助程序?

public class RepositoryHelper 
{ 

    public static CountryRepository GetCountryRepository() { 
     return new CountryRepository(HttpContext.Current.GetObjectContext()); 
    } 

    public static CurrencyRepository GetCurrencyRepository() 
    { 
     return new CurrencyRepository(HttpContext.Current.GetObjectContext()); 
    } 

    public static SettingRepository GetSettingRepository() 
    { 
     return new SettingRepository(HttpContext.Current.GetObjectContext()); 
    } 

} 

庫是非常簡單,看起來像

public class CountryRepository 
{ 

    private Context _context = null; 
    public CountryRepository(Context context) 
    { 
     _context = context; 
    } 

    public Country GetById(int id) 
    { 
     // Would return a country 
    } 

    public IEnumerable<Country> All() 
    { 
     // Would return a list of countries 
    } 

} 

回答

2

這裏面臨的挑戰是,您構建的內容不是存儲庫模式的意義上的存儲庫。存儲庫模式的目標是從問題域中抽象出數據訪問層的實現。它通過一個存儲庫完成,該存儲庫的行爲類似於內存中的域對象集合,您可以使用它執行常規的CRUD功能,並且經常執行一些更具體的操作,即GetByID(id)。

然後,存儲庫隱藏應用程序中的實際持久層,使您可以在不影響應用程序的情況下更改該層,即可以先將數據存儲在平面文件中,然後再移至RDBMS。

您通常會創建一個接口來描述您的存儲庫需要實現的方法,並使用該接口作爲類型實際傳遞存儲庫實例。這是抽象的,接口在存儲庫的所有可能的具體實現中都很常見,但是您的應用程序實際上並未被使用(在某種程度上)。

我建議回退一步,再看看存儲庫模式,看看你是否需要它。確保你不僅僅是爲了它而實現它,並且你不會不必要地增加應用程序的複雜性。一旦你確定了你的數據訪問方法,那麼你可以看看你如何最好地利用你有的EF上下文。

+0

+1,很好的建議 – smartcaveman 2011-06-09 11:59:09

+0

謝謝拉撒路。爲了清楚起見,我已經讚賞示例回購(如果我的示例不完整)。我認爲存儲庫模式正在正確地用於數據訪問,並與解決方案中的Web域分離。您的第三段是我最感興趣的內容 - 即我的web層如何與這些存儲庫進行交互,而無需編寫一個爲每個存儲庫類型注入上下文的啞助手。 – Maleks 2011-06-09 12:38:34

+0

@Maleks:我使用DI容器(Castle Windsor)在存儲庫實例化時實例化上下文(當活動控制器需要時,它本身通過DI容器實例化)。您的存儲庫應該都基於您的Web應用程序與之交互的聚合根實體,超出此範圍的範圍才能深入瞭解。將存儲庫的具體實現與數據訪問層更緊密地耦合是很好的,這實際上是不可避免的,但存儲庫耦合的應用應該是鬆散的。 – Lazarus 2011-06-10 10:46:53

0

我認爲你會從使用存儲庫Provider類和庫工廠就像在回答C#/EF and the Repository Pattern: Where to put the ObjectContext in a solution with multiple repositories?受益。

+0

你爲什麼不使它安全? – jgauffin 2011-06-09 11:39:41

+0

@jgauffin,你能改說你的問題嗎 – smartcaveman 2011-06-09 11:48:19

+0

這看起來很有趣。我很想看到IRepository的一個例子,以及如何使用回購提供者。 – Maleks 2011-06-09 13:44:57

0

對於DI,您可以使用Ninject並在綁定對象時使用InRequestScope方法。

0

閱讀我的回答here關於如何製作通用會話管理器。

然後創建一個EntityFramework會話管理器(它存儲objectcontext)。

一些半完成的僞代碼:

public static class EntityFrameworkSession 
{ 
    [ThreadStatic] private static ObjectContext _current; 

    public static AssignToSessionFactory() 
    { 
     SessionFactory.Created += OnCreateObjectContext; 
     SessionFactory.Disposed += OnDisposeContext; 
    } 

    public static void OnDisposeContext(object source, SessionEventArgs e) 
    { 
     if (e.Saved) 
      _myContext.SaveChanges(); 
    } 
} 

而在你的倉庫使用:

EntityFrameworkSession.Current 

訪問上下文。