0

Just started to use NHibernate in my ASP.NET MVC application. For an example I have created two tables: Books and 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 configuration file:

    <?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 mapping file

<?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>

Book model

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; }
    }
}

Chapter model

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

Session model

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 problem part

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

Here I'm expecting to load with Book details its all chapter list details.

ActionResult Details strongly typed view:

@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>

Application fails at view line

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

With exception

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

Please help me with this topic! Solution .7z archive is available here

2 Answers 2

2

Your chapters are lazy loaded. However, they only get lazy loaded when your view is getting rendered. By this time your Session is closed.

Two ways to solve that.

force the load when you do have a session

leave the session open for page rendering also

Sign up to request clarification or add additional context in comments.

Comments

0

The reason is as Keith Nicholas mentioned is lazy loading of the Chapters. There are a number of ways to solve this,

1. Using a DTO as a model

You could use a BookDTO and a list of ChapterDTO as a model so, when view is rendered all the necessary data in place

2. Use the session throughout the request lifetime

For this you need to use session per request approach where a single session is bound for the request and used throughout the life time of the request. Please refer this for more details.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.