我的第一个(流畅的)nhibernate查询初始化[类型]失败时出现错误...没有会话或会话被关闭 [英] I get an error in my first (fluent) nhibernate query Initializing[type]-failed... no session or session was closed

查看:159
本文介绍了我的第一个(流畅的)nhibernate查询初始化[类型]失败时出现错误...没有会话或会话被关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始使用NHibernate,使用流畅的NHibernate创建了我的映射,如下所示:

I just started with NHibernate, created my mappings using fluent NHibernate as follows:

public class CustomerMap : ClassMap<Customer>
{
    public CustomerMap()
    {
        Id(x => x._id, "Id");
        Map(x => x._KdNr, "KdNr");
        Map(x => x._Name, "Name");
        HasMany(x => x._Contact)
            .Table("Contacts")
            .KeyColumn("FKCustomerID")
            .LazyLoad();
    }
}


public class ContactMap : ClassMap<Contact>
{
    public ContactMap()
    {
        Id(x => x._id, "Id");
        Map(x => x._Name, "Name");
    }
}

保存新记录也可以:

    public static void AddCustomer(Customer cust)
    {
        using (var session = SessionFactory.Instance.OpenSession())
        {
            session.Save(cust);
            session.Save(cust._Contact);
            session.Flush();
        }
    }

然后,我尝试选择使用以下方法添加的客户:

Then I tried to select the customer I added using:

        using (var session = SessionFactory.Instance.OpenSession())
        {
            try
            {
                var v = session.CreateQuery("from Customer").List<Customers>();
                return (List<Customer>)v;
            }
            catch
            {
                session.Close();
                throw;
            }
            finally
            {
                session.Disconnect();
            }
        }
    }

也很好地加载了Customer,但是未引用内部联系人并出现以下错误:

The Customer also is loaded fine, but the contacts inside are not referenced with the following error:

初始化[fnh.DataModel.Customer#d2f2d1c5-7d9e-4f77-8b4f-9e200088187b]-失败 延迟初始化角色集合: fnh.DataModel.Kunde._Contact,没有会话或会话被关闭

Initializing[fnh.DataModel.Customer#d2f2d1c5-7d9e-4f77-8b4f-9e200088187b]-failed to lazily initialize a collection of role: fnh.DataModel.Kunde._Contact, no session or session was closed

但是我无法理解错误的出处,因为在执行我的HQL错误后会话已关闭...

But I cannot understand where the error comes from because the session is closed after executing my HQL error...

推荐答案

问题是联系人是延迟加载的,即.在初始查询中不会从数据库中获取该集合.我假设您是将对象直接传递到视图,而不是使用viewmodel?您有几种选择,每种都有其缺点.

The problem is that the contacts are lazy loaded, ie. the collection is not fetched from the database in the initial query. I presume that you are passing the objects directly to the view rather than using a viewmodel? You have a few options, each have their drawbacks.

  1. 在查看时保持会话打开 正在处理(所谓的打开" 会话中的视图方法).您可能正在此时关闭控制器中的NH会话吗?

  1. Keep the session open while the view is being process (so called Open Session In View approach). You are probably closing the NH session in the controler at the moment right?

急于加载整个对象图 在上使用.Not.Lazyload() 联系人. (不推荐)

Eager load the whole object graph using .Not.Lazyload() on the contacts. (Not recommended)

将所需的所有数据复制到视图中 在控制器中建模,并通过 对此观点.使用自动映射器可以帮助您解决这个问题.

Copy all the data you need to a view model in the controller, and pass this to the view. Use automapper to help you with this.

根据评论进行更新:

让集合延迟加载仍然有很大的好处.当然,在这种情况下,如果需要使用它们,您就不会从客户对象上的延迟加载联系人中受益.但是在另一种情况下,您可能只需要客户名称和ID-并且可以放心,这不会产生带有联接等的大查询.

There is still great benefit in leaving collections lazy loaded. Sure, in this context you don't benefit from lazy loaded contacts on the customer object, becase you need to use them. But in another context you might only need the customer name and Id - and you can rest assured that this wont generate a big query with joins etc.

要在View中使用Open Session,您不必显式地将会话传递给视图,而只需像以前一样传递对象,但是将会话保持打开状态-NH会在尝试访问时自动生成一个新查询联系人集合. (因为客户对象仍被附加"到幕后的公开会议中,所以该方法有效).唯一的区别是您需要关闭不在控制器中的会话(当前正在使用.close()显式关闭或使用"using"隐式关闭该会话).关于在哪里打开和关闭会话-有不同的方法:

To utilize Open Session in View you don't have to pass your session to the view explicitly, rather you just pass the object as before, but leave the session open - NH will automatically generate a new query when you try to access the contacts collection. (This works becuase the customer object is still 'attached' to an open session behind the scenes). The only difference here is that you need to close the session not in the controller (where it is currently being closed explicitly with the .close() or implicitly with 'using'). Regarding where to open and close the session - there are different approaches:

  • 在global.asax中-在Application_BeginRequest中打开,然后在Application_EndRequest中关闭(请参阅:

  • In the global.asax - open in Application_BeginRequest and close in Application_EndRequest (see: this article) I'd recomend starting with this for the sake of simplicity if you want to do Open Session in View.

在http模块中(与最后一个模块基本相同,但是是模块化的)(请参阅

In a http module (basically the same as the last, but modularised) (see this article)

对于这最后两个,您可能会想:但这将意味着为每个页面请求创建一个会话!" -您是正确的,但是实际上有多少页不去数据库?创建会话工厂后,会话创建轻巧.

  • 使用装饰动作方法的属性(基本上与后两个动作相同,但是通过这种方式,您可以选择打开NH会话的动作).如果要在操作完成后关闭会话,请在OnActionExecuted中关闭会话.如果要在视图中打开会话,请在OnResultExecuted中关闭.

当然,很多人不喜欢View中的Open Session,因为您无法控制仅在控制器中生成的查询-视图触发了许多查询,这可能导致无法预测的性能.

Of course, many people don't like Open Session in View, becuase you cannot control what queries are being generated purely in the controller - the view is triggering many queries, this can cause unpredictable performance.

3与2根本不同,因为在不需要惰性加载的集合的情况下,不会从数据库中获取它.例如,在这种情况下,您可能会复制带有完整对象图的ViewModel,但在另一种情况下,您可能会使用仅带有客户名称和ID的ViewModel-在这种情况下,不必执行contact集合的联接.我认为3是做事的正确方法-但最终会创建更多对象(由于视图对象).

3 is subtely different from 2, because in situations where you don't need the lazy loaded collection it is not fetched from the DB. For instance, in this case you might be copying to a ViewModel with the full object graph, but in another situation you might use a ViewModel with just the customer name and Id - in this case the joins for the contacts collection would not needlessly be executed. In my opinion 3 is the proper way to do things - but you end up creating many more objects (becuase of the view objects).

这篇关于我的第一个(流畅的)nhibernate查询初始化[类型]失败时出现错误...没有会话或会话被关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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