好的,我将把它作为答案发布,因为它主要是在做我想要的。但是,我想要一些反馈,也可能是迄今为止我对解决方案的一个警告的答案:
我创建了一个名为 IPagedList 的接口。
public interface IPagedList<T> : IList<T>, ICollection
{
IList<T> GetPagedList(int pageNo, int pageSize);
}
然后创建了一个从 IPagedList 继承的基类:
public class PagedList<T> : IPagedList<T>
{
private List<T> _collection = new List<T>();
public IList<T> GetPagedList(int pageNo, int pageSize)
{
return _collection.Take(pageSize).Skip((pageNo - 1) * pageSize).ToList();
}
public int IndexOf(T item)
{
return _collection.IndexOf(item);
}
public void Insert(int index, T item)
{
_collection.Insert(index, item);
}
public void RemoveAt(int index)
{
_collection.RemoveAt(index);
}
public T this[int index]
{
get
{
return _collection[index];
}
set
{
_collection[index] = value;
}
}
public void Add(T item)
{
_collection.Add(item);
}
public void Clear()
{
_collection.Clear();
}
public bool Contains(T item)
{
return _collection.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_collection.CopyTo(array, arrayIndex);
}
int Count
{
get
{
return _collection.Count;
}
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
return _collection.Remove(item);
}
public IEnumerator<T> GetEnumerator()
{
return _collection.GetEnumerator();
}
int ICollection<T>.Count
{
get { return _collection.Count; }
}
IEnumerator IEnumerable.GetEnumerator()
{
return _collection.GetEnumerator();
}
public void CopyTo(Array array, int index)
{
T[] arr = new T[array.Length];
for (int i = 0; i < array.Length ; i++)
{
arr[i] = (T)array.GetValue(i);
}
_collection.CopyTo(arr, index);
}
int ICollection.Count
{
get { return _collection.Count; }
}
// The IsSynchronized Boolean property returns True if the
// collection is designed to be thread safe; otherwise, it returns False.
public bool IsSynchronized
{
get
{
return false;
}
}
public object SyncRoot
{
get
{
return this;
}
}
}
然后,我为 NHibernate 创建一个 IUserCollectionType 以用作自定义集合类型,并将继承自 PersistentGenericBag 的 NHPagedList、IPagedList 作为实际集合本身。我为它们创建了两个单独的类,因为 IUserCollectionType 的使用似乎对要使用的实际集合没有任何影响,所以我将这两个逻辑分开。以下代码用于上述两个:
public class PagedListFactory<T> : IUserCollectionType
{
public PagedListFactory()
{ }
#region IUserCollectionType Members
public bool Contains(object collection, object entity)
{
return ((IList<T>)collection).Contains((T)entity);
}
public IEnumerable GetElements(object collection)
{
return (IEnumerable)collection;
}
public object IndexOf(object collection, object entity)
{
return ((IList<T>)collection).IndexOf((T)entity);
}
public object Instantiate(int anticipatedSize)
{
return new PagedList<T>();
}
public IPersistentCollection Instantiate(ISessionImplementor session, ICollectionPersister persister)
{
return new NHPagedList<T>(session);
}
public object ReplaceElements(object original, object target, ICollectionPersister persister,
object owner, IDictionary copyCache, ISessionImplementor session)
{
IList<T> result = (IList<T>)target;
result.Clear();
foreach (object item in ((IEnumerable)original))
{
result.Add((T)item);
}
return result;
}
public IPersistentCollection Wrap(ISessionImplementor session, object collection)
{
return new NHPagedList<T>(session, (IList<T>)collection);
}
#endregion
}
NHPagedList 下一个:
public class NHPagedList<T> : PersistentGenericBag<T>, IPagedList<T>
{
public NHPagedList(ISessionImplementor session) : base(session)
{
_sessionImplementor = session;
}
public NHPagedList(ISessionImplementor session, IList<T> collection)
: base(session, collection)
{
_sessionImplementor = session;
}
private ICollectionPersister _collectionPersister = null;
public NHPagedList<T> CollectionPersister(ICollectionPersister collectionPersister)
{
_collectionPersister = collectionPersister;
return this;
}
protected ISessionImplementor _sessionImplementor = null;
public virtual IList<T> GetPagedList(int pageNo, int pageSize)
{
if (!this.WasInitialized)
{
IQuery pagedList = _sessionImplementor
.GetSession()
.CreateFilter(this, "")
.SetMaxResults(pageSize)
.SetFirstResult((pageNo - 1) * pageSize);
return pagedList.List<T>();
}
return this
.Skip((pageNo - 1) * pageSize)
.Take(pageSize)
.ToList<T>();
}
public new int Count
{
get
{
if (!this.WasInitialized)
{
return Convert.ToInt32(_sessionImplementor.GetSession().CreateFilter(this, "select count(*)").List()[0].ToString());
}
return base.Count;
}
}
}
您会注意到它将检查集合是否已初始化,以便我们知道何时检查数据库中的分页列表或何时仅使用当前内存中的对象。
现在您可以开始了,只需将模型上的当前 IList 引用更改为 IPagedList,然后将 NHibernate 映射到新的自定义集合,使用流畅的 NHibernate 如下,您就可以开始了。
.CollectionType<PagedListFactory<Recipient>>()
这是此代码的第一次迭代,因此需要进行一些重构和修改才能使其完美。
目前我唯一的问题是它不会按照映射文件建议的父子关系的顺序获取分页项目。我在地图上添加了一个 order-by 属性,它只是不会注意它。与每个查询中的任何其他 where 子句一样,没有问题。有谁知道为什么会发生这种情况以及周围是否存在?如果我不能解决这个问题,我会很失望。