2009-09-21 54 views
3

比方說,我需要顯示一個客戶列表,但只想顯示名稱,並以某種方式將鍵關聯到列表控件中的名稱。從Repository <T>返回數據子集的可能方法?

檢索客戶及其所有屬性的整個列表可能代價高昂。在這種情況下,創建另一個具有所需屬性(在本例中爲Id和Name)的類會更好嗎?

基本實現看起來是這樣的:

public class Customer { 
    public int Id { get; set; } 
    public string Firstname { get; set; } 
    public string Lastname { get; set; } 
    public int Age { get; set; } 
    ..... 
} 

public class CustomerListView { 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public interface IRepository<T> { 
    public T Find(int id); 
    public IEnumerable<T> FindAll(); 
    .... 
} 

public class Repository<T>: IRepository<T> { 
    .... 
} 

public class CustomerRepository: Repository<Customer> { 
    public IEnumerable<CustomerListView> FindAllListView(); 
} 

請問這種做法是合適的?還有什麼其他選擇?

回答

1

如果您使用的IQueryable爲你的回報,而不是IEnumerable的比沒有這樣做的成本:。

CustomerRepository()GETALL()查找(1),因爲AsQueryable已實際上並不執行,直到您請求的數據。這意味着LINQ可以優化它到:

SELECT .... .... FROM WHERE ID = 1而不是

得到一切。尋找到ID = 1

看到這個職位的一個解釋:

Why use AsQueryable() instead of List()?

使用這種方法,你可以創建一個匿名類,並進一步縮小範圍向下的數據通過線路到你想要的東西, 。這樣LINQ生成的查詢得到了最充分的優化。

+0

這是一個有趣的想法,我沒有考慮過。除了將我的存儲庫耦合到LINQ之外,還有其他的原因可以避免這種情況嗎?我一直認爲知識庫的責任是提供對域對象的訪問。無論如何,我會研究這個建議,因爲如果必須的話,我不介意偏離「純粹」DDD。 – Joepro 2009-09-22 00:07:10

+0

LINQ是C#的核心功能,所以不用擔心。這種設計模式通常被視爲Repository,但它比任何事情都更加活躍。我經常做的是使用裝飾模式,並將類型的擴展方法進行進一步過濾。 – 2009-09-22 16:36:56

1

如果您不得不從數據庫中檢索列表,那麼您的提議有一定意義,但我會考慮Linq和匿名類型解決方案。

如果客戶列表已經存在於內存中,那麼就沒有節省。

+0

是的,你是對的。我應該提到從數據庫中檢索數據。 – Joepro 2009-09-21 23:58:42

2

爲了實現這些目標,我創建了一個簡單的'View'類,例如CustomerView,它只包含顯示概覽所需的屬性。

My Repository然後有一個方法返回這些CustomerView對象的集合。

我主要在我的項目中使用NHibernate。 Nhibernate允許您使用「預測」。 所以,我在我的存儲庫中做的是: (注意下面的代碼只是一些僞代碼;它不會編譯)。

public IList<CustomerView> GetAllCustomers() 
{ 
    ICriteria crit = _session.CreateCriteria (typeof(Customer)); 

    crit.AddProjection (...); 

    crit.SetResultTransformer (new EntityToBeanTransformer(typeof(CustomerView)); 

    return crit.ToList(); 
} 

事實上,它歸結爲這樣的:我告訴我的O/R映射工具,它應該詢問顧客,但它應該返回類型「CustomerView」的實體。 在定義投影時,我還定義了Customer類的哪些屬性映射到CustomerView類的哪些屬性。 然後,O/R映射器足夠聰明,可以生成一個非常簡單的查詢,該查詢僅檢索填充CustomerView類所需的那些字段。 例如,所執行的查詢可以是簡單的:

SELECT customerid, customername FROM tblCustomer 
+0

我沒有考慮過使用NHibernate。感謝您的建議。 – Joepro 2009-09-22 02:42:22

+0

我的觀點並不是真的建議你應該使用NHibernate(雖然它會有所幫助,因爲它是一個很好的工具),但更重要的是它非常適合使用'笨'的CustomerView類型來顯示概覽的客戶。 – 2009-09-22 07:08:42

0

你可以使用LINQ對NHibernate的結合日產和弗雷德裏克(匿名類型和NHibernate)所使用的技術。

Bill Wagner的更有效C#中的Item#31表示「通過使用匿名類型限制類型範圍」,我同意。順便說一下,我推薦整本書。