简体   繁体   English

NHibernate维护Isession对象的方法

[英]NHibernate approach to maintain Isession object

My code is as below. 我的代码如下。 My problem is when I use NHibernate to retrieve an object that contains a navigation property and try to set a value in that navigation property object it throws an error saying that session does not exist. 我的问题是,当我使用NHibernate检索包含导航属性的对象并尝试在该导航属性对象中设置值时,它抛出一个错误,指出会话不存在。

[The 'f.HIERARCHY.CHANGETIME = DateTime.Now;' ['f.HIERARCHY.CHANGETIME = DateTime.Now;' line inside the main method] 行里面的主要方法]

I understand that this is because when NHibernate tries to fetch the 'HIERARCHY' object the session is already closed inside the repository class 我了解这是因为,当NHibernate尝试获取“ HIERARCHY”对象时,会话已在存储库类中关闭

What I need to know is the standard approach to write the code so that I can still use lazy loading but can access the properties of navigation objects later in the code WITHOUT disabling lazy loading. 我需要知道的是编写代码的标准方法,这样我仍然可以使用延迟加载,但是稍后可以在代码中访问导航对象的属性,而无需禁用延迟加载。

Is it a good approach to always keep the Isession object open? 始终保持Isession对象打开的好方法吗? Most of the code samples i found on internet always opens up a new session at each CRUD operation for each operation and closes it immediately after. 我在Internet上找到的大多数代码示例始终在每个CRUD操作中为每个操作打开一个新会话,并在此之后立即将其关闭。 How do they address the issue of accessing navigation properties later in the code? 他们如何解决稍后在代码中访问导航属性的问题?

 public class NHibernateBaseRepository : IDisposable { private ISessionFactory m_SessionFactory = null; private ISession m_Session = null; public T GetById<T>(long id) { using (ISession session = m_SessionFactory.OpenSession()) { return session.Get<T>(id); } } } public class ROLE { public virtual string RoleComment { get; set; } public virtual HIERARCHY HIERARCHY { get; set; } } public class HIERARCHY_STRUCTURE { public virtual DateTime CHANGETIME{ get; set; } } class Program { static void Main(string[] args) { NHibernateBaseRepository persistenceManager = new NHibernateBaseRepository(); ROLE f = persistenceManager.GetById<ROLE>(34); f.RoleComment = "Test Com"; f.HIERARCHY.CHANGETIME = DateTime.Now; //Throws error persistenceManager.SaveOrUpdateEntitiy<ROLE>(f); } } 

How do they address the issue of accessing navigation properties later in the code? 他们如何解决稍后在代码中访问导航属性的问题?

WITHOUT disabling lazy loading 不禁用延迟加载

Try to use Fetch() method in repository when the session is open. 会话打开时,尝试在存储库中使用Fetch()方法。 For example: 例如:

private IList<Container> ReadContainer()
{
        var modeList = new List<Container>();

        using (var session = DatabaseHelper.OpenSession())
        {
            var tmp = session.Query<Container>().Fetch(items => items.TmcList).ToList();
        }
        return modeList;
    }

Mainly what you need to do is change how you manage the lifetime of your Session object and make it isolated of your single repository method call, this will give you benefits like write and query batching. 主要要做的是更改管理Session对象生命周期的方式,并使它与单个存储库方法调用隔离开来,这将为您带来诸如写入和查询批处理之类的好处。

That means, that you have to define a Session in a more global manner, maybe as a private field in your NHibernateBaseRepository class, instantiate it in the constructor and then implement IDisposable and in the Dispose method, close your session. 这意味着,您必须以更全局的方式定义一个Session,也许将其定义为NHibernateBaseRepository类中的私有字段,然后在构造函数中实例化它,然后实现IDisposable并在Dispose方法中关闭会话。 this way you can do multiple actions (and a more consistent unit of work) on the same session. 这样,您可以在同一会话中执行多个操作(以及更一致的工作单元)。

Some code example: 一些代码示例:

NHibernateBaseRepository class: NHibernateBaseRepository类:

public class NHibernateBaseRepository : IDisposable
{
    private ISession _session;

    public NHibernateBaseRepository ()
    {
        _session = m_SessionFactory.OpenSession(); //session factory should be created once per application lifetime, not per instance.
    }

    public void Dispose()
    {
        _session.Dispose();
    }

    public T GetById<T>(long id)
    {
        return _session.Get<T>(id); 
    }
}

Main method: 主要方法:

static void Main(string[] args)
{
     using(var persistenceManager = new NHibernateBaseRepository())
     {
         ROLE f = persistenceManager.GetById<ROLE>(34);

         f.RoleComment = "Test Com";
         f.HIERARCHY.CHANGETIME = DateTime.Now; //Throws error
         persistenceManager.SaveOrUpdateEntitiy<ROLE>(f);
     }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM