NHibernate 一对多

One to many in NHibernate

我有两个模型,DerbySpawn 和 DerbyArena

DerbyArena.cs

public class DerbyArena
{
        public DerbyArena()
        {
            DerbySpawns = new List<DerbySpawn>();
        }
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual short MaxPlayers { get; set; }
        public virtual short MinPlayers { get; set; }
        public virtual short Interior { get; set; }
        public virtual short Model { get; set; }
        public virtual float MinZ { get; set; }
        public virtual IList<DerbySpawn> DerbySpawns { get; set; }
}

DerbySpawn.cs

public class DerbySpawn
{ 
     public virtual int SpawnId { get; set; }
     public virtual float SpawnX { get; set; }
     public virtual float SpawnY { get; set; }
     public virtual float SpawnZ { get; set; }
     public virtual float SpawnA { get; set; }
     public virtual DerbyArena DerbyArena { get; set; }
 }

还有我的映射

德比竞技场地图

 public class DerbyArenaMap : ClassMap<DerbyArena>
 {
          public DerbyArenaMap()
          {
                Id(x => x.Id);
                Map(x => x.Interior);
                Map(x => x.MaxPlayers);
                Map(x => x.MinPlayers);
                Map(x => x.Model);
                Map(x => x.Name);
                Map(x => x.MinZ);
                HasMany<DerbySpawn>(x => x.DerbySpawns)
                    .Inverse()
                    .AsBag();
                Table("DerbyArens");


          }
 }

DerbySpawnMap

public class DerbySpawnMap : ClassMap<DerbySpawn>
{
        public DerbySpawnMap()
        {
            Id(x => x.SpawnId);
            Map(x => x.SpawnX);
            Map(x => x.SpawnY);
            Map(x => x.SpawnZ);
            Map(x => x.SpawnA);
            References(x => x.DerbyArena);
            Table("DerbySpawns");

        }
   }

在 DerbyArens 中,列 Id 为主键,自增

在 DerbySpawns 列 SpawnId 是主键,自动递增,列 DerbyArena 是外键 与 table DerbyArens 的关系,列 Id

我select通过这个代码随机竞技场:

using (ISession session = DbSession.OpenSession())
{
      arena = (from x in session.Query<DerbyArena>() orderby Guid.NewGuid() select x).First();
}

但是当我使用

Console.Write(arena.DerbySpawns[y].SpawnX + " " + arena.DerbySpawns[y].SpawnY + " " + arena.DerbySpawns[y].SpawnZ + " " + arena.DerbySpawns[y].SpawnA);

我遇到异常

NHibernate.LazyInitializationException: Initializing[SSS.Models.DerbyArena#1]-failed to lazily initialize a collection of role: SSS.Models.DerbyArena.DerbySpawns, no session or session was closed

DbSession.cs

public static class DbSession
{
    private static ISessionFactory _sessionFactory;
    public static ISessionFactory Factory
    {
        get { return _sessionFactory ?? (_sessionFactory = CreateSessionFactory()); }
    }
    public static ISession OpenSession()
    {
        return Factory.OpenSession();
    }

    private static ISessionFactory CreateSessionFactory()
    {
        return Fluently.Configure()
            .Database(
                MySQLConfiguration.Standard
                    .ConnectionString("connectionstring(thiswork)")
            //Your connectionstring goes here.
            )
            .Mappings(m =>
                m.FluentMappings.AddFromAssemblyOf<DbMappings>())
            .ExposeConfiguration(TreatConfiguration)
            .BuildSessionFactory();
    }


    private static void TreatConfiguration(Configuration configuration)
    {
        var update = new SchemaUpdate(configuration);
        update.Execute(false, true);
    }

}

很可能您在 using (ISession ... 之外访问 DerbySpawns,而在其上启用了延迟加载。

由于session被using释放,延迟加载不会发生

您必须确保会话关闭后不会发生延迟加载。

  1. using (ISession ... 内完成整个工作单元。
  2. 或在 using (ISession ... 中获取您的依赖项:
    • 使用预先加载(.FetchMany 在您的查询中)。当心,结合您的 'random sort',这很可能会导致您 this bug (tagged as EF but I am quite confident NH would have it too), forcing you to use a more complex 'random sort'.
    • 或者通过访问属性来触发延迟加载。如果这只是一个 'dummy' 访问,那就太脏了...
    • 或者在映射中强制获取此集合(影响所有 DerbyArena 加载,也很可能导致前面提到的错误)。