实施IPagedList< T>在使用NHibernate我的模型 [英] Implementing IPagedList<T> on my models using NHibernate

查看:207
本文介绍了实施IPagedList< T>在使用NHibernate我的模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经使用NHibernate和创建一对多关系的对象,当很多增长非常大的它可以显着减慢时上找到。现在,我确实有我的仓库方法收集该类型的分页的IList,不过,我想preFER会对模型,以及这些方法,因为这往往是在其他开发商先来看看收集的子对象列表

I have found when using NHibernate and creating a one to many relationship on an object that when the many grows very large it can slow down dramatically. Now I do have methods in my repository for collecting a paged IList of that type, however I would prefer to have these methods on the model as well because that is often where other developers will look first to gather the list of child objects.

例如

RecipientList.Recipients将返回列表中的每一个收件人。

RecipientList.Recipients will return every recipient in the list.

我想实现的方式来使用preferably一个接口,但真的什么,不会强迫到模型的类型化的关系我的模型我所有的OEN中添加分页到许多关系。例如,它会是不错的有以下接口:

I would like to implement a way to add paging on all of my oen to many relationships in my models using preferably an interface but really anything that won't force a typed relationship onto the model. For example it would be nice to have the following interface:

public interface IPagedList<T> : IList<T>
{
    int Count { get; }
    IList<T> GetPagedList(int pageNo, int pageSize);
    IList<T> GetAll();
}

然后能够在code使用它...

Then being able to use it in code...

IList<Recipient> recipients = RecipientList.Recipients.GetPagedList(1, 400);

我一直在努力想办法做到这一点不给模型中的分页任何意识,但我打的那一刻我的头撞墙。

I have been trying to think of ways to do this without giving the model any awareness of the paging but I'm hitting my head against a brick wall at the moment.

反正我有可以实现在NHibernate的确实为IList的,目前惰性加载方式类似的界面?我没有NHibernate的的足够的知识,知道了。

Is there anyway I can implement the interface in a similar way that NHibernate does for IList and lazyloading currently? I don't have enough knowledge of NHibernate to know.

是实现这甚至是一个好主意?你的想法会pciated作为是家中唯一的.NET开发我有没有一个反弹的想法了AP $ P $。

Is implementing this even a good idea? Your thoughts would be appreciated as being the only .NET developer in house I have no-one to bounce ideas off.

更新

以下职位指出我的NHibernate的自定义集合属性,这将很好地工作。但是我不能确定最好的办法就是去解决这算什么,我试图从PersistentGenericBag继承使之具有没有太多工作的IList的基本功能相同,但是我不能确定如何收集基础上,ISessionImplementor对象的列表。我需要知道如何可以:

The post below has pointed me to the custom-collection attribute of NHibernate, which would work nicely. However I am unsure what the best way is to go around this, I have tried to inherit from PersistentGenericBag so that it has the same basic functionality of IList without much work, however I am unsure how to gather a list of objects based on the ISessionImplementor. I need to know how to either:


  • 获取某种形式的ICriteria细节对于当前的IList,我待填充

  • 获取映射细节与相关的IList的特定属性,所以我可以创建自己的ICriteria。

不过我不确定我是否能做到上述任何的?

However I am unsure if I can do either of the above?

感谢

推荐答案

好吧我要去,因为它做主要是我想后这是一个答案。不过,我想一些反馈,也可能是回答我的解决方案的一个警告迄今:

Ok I'm going to post this as an answer because it is doing mostly what I wanted. However I would like some feedback and also possibly the answer to my one caveat of the solution so far:

我已经创建了一个名为IPagedList的接口。

I've created an interface called IPagedList.

public interface IPagedList<T> : IList<T>, ICollection
{

    IList<T> GetPagedList(int pageNo, int pageSize);

}

然后创建它从IPagedList继承的基类:

Then created a base class which it inherits from 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;
        }
    }
}

我然后创建一个IUserCollectionType NHibernate的为自定义集合类型和NHPagedList从PersistentGenericBag,IPagedList继承与实际集合本身使用。我创建了两个单独的类他们,因为它似乎像使用IUserCollectionType的人在所有要使用的实际收集没有影响,所以我保持逻辑独立的两片。 code以下两个以上的:

I then create an IUserCollectionType for NHibernate to use as the custom collection type and NHPagedList which inherits from PersistentGenericBag, IPagedList as the actual collection itself. I created two seperate classes for them because it seemed like the use of IUserCollectionType had no impact on the actual collection to be used at all, so I kept the two pieces of logic seperate. Code below for both of the above:

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下一:

NHPagedList next:

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;
        }
    }

}

您会发现,它会检查如果集合已初始化与否,让我们知道什么时候检查数据库的分页列表或何时只使用当前内存中的对象。

You will notice that it will check to see if the collection has been initialized or not so that we know when to check the database for a paged list or when to just use the current in memory objects.

现在你已经准备好,简单地改变你的模型您当前的IList引用视为IPagedList然后映射NHibernate的新的自定义集合,用流利的NHibernate的是下面的,你准备好去。

Now you're ready to go, simply change your current IList references on your models to be IPagedList and then map NHibernate to the new custom collection, using fluent NHibernate is the below, and you are ready to go.

.CollectionType<PagedListFactory<Recipient>>()

这是这个code首次itteration所以它需要一些重构和修改得到完美。

This is the first itteration of this code so it will need some refactoring and modifications to get it perfect.

我此刻唯一的问题是,它不会得到在该映射文件建议为父子关系的顺序被寻呼的项目。我添加了一个order-by属性的地图,它只是不会注意它。凡任何其他WHERE子句在每个查询没有问题。没有人有任何想法,为什么这可能发生,如果有无论如何它周围?我会很失望,如果我不解决这个工作了。

My only problem at the moment is that it won't get the paged items in the order that the mapping file suggests for the parent to child relationship. I have added an order-by attribute to the map and it just won't pay attention to it. Where as any other where clauses are in each query no problem. Does anyone have any idea why this might be happening and if there is anyway around it? I will be disappointed if I can't work away around this.

这篇关于实施IPagedList&LT; T&GT;在使用NHibernate我的模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆