NHibernate、数据绑定到DataGridView、延迟加载和会话管理-需要建议吗

NHibernate、数据绑定到DataGridView、延迟加载和会话管理-需要建议吗,nhibernate,data-binding,session,datagridview,lazy-loading,Nhibernate,Data Binding,Session,Datagridview,Lazy Loading,我的主应用程序表单(WinForms)有一个DataGridView,它使用数据绑定和Fluent NHibernate显示来自SQLite数据库的数据。此表单在应用程序运行的整个过程中都处于打开状态 出于性能原因,我为所有DB访问设置了DefaultLazy.Always()约定 到目前为止,我发现实现这一点的唯一方法是保持主窗体的会话(我们称之为MainSession)始终处于打开状态,这样NHibernate就可以在用户使用网格导航时延迟加载新数据 应用程序的另一部分可以在后台运行,并保存

我的主应用程序表单(WinForms)有一个DataGridView,它使用数据绑定和Fluent NHibernate显示来自SQLite数据库的数据。此表单在应用程序运行的整个过程中都处于打开状态

出于性能原因,我为所有DB访问设置了DefaultLazy.Always()约定

到目前为止,我发现实现这一点的唯一方法是保持主窗体的会话(我们称之为MainSession)始终处于打开状态,这样NHibernate就可以在用户使用网格导航时延迟加载新数据

应用程序的另一部分可以在后台运行,并保存到数据库中。目前,(经过相当多的努力之后),我的方法是调用MainSession.Disconnect(),为每次保存创建一个一次性会话,并在完成保存后调用MainSession.Reconnect()。否则SQLite将抛出“数据库文件已锁定”异常

到目前为止,这似乎工作得很好,但过去的经验让我对长时间保持会话打开感到紧张(当我尝试使用单个会话进行保存和加载时,遇到了性能问题—缓存已满,并且陷入了所有问题—请参阅)

所以,我的问题是——这是一个好的方法,还是我正在考虑未来的问题

如果这是一个糟糕的方法,有什么替代方案?我曾经考虑过在用户使用网格导航时打开和关闭我的主会话,但我不知道该怎么做——从网格中钩住可能导致延迟加载的每个事件

我有一种烦人的感觉,即试图以这种方式管理自己的会话从根本上说是错误的方法,但不清楚什么是正确的方法

编辑

我问这个问题已经一年多了……事实证明,在应用程序的生命周期中保持主会话打开确实会导致性能问题。

最近NH的用户似乎多了很多,所以-有人想建议一个更好的方法吗?是的,又是我。;-)
偶然发现你的新问题让我想起以下几点:你是否理解延迟加载的原理,或者你是否将延迟加载误认为分页?NHibernate还为此提供了功能

如果您只想在网格中显示一些定义的属性,这些属性当然在对象图中,那么我认为您应该使用“获取连接”立即检索整个数据。如果数据的行数太高,您可以考虑,据我所知,使用DataGridView和绑定也是可能的。
延迟加载会导致多个数据库调用——在您的情况下,我认为每行至少有一个。这似乎不是性能最好的解决方案。

如果您使用的是FetchType.Join分页,那么您可以摆脱长时间运行的会话,所有问题都应该得到解决。那怎么样?

我有一个项目,其中有一个主网格供选择

我有一个类在集合中翻页,每当我有新的页面时,我都调用session.Clear()

class MyList : IList<Data>
{
    private int _pagesize = 50;
    private int _session;     // from ctor

    private int _firstresult = int.MinValue;
    private IList<Data> cached;

    public Data this[int index]
    get
    {
        if (!index.Between(_firstresult, _firstresult + cached.Count))
        {
            _firstresult = index;
            GetData();
        }
        if (!index.Between(_firstresult, _firstresult + cached.Count))
            throw new IndexOutOfRangeException();

        return cachedData[index - _firstresult];
    }

    void GetData()
    {
        Session.Clear();

        cached = Session.QueryOver<Data>()
            .Skip(_firstresult)
            .Take(_pagesize)
            .List();
    }
}
类MyList:IList
{
私有int_pagesize=50;
private int _session;//来自ctor
私有int _firstresult=int.MinValue;
私有IList缓存;
公共数据此[int索引]
得到
{
如果(!index.Between(_firstresult,_firstresult+cached.Count))
{
_firstresult=指数;
GetData();
}
如果(!index.Between(_firstresult,_firstresult+cached.Count))
抛出新的IndexOutOfRangeException();
返回cachedData[index-_firstresult];
}
void GetData()
{
Session.Clear();
cached=Session.QueryOver()
.Skip(_firstresult)
.Take(_pagesize)
.List();
}
}

如果您需要数据绑定,可以实现IBindingList

嘿,zoidbeck!谢谢你的建议和链接。我知道DataGridView有一个“虚拟”模式,可以处理分页,所以如果我在保持会话始终打开时遇到问题,那么这可能是一个可行的选择。