2009-09-23 108 views
1

這是一個好的或不好的主意?關於存儲庫模式的問題

public interface IRepository<T> 
{ 
    ... 
    IList<T> Get(Func<T, bool> predicate) 
    ... 
} 

我的意思是 - 它似乎真的很強大的附加功能,我可以實現它太(至少 - 在一定的水平),但我的膽量告訴我,這是一種錯誤的。任何人都可以啓發我嗎?

+0

@AdamRalph如果我知道 - 我不會問。這只是一種直覺。 – 2009-09-23 09:53:12

回答

1

那麼,它肯定是一個強大的功能。問題是:在界面中引入它會強制IRepository的所有實現提供一個合適的定義 - 根據實現可能不可能(或者至少非常困難)(例如,由數據庫連接支持的實現或其他)。

也許,你應該做的,而不是

public interface IRepository<T> 
{ 
    ... 
} 

public interface IAdvancedRepository<T>: IRepository<T> 
{ 
    IList<T> Get(Func<T, bool> predicate) 
} 

,並只提供Get,如果實現能有效地做到這一點。

+0

也想過這個。但我想知道 - 一般來說,提供這種API(通過超泛型謂詞查詢)是一個好主意。這會導致像'FindByCountryName'和'GetByLastName'這樣的儲存庫方法的必要性消失。基本上 - 我從存儲庫中移出一個問題來回答質疑我究竟在詢問什麼。看來我錯過了一些東西,這會在未來導致嚴重的問題。 – 2009-09-23 09:50:04

+2

問題是,您正在使用此解決方案有效地強制執行「全表掃描」,也就是說,即使您的存儲庫實現在LastName(哈希表,DB索引等)上有索引,您不能在實現Get的過程中使用它,因爲您不知道哪些屬性會被謂詞實際測試。這對「IRespository」的實施施加了嚴重的限制。 – Dirk 2009-09-23 09:58:21

+0

您不應刪除關於索引的那一點。我認爲這是一個有效的觀點。缺乏明確性會導致更難維護數據庫。 – 2009-09-23 09:59:02

3

我覺得這是更好的:

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

,那麼你可以寫你的自定義查詢爲:

var employees=Repositroy<Employee>.GetAll().Where(emp=>emp.Salary>10000).Select(emp=>emp).ToList(); 
+1

這是如果我們知道暴露完整的查詢API是不錯的主意。 – 2009-09-23 10:22:40

0

我傾向於將'Get'鏈接到一個簡單的實例,而不是一個列表。 因此,當我有一個方法返回一個集合時,我通常將該方法命名爲「Find」或類似的東西。

(請注意,FxCop會告訴你,使用'Get'作爲函數名是個壞主意)。

啊,好的,我錯過了這一點。 :) 我不會創建一個方法,它將一個標準作爲參數。我寧願在我的存儲庫上使用專門的方法,而不是傳入各種標準。 我知道,它不是那麼靈活,但它更加明確。

+0

這已經接近點。但是它只是爲了明確嗎? – 2009-09-23 09:57:02

0

對我來說,它似乎並不需要知識庫,因爲.NET開發人員通常都會理解它。

我想你需要的東西是這樣的:

public interface IStore { 
    // Low-level abstraction over a real database 
} 

public interface IAction<TInput, TResult> { // Or maybe ICommand? 
    TResult Execute(TInput input); 
} 

// then: 
public interface IGetCustomerById : IAction<int, Customer> { 
} 
public class GetCustomerById : IGetCustomerById { 
    IStore store; 
    public GetCustomerById(IStore store) { 
     this.store = store; 
    } 

    public Customer Execute(int id) { 
     return store.ResultOfExecutedSqlOrWhatever(id); 
    } 
} 
// it might not only be READ action but more complex one, reusing other actions too 
public class ApproveCustomer<ApprovalInfo,ApprovalResult> : IAction { 
    IStore store; 
    IGetCustomerById getCustomer; 
    public ApproveCustomer(IStore store, IGetCustomerById getCustomer) { 
     this.store = store; 
     this.getCustomer = getCustomer; 
    } 

    public ApprovalResult Execute(ApprovalInfo approval) { 
     var customer = getCustomer.Execute(approval.CustomerId); 
     var result = new ApprovalResult(); 
     if (customer == null) { 
      result.Message = "No such customer"; 
      return result; 
     } 
     if (!customer.IsEligibleForSomething()) { // This can be another action! 
      result.Message = "Not eligible" 
      return result; 
     } 
     result.Message = "Successfully approved" 
     result.IsApproved = true; 
     return result; 
    } 
} 

附加在這裏的好處是,所有這些行動可以依賴注入很容易地使用。

+0

缺點是什麼? – 2009-09-23 10:18:08

+0

一個缺點是它可能需要更多的代碼。 – 2009-09-23 12:10:22