Après avoir examiné les sources pour NHibernate, je suis assez sûr qu'il n'y existe pas une telle fonctionnalité.
Cela ne me dérangerait pas, cependant, que quelqu'un me prouve le contraire.
Dans mon propre mise en, j'ai résolu ce problème en écrivant une méthode qui prend quelques lambdas (représentant la colonne de clé, et une colonne en option pour filtrer - toutes les propriétés d'une entité de domaine spécifique). Cette méthode construit ensuite le sql et appelle session.CreateSQLQuery(...).UniqueResult();
Je ne prétends pas que c'est une solution polyvalente. Pour éviter l'utilisation de chaînes magiques, j'ai emprunté une copie de PropertyHelper<T>
de this answer.
Voici le code:
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; }
}
Et vous l'utiliser comme ceci:
...
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);
Comme je l'ai dit, cela fonctionne pour moi. Je vais certainement le modifier au fur et à mesure que j'avance. YMMV.
Maintenant, si l'OP a résolu cela lui-même, alors j'aimerais voir sa solution! :-)
C'est quelque chose que je cherche aussi. Lorsque vous avez posté cette question, j'attendais avec impatience toutes les réponses ... Après avoir regardé les sources de NHibernate, je suis à peu près sûr qu'il n'existe pas de telle fonctionnalité. –
En outre, la syntaxe quelque peu maladroite de la fonction row_number() rend probablement difficile l'implémentation de cette fonctionnalité. –
Considéreriez-vous une solution qui ne soit pas basée sur ICriteria et spécifique à SQL Server? (La solution ne nécessite pas d'entrée de chaînes magiques, est un peu limitée en fonctionnalités mais profite de vos entités de domaine ...) –