5

我在C#标准库接口,其中包括以下方法:存储库/工作单元模式 - 如何查询符合特定条件的对象的存储库?

IEnumerable<T> GetAll(); 
T GetById(int id); 
void Delete(T entity); 
void Add(T entity); 

在我的领域层我的全部实例是工作包装纸的新单位,并把它传递到存储库。工作单元包装类隐藏了我是否使用NHibernate或实体框架并公开了一个Commit()方法。

在我的域图层中,如何查询仅满足特定条件的对象?

我认为我目前所做的工作非常低效。我目前做这个:

var results = myRepository.GetAll().Where...... 

如果我有一个非常大的物体,是GETALL()会过滤掉我不需要的那些前,他们中的每一个回归?我怎样才能防止不需要的对象被返回?

很明显,我可以在界面中添加更多的方法,但这似乎并不符合通过界面公开CRUD操作。

即 - 我不认为我应该增加之类的东西(但也许我错了):

IList<T> GetAllWhereMeetsMyCriteria(); 

回答

3

查看this blog post [weblogs.asp.net]中使用的存储库模式。我发现源代码使用了一些有趣的模式,我不断返回并再次检查。该代码实现了存储库和工作模式单元。

为了回答您的具体问题,库接口包含的方法:

IEnumerable<T> GetMany(Expression<Func<T, bool>> where);  

它作为RepositoryBase<T>类实现方式是:

public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where) 
{ 
    return dbset.Where(where).ToList(); 
} 

大概都EF和NHibarnate将有接口必须支持这种用法。

+0

的确他们非常感谢。这解决了我的问题。 – JMc 2011-05-14 11:54:21

2

不熟悉NHibernate的,但通常情况下,我跟你最后溶液(IList<T> GetAllWhereMeetsMyCriteria();) :

public IList<TEntity> Find<TEntity>(Func<TEntity, bool> criteria) where TEntity : class 
{ 
    return this.Query<TEntity>().Where<TEntity>(criteria).ToList<TEntity>(); 
} 

有在写一个伟大的Genric库:http://www.martinwilley.com/net/code/nhibernate/genericrepository.html

你可能想使用,因为它涵盖了更多的情况。此外,您可以根据特定需求从中派生自定义存储库。 (例如:http://www.martinwilley.com/net/code/nhibernate/productrepository.html

UPDATE
您可以在您导出库定义自定义指标分析,并使用它们。例如

private ICriteria CriteriaCategoryId(int categoryId) 
    { 
     ICriteria criteria = Session.CreateCriteria(typeof(Product)); 
     criteria.CreateCriteria("Category") 
      .Add(Expression.Eq("Id", categoryId)); 
     return criteria; 
    } 
public IList<Product> ProductByCategory(int categoryId, int pageStartRow, int pageSize) 
    { 
     var criteria = CriteriaCategoryId(categoryId) 
      .SetFirstResult(pageStartRow) 
      .SetMaxResults(pageSize); 

     return criteria.List<Product>(); 
    } 
+0

这很有帮助,非常感谢+1。如果事实证明是这样,我会研究你的建议并标记为答案。谢谢! – JMc 2011-05-14 11:01:23

+0

没问题。只要注意许多人不直接使用通用存储库。他们从那里(例如'ProductRepository')派生定制的存储库并直接使用这些派生的存储库。祝你好运。 – Kamyar 2011-05-14 11:05:43

6

是的,您的GetAll().Where会将您的所有对象从数据库中提取到您的应用程序并执行linq-to-objects。 @Kamyar解决方案也会这样做。 @Dysaster在我写这个答案时提供了一个正确的解决方案。

首先 - 你真的需要它必须支持的NHibernate或EF库?它是客户的要求吗?如果不是你在浪费资源。选择技术并创建应用程序所需的最小抽象,以遵循问题分离。

如果你真的需要高层次的抽象和持久性API,你应该从家庭使用第三图案绝对的独立性 - Specification pattern。使用自定义规范,如果将规范描述的条件转换为数据源所需的操作,您将能够将持久性更改为任何内容。 NHibernate中的Criteria API或IQueryable的扩展方法是规范,但它们是技术相关的。

+0

请你解释,为什么'this.Query ()。凡(标准).ToList ();'返回的所有实体,然后执行LINQ到对象?我以为它不会从数据库中获取数据,直到我们使用ToList()或等价的方法。是否查询。在哪里'首先返回来自数据库的所有数据,并且它们执行linq? – Kamyar 2011-05-14 11:22:17

+0

不是客户的要求。我正在为我的MSc编写一个项目,在其中检查实体框架的各个方面。我被要求将它与一个更成熟的O/RM(NHibernate)进行对比,看看它们是如何相互叠加的,因此需要支持这两者。感谢您的答复。 – JMc 2011-05-14 11:23:24

+1

@Kamyar:'ToList'执行查询,但问题是您在'Expressoin '而不是'Expressoin '处使用'Func'。 'Func'是'IEnumerable'上使用的委托,因此EF必须首先将所有实体加载到内存才能运行委托。 '表达式'在'IQueryable'上使用,并被转换为SQL。这是非常常见的错误。 – 2011-05-14 11:50:57