7

我只想知道關於編寫存儲庫方法的最佳實踐。問題在於決定編寫其中上下文沒有延遲加載的存儲庫。你如何命名你的方法,如果它是GetById,但不清楚哪些導航包含在實體中。存儲庫模式和導航屬性

所以我想寫方法名稱像GetUserByIdIncludedPosts或者最好是使用延遲加載激活的上下文?

如果我在方法名中寫入包含的屬性,那麼對於很少的導航屬性來說真的很煩人的長方法名。

回答

2

使用存儲庫模式並不意味着您將無法使用延遲加載。您仍然可以返回將能夠延遲加載其相關實體的實體。唯一的要求是用於加載實體的DbContext必須是「活着的」。

但是,讓我們對倉庫的定義,看看通過Martin Fowler

版本庫介導 域和數據映射層之間,作用 像在內存中的域對象 集合。客戶對象以聲明方式構造 查詢規範,並將 提交給Repository,以獲得 滿意度。對象可以被添加到 併除去從所述存儲庫,因爲 它們可以從 對象的簡單集合,並且由存儲庫封裝映射代碼 將 進行適當的操作 幕後。從概念上講,存儲庫封裝了持久存儲在數據存儲中的對象集合 和通過它們執行的操作, 提供了持久層的更加面向對象的視圖 。存儲庫 也支持 的目標實現域 和數據映射層之間的乾淨分離和 單向依賴性。

我覺得最有趣的部分是:客戶對象構建查詢規範聲明,並提交給倉庫中的滿意度。庫也通常用於提供聚合根。因此,您要麼始終提供完整的根(不總是可能的),要麼您將滿足所提及的語句,並且您將通過Include擴展方法在IQueryable之上定義存儲庫以外的急切加載。正因爲如此,你將永遠不需要專門的方法,如GetUserByIdIncludeSomething

如果你想用戶信息庫開始用這種方法爲所有查詢:

public interface IRepository<T> 
{ 
    IQueryable<T> GetQuery(); 
} 

順便說一句。我不認爲用戶是帖子的聚合根。在這種情況下,大多數應用程序將只有一個聚合根 - 一個用戶。

編輯:

小澄清:IQueryable默認情況下不提供Include方法。它在CTP5程序集中作爲擴展方法提供,但如果使用它,則會使上層依賴於EntityFramework.dll。這是你通常不想要的東西(你使用存儲庫的原因)。所以,要走的路是定義你自己的擴展方法,用你的倉庫包裝提供的程序集擴展。

+0

如果您希望在數據層中保留與數據相關的異常,請不要這樣做。由於延遲加載將在比洋蔥結構主體將要頒佈的更高層上執行。導致各種錯誤的行爲。 還有其他的原因,如果你想觀察關於這個話題的激情論證,那麼簡單的谷歌'存儲庫模式IQueryable'。 – Shadetheartist 2017-05-15 23:03:13

2

我用我的庫基類下面,以便與依賴關係/關係的用戶指定列表一起實體檢索:

protected DbSet<T> Objects { get; private set; } 
protected YourDatabaseContext Context { get; private set; } 

public virtual T GetByID(int id, params string[] children) 
{ 
    if(children == null || children.Length == 0) 
    { 
     return Objects.SingleOrDefault(e => e.ID == id); 
    } 
    DbQuery<T> query = children.Aggregate<string, DbQuery<T>>(Objects, (current, child) => current.Include(child)); 
    return query.SingleOrDefault(e => e.ID == id); 
} 

代碼使用EF4/CTP5,因此使用db *類,但是將其轉換回正常的EF4類(例如,ObjectSet而不是DbSet)是微不足道的。

這將被用於像這樣:

var product = productsRepository.GetByID(42, "Category", "Orders.OrderLines"); 

這將獲取你類別和訂單人口以及具有其OrderLines即時加載的所有訂單的產物。