这是一个好的或不好的主意?关于存储库模式的问题
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