建模NHibernate查询

7
通常我会将我的条件/HQL查询放在与实体相关的存储库/DAL类中,但最近我考虑添加另一个表示查询的抽象层,这将使我有可能在基类中添加所有查询的通用行为(例如分页)等。
因此,现在我的组件如下:
不涉及nhibernate的通用接口:
public interface IQuery<T>
{
    IList<T> List();
    T Single();
}

这是一个基于Criteria查询的示例实现,类似的操作也可以通过Hql查询或nhibernate-linq查询来完成。

public abstract class CriteriaQuery<T>: IQuery<T>
{
    [Inject]
    public ISessionFactory SessionFactory { protected get; set; }

    protected ISession Session
    {
        get { return SessionFactory.GetCurrentSession(); }
    }

    protected abstract ICriteria Configure(ICriteria criteria);

    [Transaction]
    public virtual IList<T> List()
    {
        var criteria = Session.CreateCriteria(typeof (T));

        return Configure(criteria)
                 .List<T>();
    }

    [Transaction]
    public virtual T Single()
    {
        return Configure(Session.CreateCriteria(typeof(T)))
                .UniqueResult<T>();
    }
}

这里的领域特定查询看起来像:

public interface IGetVideosQuery: IQuery<Video>
{
    IGetVideosQuery Page(int index);
    IGetVideosQuery PageSize(int pageSize);

    IGetVideosQuery AllTime { get; }
    IGetVideosQuery Today { get; }
    IGetVideosQuery LastWeek { get; }
}

你对此有什么想法?你认为我可能会遇到哪些问题吗? 谢谢!


1
请查看Fabio Maulo的“增强”查询对象,以获取某种相关结构:http://fabiomaulo.blogspot.com/2010/07/enhanced-query-object.html - DanP
2个回答

4
我走了一条不同的路线,即CQS的路线。这样做的好处是将我的变异逻辑与查询逻辑分开。
现在,有不同的想法来实现这一点,而我选择了这个:
- 我的所有突变逻辑都使用像DeactivateUserChangeRelationAddress这样的命令激活。对于这个业务逻辑,我有像您所描述的普通存储库; - 对于数据显示,我使用一个完全受控制的系统。通过这个系统,我描述了像 Specification Pattern这样的查询。我描述了基础表和字段。查询系统自动为我创建连接,并使用我提供的过滤器定义过滤器。
这个系统使我能够保持我的存储库的复杂性,因为我不必考虑用户可能设置的过滤器或ORDER BY。显示这些数据的系统自动使用Criteria创建过滤器并处理分页。
也许这样的系统适合你。

2

我的第一个建议是使用Linq2NH,它在NHibernate 2.1及以上版本中可用。会话(Session)在其上公开了一个AsQueryable<T>()方法,您可以在此基础上构建Linq查询。这将允许您使用标准的Linq扩展方法附加条件和投影,包括Skip()和Take()以实现分页(myQuery.Skip(PageIdx*PageSize).Take(PageSize).ToList()),以及Where子句进行过滤。这些查询中使用的lambda表达式和变量可以封装在某种QueryInfo类中,从而允许可重复、可持久化的查询。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接