這是一個好的或不好的主意?關於存儲庫模式的問題
public interface IRepository<T>
{
...
IList<T> Get(Func<T, bool> predicate)
...
}
我的意思是 - 它似乎真的很強大的附加功能,我可以實現它太(至少 - 在一定的水平),但我的膽量告訴我,這是一種錯誤的。任何人都可以啓發我嗎?
這是一個好的或不好的主意?關於存儲庫模式的問題
public interface IRepository<T>
{
...
IList<T> Get(Func<T, bool> predicate)
...
}
我的意思是 - 它似乎真的很強大的附加功能,我可以實現它太(至少 - 在一定的水平),但我的膽量告訴我,這是一種錯誤的。任何人都可以啓發我嗎?
那麼,它肯定是一個強大的功能。問題是:在界面中引入它會強制IRepository
的所有實現提供一個合適的定義 - 根據實現可能不可能(或者至少非常困難)(例如,由數據庫連接支持的實現或其他)。
也許,你應該做的,而不是
public interface IRepository<T>
{
...
}
public interface IAdvancedRepository<T>: IRepository<T>
{
IList<T> Get(Func<T, bool> predicate)
}
,並只提供Get
,如果實現能有效地做到這一點。
也想過這個。但我想知道 - 一般來說,提供這種API(通過超泛型謂詞查詢)是一個好主意。這會導致像'FindByCountryName'和'GetByLastName'這樣的儲存庫方法的必要性消失。基本上 - 我從存儲庫中移出一個問題來回答質疑我究竟在詢問什麼。看來我錯過了一些東西,這會在未來導致嚴重的問題。 – 2009-09-23 09:50:04
問題是,您正在使用此解決方案有效地強制執行「全表掃描」,也就是說,即使您的存儲庫實現在LastName(哈希表,DB索引等)上有索引,您不能在實現Get的過程中使用它,因爲您不知道哪些屬性會被謂詞實際測試。這對「IRespository」的實施施加了嚴重的限制。 – Dirk 2009-09-23 09:58:21
您不應刪除關於索引的那一點。我認爲這是一個有效的觀點。缺乏明確性會導致更難維護數據庫。 – 2009-09-23 09:59:02
我覺得這是更好的:
public interface IRepository<T>
{
IQueryable<T> GetAll();
}
,那麼你可以寫你的自定義查詢爲:
var employees=Repositroy<Employee>.GetAll().Where(emp=>emp.Salary>10000).Select(emp=>emp).ToList();
這是如果我們知道暴露完整的查詢API是不錯的主意。 – 2009-09-23 10:22:40
我傾向於將'Get'鏈接到一個簡單的實例,而不是一個列表。 因此,當我有一個方法返回一個集合時,我通常將該方法命名爲「Find」或類似的東西。
(請注意,FxCop會告訴你,使用'Get'作爲函數名是個壞主意)。
啊,好的,我錯過了這一點。 :) 我不會創建一個方法,它將一個標準作爲參數。我寧願在我的存儲庫上使用專門的方法,而不是傳入各種標準。 我知道,它不是那麼靈活,但它更加明確。
這已經接近點。但是它只是爲了明確嗎? – 2009-09-23 09:57:02
對我來說,它似乎並不需要知識庫,因爲.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;
}
}
附加在這裏的好處是,所有這些行動可以依賴注入很容易地使用。
缺點是什麼? – 2009-09-23 10:18:08
一個缺點是它可能需要更多的代碼。 – 2009-09-23 12:10:22
@AdamRalph如果我知道 - 我不會問。這只是一種直覺。 – 2009-09-23 09:53:12