NHibernate - LAZY LOADING PROBLEM -Initializing [] - 无法初始化代理 - 没有会话。“}

时间:2011-09-28 13:49:47

标签: c# session fluent-nhibernate lazy-loading

您好我使用Fluent NHibernate,我对Lazy Loading感到困惑。

  1. 我查询了数据库中的对象
  2. 修改过的对象属性
  3. 使用此对象更新数据库
  4. 这是代码:

    public class Credentials
    {
        public virtual int Id { get; set; }
        public virtual string Nick { get; set; }
        public virtual string Password { get; set; }
    }
    
    public class CredentialsMap : ClassMap<Credentials>
    {
        public CredentialsMap()
        {
            Id(x => x.Id);
            Map(x => x.Nick).Column("NICK");
            Map(x => x.Password).Column("PASSWORD");
            Table("R_CREDENTAILS");
        }
    }
    
    public class Status
    {
        public virtual int Id { get; set; }
        public virtual string Msg { get; set; }
        public virtual DateTime AddTime { get; set; }
    }
    
    public class StatusMap : ClassMap<Status>
    {
        public StatusMap()
        {
            Id(x => x.Id);
            Map(x => x.Msg).Column("MESSAGE");
            Map(x => x.AddTime).Column("ADD_TIME");
            Table("R_STATUS");
        }
    }
    
    public class Account
    {
        public virtual int Id { get; set; }
        public virtual string SelfNick { get; set; }
        public virtual Credentials Credentials { get; set; }
        public virtual Status Status { get; set; }
    }
    
    public class AccountMap : ClassMap<Account>
    {
        public AccountMap()
        {
            Id(x => x.Id);
            Map(x => x.SelfNick).Column("SELF_NICK");
            References(x => x.Credentials)
                .Column("CREDENTIALS_ID")
                .ForeignKey();
            References(x => x.Status)
                .Column("STATUS_ID")
                .ForeignKey();
            Table("R_ACCOUNTS");
        }
    }
    

    NHibernate配置类:

    public class NHiberanteHelper
    {
        private static ISessionFactory _sessionFactory;
    
        private static ISessionFactory SessionFactory
        {
            get
            {
                if (_sessionFactory == null)
                    InitializeSessionFactory();
    
                return _sessionFactory;
            }
        }
    
        private static void InitializeSessionFactory()
        {
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008
                              .ConnectionString(
                                   @"Server=TEST\SQLEXPRESS;Database=SimpleNHibernate;Trusted_Connection=True;").
                                   ShowSql()
                                  )
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Account>().Conventions.Add( DefaultCascade.All()))
                .ExposeConfiguration(cfg => new SchemaUpdate(cfg).Execute(true, true))
                .BuildSessionFactory();
        }
    
        public static ISession OpenSession()
        {
            return SessionFactory.OpenSession();
        }
    }
    

    以下是用法:

        public class LoginDbHelper
        {
            public static Account GetAccount(string nick)
            {
                using (var session = NHiberanteHelper.OpenSession())
                {
                    var account = (session.QueryOver<Account>()
                        .JoinQueryOver<Credentials>(a => a.Credentials)
                        .Where(c => c.Nick == nick));
    
                    if (account != null)
                        return account.SingleOrDefault();
    
                    return null;
                }
            }
    
            public static void SaveOrUpdateAccount(Account account)
            {
                using (var session = NHiberanteHelper.OpenSession())
                {
                    using (var trans = session.BeginTransaction())
                    {
                        session.SaveOrUpdate(account);
                        trans.Commit();
                    }
                }
            }
       }
    

    问题代码:

    var actualAccount = LoginDbHelper.GetAccount(nick);
    
    //modify
    actualAccount.Status.Msg = "New status 2";
    actualAccount.Status.AddTime = DateTime.Now;
    
    
    LoginDbHelper.SaveOrUpdateAccount(account);
    

    我收到此错误:

    {"Initializing[NHibernateSample1.Status#1]-Could not initialize proxy - no Session."}
    

    堆栈跟踪:

     at NHibernate.Proxy.AbstractLazyInitializer.Initialize() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 113
       at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation() in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Proxy\AbstractLazyInitializer.cs:line 191
       at NHibernate.ByteCode.Castle.LazyInitializer.Intercept(IInvocation invocation) in d:\CSharp\NH\NH\nhibernate\src\NHibernate.ByteCode.Castle\LazyInitializer.cs:line 61
       at Castle.DynamicProxy.AbstractInvocation.Proceed()
       at Castle.Proxies.StatusProxy.set_Msg(String value)
       at NHibernateSample1.Program.Main(String[] args) in E:\C# PROJECTS\Samples\SimpleNHibernateClient\NHibernateSample1\Program.cs:line 215
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    

    我谷歌它,我认为它是由懒惰加载引起的,因为在方法GetAccount中我关闭了SESSION。 这是我对NHibernate的第一次尝试,所以如何才能正确解决这个问题? 如果是的话可以禁用LAZY LOADING怎么办?

5 个答案:

答案 0 :(得分:8)

你是对的。因为NHibernate会话在GetAccount方法中关闭(它只在using语句的范围内打开),所以不能在此方法之外加载其他对象。有两个可能的修复:

  1. 在操作级别(即在包含问题代码的方法中)创建会话,然后在get&amp;中使用此会话。保存方法。您可以通过将其作为参数传递给方法来使用会话。
  2. 将对象更改为不使用延迟加载。您可以通过将.Not.LazyLoad()添加到流畅映射中的Status对象来执行此操作。

答案 1 :(得分:4)

我发现关闭延迟加载的最简单方法是添加DefaultLazy约定,即:

.Conventions.Add( DefaultCascade.All(), DefaultLazy.Never() )

请注意,启用延迟加载(DefaultLazy.Always())可以真正提高性能,具体取决于您的应用程序。

缺点是,在您可以延迟加载实体中的其余数据之前,您必须打开会话。根据我的经验,支持延迟加载的会话管理是NHibernate的一大难点。

答案 2 :(得分:0)

您可以在LoginDbHelper.GetAccount(...)方法中打开和关闭会话 尝试在方法之外创建并打开会话,并将其作为方法参数传递,例如:

    // method
    public static Account GetAccount(string nick, ISession session) 
    {   
     var account = (session.QueryOver<Account>().JoinQueryOver<Credentials>(a => a.Credentials).Where(c => c.Nick == nick));   

           if (account != null)                      
            return account.SingleOrDefault();                    
    return null;  
    }

// usage
    var actualAccount = LoginDbHelper.GetAccount(nick);   
    actualAccount.Status.AddTime = DateTime.Now;   
    using (var session = NHiberanteHelper.OpenSession())  

    LoginDbHelper.SaveOrUpdateAccount(account, session); 

答案 3 :(得分:0)

作为解决方法,您可以替换以下代码:

$ awk -F";" ' /^cell/ { print ; next } { a=$1; getline; print $1, a ";" } ' nehac.txt
cell1
input C;
input Cp;
input D;
output Q;
output Qn;
cell2
input Cp;
input D;
output Q;
cell3
input A1;
input B;
input B1;
output S;
output Sn;
$

使用以下代码:

if (account != null)
    return account.SingleOrDefault();

答案 4 :(得分:0)

如果您的会话完全打开但您调用了 Session.Clear(),也会发生这种情况。不要那样做。