NHibernate 多个表。 ASP.NETMVC

NHibernate multiple tables. ASP.NET MVC

刚开始在我的 ASP.NET MVC 应用程序中使用 NHibernate。例如,我创建了两个表:Books 和 Chapters。

CREATE TABLE [dbo].[Books] (
    [Id] INT NOT NULL PRIMARY KEY IDENTITY,
    [Title]  NVARCHAR (50) NOT NULL,
    [Author] NVARCHAR (50) NOT NULL,    
);

CREATE TABLE [dbo].[Chapters] (
    [Id] INT NOT NULL PRIMARY KEY IDENTITY,
    [Title]        NVARCHAR (MAX) NOT NULL,
    [Notes]        TEXT           NULL,
    [ChapterIndex] INT            NULL,
    [BookId]       INT            NULL,    
    CONSTRAINT [FK_Chapters_ToTable] FOREIGN KEY (BookId) REFERENCES Books(Id)
);

NHibernate 配置文件:

    <?xml version="1.0" encoding="utf-8" ?>
    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
      <session-factory>
        <property name="connection.provider">
          NHibernate.Connection.DriverConnectionProvider
        </property>
        <property name="connection.driver_class">
          NHibernate.Driver.SqlClientDriver
        </property>
        <property name="connection.connection_string">
          Data Source= LocalDB)\v11.0;AttachDbFilename="c:\users\anton\documents\visual studio 2013\Projects\Books\Books\App_Data\BooksDB.mdf";Integrated Security=True
        </property>
        <property name="dialect">
          NHibernate.Dialect.MsSql2012Dialect
        </property>
      </session-factory>
    </hibernate-configuration>

Book.hmb.xls 映射文件

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="Books" namespace="Books.Models">

  <class name="Book" table="Books" dynamic-update="true">
    <cache usage="read-write"/>
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Author" not-null="true"/>
    <list name="Chapters" cascade="all-delete-orphan">
      <key column="BookId"/>
      <index column="ChapterIndex"/>
      <one-to-many class="Chapter"/>
    </list>
  </class>

  <class name="Chapter" table="Chapters" dynamic-update="true">
    <cache usage="read-write"/>
    <id name="Id" column="Id" type="int">
      <generator class="native" />
    </id>
    <property name="Title" not-null="true" />
    <property name="Notes" />
  </class>
</hibernate-mapping>

图书模型

namespace Books.Models
{
    public class Book
    {
        public virtual int Id { get; set; }
        public virtual string Title { get; set; }
        public virtual string Author { get; set; }
        public virtual IList<Chapter> Chapters { get; set; }
    }
}

章节模型

namespace Books.Models
{
    public class Chapter
    {
        public virtual int Id { get; set; }
        public virtual string Title { get; set; }
        public virtual string Notes { get; set; }
    }
}

会话模型

namespace Books.Models
{
    public class NHibernateSession
    {

        public static ISession OpenSessionBooks()
        {
            var configuration = new Configuration();
            var configurationPath = HttpContext.Current.Server.MapPath(@"~\Models\NHibernate\hibernate.cfg.xml");
            configuration.Configure(configurationPath);
            var booksConfigurationFile = HttpContext.Current.Server.MapPath(@"~\Models\NHibernate\Book.hbm.xml");
            configuration.AddFile(booksConfigurationFile);
            ISessionFactory sessionFactory = configuration.BuildSessionFactory();
            return sessionFactory.OpenSession();

        }

    }
}

BookController问题部分

public ActionResult Details(int id)
        {
            using (ISession session = NHibernateSession.OpenSessionBooks())
            {
                var book = session.Get<Book>(id);
                return View(book);
            }
        }

我希望在这里加载书籍详细信息及其所有章节列表详细信息。

ActionResult 详细信息强类型视图:

@model Books.Models.Book

@{
    ViewBag.Title = "Details";
}

<h2>Details</h2>

<fieldset>
    <legend>Book</legend>

    <div class="display-label">
         @Html.DisplayNameFor(model => model.Title)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.Title)
    </div>

    <div class="display-label">
         @Html.DisplayNameFor(model => model.Author)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.Author)
    </div>

    <div class="display-label">
        @Html.DisplayNameFor(model => model.Chapters)
    </div>
    <div class="display-field">
        @Html.DisplayFor(model => model.Chapters)
    </div>

</fieldset>
<p>
    @Html.ActionLink("Edit", "Edit", new { id=Model.Id }) |
    @Html.ActionLink("Back to List", "Index")
</p>

应用程序在视图行失败

     @Html.DisplayNameFor(model => model.Chapters)

有例外

    Initializing[Books.Models.Book#7]-failed to lazily initialize a collection of role: Books.Models.Book.Chapters, no session or session was closed

请帮我解决这个问题!解决方案 .7z 存档可用 here

您的章节是延迟加载的。但是,它们只会在您的视图呈现时才延迟加载。此时您的会话已关闭。

两种解决方法。

在有会话时强制加载

同时保持会话打开以进行页面呈现

原因如Keith Nicholas所述是章节的延迟加载。有很多方法可以解决这个问题,

1.使用 DTO 作为模型

您可以使用 BookDTO 和 ChapterDTO 列表作为模型,这样当视图呈现时所有必要的数据就位

2。在整个请求生命周期中使用会话

为此,您需要使用每个请求的会话方法,其中单个会话绑定到请求并在请求的整个生命周期内使用。详情请参考this