Wpf 每个演示者的会话NHibernate桌面应用程序-未从数据库加载最新数据

Wpf 每个演示者的会话NHibernate桌面应用程序-未从数据库加载最新数据,wpf,nhibernate,session,Wpf,Nhibernate,Session,我正在使用每个演示者的会话编写WPF NHibernate桌面应用程序。我有一个列表视图,显示所有保存的SalesOrders,双击销售订单时还有一个编辑销售订单表单 这些表单中的每一个都有一个会话对象,该对象将持续到表单的生命周期。保存SalesOrder时,它会发布一个事件,通知列表视图重新加载。EditForm肯定会保存到数据库中,ListView肯定会从数据库中进行选择。但是,属于ListViewPresenter的会话没有使用从数据库检索的实体更新其实体。它只返回与在保存任何内容之前首

我正在使用每个演示者的会话编写WPF NHibernate桌面应用程序。我有一个列表视图,显示所有保存的SalesOrders,双击销售订单时还有一个编辑销售订单表单

这些表单中的每一个都有一个会话对象,该对象将持续到表单的生命周期。保存SalesOrder时,它会发布一个事件,通知列表视图重新加载。EditForm肯定会保存到数据库中,ListView肯定会从数据库中进行选择。但是,属于ListViewPresenter的会话没有使用从数据库检索的实体更新其实体。它只返回与在保存任何内容之前首次加载listSession时相同的值

下面是一些最能复制场景的代码:-

        [Test]
    public void SessionPerPresenter()
    {
        //This session is the one that is used to load all salesorders from the      database. It's lifetime is the lifetime of the form but as you double click on an entry in the list to edit it will stay alive longer than the session in the edit form
        ISession listSession = NHibernateHelper.OpenSession();

        SalesOrder order = new SalesOrder("P123435", "ACME");
        order.AddLine(new SalesOrderLine("Beans", 15));
        order.AddLine(new SalesOrderLine("Coke", 24));
        order.AddLine(new SalesOrderLine("Pepsi", 3));
        order.AddLine(new SalesOrderLine("Apples", 4));

        //this session is the equivalent of the one in the Edit Form as soon as the entity is Saved
        //the session is disposed
        using (ISession session = NHibernateHelper.OpenSession())
        {
            session.SaveOrUpdate(order);
            ID = order.SalesOrderID;
        }

        //retrieve all SalesOrders from the database and store them in a list
        IList<SalesOrder> salesOrders = listSession.CreateCriteria<SalesOrder>().List<SalesOrder>();
        foreach (SalesOrder so in salesOrders)
        {
            Console.WriteLine(so.ToString());
        }

        //edit the selected order and update its order code value and resave
        using (ISession session = NHibernateHelper.OpenSession())
        {
            hydratedSalesOrder = session.Get<SalesOrder>(ID);
            hydratedSalesOrder.OrderCode = "1234-5678";
            session.SaveOrUpdate(hydratedSalesOrder);
            session.Flush();
        }

        //re-retrieve the list of orders from the database. Using SQLServer Profiler / NHibernate profiler
        //you can see the query being sent to the database so I don't believe it is in the cache. Indeed, if you run
        //the query directly against the database the value 1234-5678 is returned. Can't work out why
        //the listSession does not have the values read from the database in it but has the values from the
        //original list retrieval.
        salesOrders = listSession.CreateCriteria<SalesOrder>().List<SalesOrder>();
        foreach (SalesOrder so in salesOrders)
        {
            Console.WriteLine(so.ToString());
        }
        listSession.Close()
    }
[测试]
public void SessionPerPresenter()
{
//此会话用于从数据库加载所有SalesOrder。它的生存期是表单的生存期,但当您双击列表中的某个条目进行编辑时,它将比编辑表单中的会话保持活动时间更长
ISession listSession=NHibernateHelper.OpenSession();
销售订单=新销售订单(“P123435”、“ACME”);
AddLine(新的销售订单行(“Beans”,15));
order.AddLine(新销售订单行(“Coke”,24));
order.AddLine(新销售订单行(“百事”,3));
order.AddLine(新的销售订单行(“Apples”,4));
//保存实体后,此会话与编辑表单中的会话等效
//会话被释放
使用(ISession session=NHibernateHelper.OpenSession())
{
会话。保存或更新(顺序);
ID=order.SalesOrderID;
}
//从数据库中检索所有销售订单并将其存储在列表中
IList salesOrders=listSession.CreateCriteria().List();
foreach(销售订单中的销售订单so)
{
Console.WriteLine(so.ToString());
}
//编辑所选订单并更新其订单代码值,然后重新保存
使用(ISession session=NHibernateHelper.OpenSession())
{
hydratedSalesOrder=session.Get(ID);
水合SalesOrder.OrderCode=“1234-5678”;
会话。保存或更新(HydredSalesOrder);
session.Flush();
}
//从数据库中重新检索订单列表。使用SQLServer探查器/NHibernate探查器
//您可以看到查询被发送到数据库,因此我认为它不在缓存中
//直接针对数据库的查询返回值1234-5678。无法找出原因
//listSession中没有从数据库读取的值,但具有从数据库读取的值
//原始列表检索。
salesOrders=listSession.CreateCriteria().List();
foreach(销售订单中的销售订单so)
{
Console.WriteLine(so.ToString());
}
listSession.Close()
}

有人能帮我解决这件事吗?我做错了什么?我错过了什么重要的东西吗?如果它没有查询数据库,我会认为这与一级缓存有关,但这似乎不太可能。

确保实体未被缓存的方法是使用ISession.clear()清除会话。您还可以通过调用
ISession.execute(对象实体)
来逐出单个实体

如果您不确定应用程序中发生了什么,请考虑一个分析工具,如.< /P>


快速提示:在对话框的生命周期中使用会话在没有并发问题的小型应用程序中非常方便,但从长远来看,您会遇到麻烦。会话应迟开早关。

每个表单的会话原因是,我认为使用NHibernate(msdn.microsoft.com/en us/magazine/ee819139.aspx)构建桌面待办应用程序是桌面应用程序的推荐最佳实践。我使用过NHibernate探查器,它肯定在调用数据库,但似乎没有重新加载listSession。打开两个表单时,只能收回在当前表单中编辑的实体。它不会从数据库中重新加载以其他形式修改的实体。在我看来,使用Clear()似乎失去了NHibernate的许多好处。在很多情况下,每个表单的会话都会起作用。当我需要快速的结果时,我会这样做。关于你的评论,那可能是缓存。不要在任何地方都使用Clear(),当然,在需要时使用它。没有更多关于你问题的信息,这是我能给你的唯一建议。对不起。