nhibernate - ROW_NUMBER() 和 nhibernate - 查找项目的页面

标签 nhibernate paging row-number

给定一个 ICriteria 对象形式的查询,我想使用 NHibernate(通过投影?)来查找元素的顺序,
以等效于使用的方式

SELECT ROW_NUMBER() OVER (...)

在查询中查找特定项目的索引。
(我需要这个用于分页中的“跳转到页面”功能)
有什么建议?

注意:我还不想转到有编号的页面 - 我知道该怎么做 - 我想获取项目的 INDEX,这样我就可以按页面大小划分它并获取页面索引。

最佳答案

在查看了 NHibernate 的来源之后,我相当确定不存在这样的功能。

然而,我不介意有人证明我是错的。

在我的特定设置 ,我确实通过编写一个方法解决了这个问题,该方法需要几个 lambdas(代表键列和一个可选列来过滤 - 特定域实体的所有属性)。此方法然后构建 sql 并调用 session.CreateSQLQuery(...).UniqueResult();我并不是说这是一个通用的解决方案。

为了避免使用魔法字符串,我借了一份 PropertyHelper<T>来自 this answer .

这是代码:

public abstract class RepositoryBase<T> where T : DomainEntityBase
{
    public long GetIndexOf<TUnique, TWhere>(T entity, Expression<Func<T, TUnique>> uniqueSelector, Expression<Func<T, TWhere>> whereSelector, TWhere whereValue) where TWhere : DomainEntityBase
    {
        if (entity == null || entity.Id == Guid.Empty)
        {
            return -1;
        }

        var entityType = typeof(T).Name;

        var keyField = PropertyHelper<T>.GetProperty(uniqueSelector).Name;
        var keyValue = uniqueSelector.Compile()(entity);

        var innerWhere = string.Empty;

        if (whereSelector != null)
        {
            // Builds a column name that adheres to our naming conventions!
            var filterField = PropertyHelper<T>.GetProperty(whereSelector).Name + "Id";

            if (whereValue == null)
            {
                innerWhere = string.Format(" where [{0}] is null", filterField);
            }
            else
            {
                innerWhere = string.Format(" where [{0}] = :filterValue", filterField);
            }
        }

        var innerQuery = string.Format("(select [{0}], row_number() over (order by {0}) as RowNum from [{1}]{2}) X", keyField, entityType, innerWhere);

        var outerQuery = string.Format("select RowNum from {0} where {1} = :keyValue", innerQuery, keyField);

        var query = _session
            .CreateSQLQuery(outerQuery)
            .SetParameter("keyValue", keyValue);

        if (whereValue != null)
        {
            query = query.SetParameter("filterValue", whereValue.Id);
        }

        var sqlRowNumber = query.UniqueResult<long>();

        // The row_number() function is one-based. Our index should be zero-based.
        sqlRowNumber -= 1;

        return sqlRowNumber;
    }

    public long GetIndexOf<TUnique>(T entity, Expression<Func<T, TUnique>> uniqueSelector)
    {
        return GetIndexOf(entity, uniqueSelector, null, (DomainEntityBase)null);
    }

    public long GetIndexOf<TUnique, TWhere>(T entity, Expression<Func<T, TUnique>> uniqueSelector, Expression<Func<T, TWhere>> whereSelector) where TWhere : DomainEntityBase
    {
        return GetIndexOf(entity, uniqueSelector, whereSelector, whereSelector.Compile()(entity));
    }
}

public abstract class DomainEntityBase
{
    public virtual Guid Id { get; protected set; }
}

你像这样使用它:
...

public class Book : DomainEntityBase
{
    public virtual string Title { get; set; }
    public virtual Category Category { get; set; }
    ...
}

public class Category : DomainEntityBase { ... }

public class BookRepository : RepositoryBase<Book> { ... }

...

var repository = new BookRepository();
var book = ... a persisted book ...

// Get the index of the book, sorted by title.
var index = repository.GetIndexOf(book, b => b.Title);

// Get the index of the book, sorted by title and filtered by that book's category.
var indexInCategory = repository.GetIndexOf(book, b => b.Title, b => b.Category);

正如我所说,这对我有用。随着我的前进,我肯定会调整它。天啊。

现在,如果 OP 自己解决了这个问题,那么我很乐意看到他的解决方案! :-)

关于nhibernate - ROW_NUMBER() 和 nhibernate - 查找项目的页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1998560/

相关文章:

nhibernate - NHibernate Projections.Max 如何处理空表?

c# - DTO 和 Entity 是否都应该有输入验证

sql - 需要使用 row_number() 从表中删除重复记录

sql - 在 select 语句中动态对不同的 sql 行进行编号

NHibernate:实体和同一查询中可能的子类的查询条件

sql-server - NHibernate - 必须更改保存顺序才能满足数据库约束吗?

linux - Linux 内核中的 x86 分页与 mmu

ipad - UICollectionView 在覆盖 scrollViewWillEndDragging 时并不总是动画减速

Windows 大页面支持 2MB 以外的吗?

sql-server - 如何仅选择前 ROW_NUMBER 与 SUM 组合