I am creating an application that uses NHibernate, an object relational mapper that is a port of the Java Object relational mapper hibernate. Currently I am trying to represent my entities via hibernate xml files. The application I have right now is throwing an error I am thinking may be related to an object hirerarchy I have in the application. I have a set of Template objects which are used to store a template to the database which the View will act on polymorphically. I am using an Oracle XE database. I will post the code for the template I am testing, the repository, the hibernate XML, and the error text.

Error text: Index was out of range. Must be non-negative and less than the size of the collection.\r\nParameter name: index
Error Full Text: [ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index]
System.Collections.ArrayList.get_Item(Int32 index) +14715788
Oracle.DataAccess.Client.OracleParameterCollection.GetParameter(Int32 index) +18
NHibernate.Type.Int32Type.Set(IDbCommand rs, Object value, Int32 index) +50
NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id, Object[] fields, Object rowId, Boolean[] includeProperty, Boolean[][] includeColumns, Int32 table, IDbCommand statement, ISessionImplementor session, Int32 index) +496
NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Boolean[] notNull, Int32 j, SqlCommandInfo sql, Object obj, ISessionImplementor session) +902
NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Object obj, ISessionImplementor session) +272
NHibernate.Action.EntityInsertAction.Execute() +222
NHibernate.Engine.ActionQueue.Execute(IExecutable executable) +41
NHibernate.Engine.ActionQueue.ExecuteActions(IList list) +89
NHibernate.Engine.ActionQueue.ExecuteActions() +20
NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session) +222
NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event) +169
NHibernate.Impl.SessionImpl.Flush() +256
NHibernate.Transaction.AdoTransaction.Commit() +195
AdHockey.Repositories.ReportRepository.Update(Report entity) in M:\AdHockey_NHibernate\AdHockey\Repositories\ReportRepository.cs:70
AdHockey.Controllers.ManageBulkTemplateController.SubmitTemplate(BulkTemplate template) in M:\AdHockey_NHibernate\AdHockey\Controllers\ManageBulkTemplateController.cs:80
lambda_method(Closure , ControllerBase , Object[] ) +139
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +229 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +35
System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b39(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +39
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +67
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b
3d() +72
System.Web.Mvc.Async.<>cDisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b3f() +385
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>cDisplayClass2b.<BeginInvokeAction>b1c() +38
System.Web.Mvc.Async.<>cDisplayClass21.<BeginInvokeAction>b1e(IAsyncResult asyncResult) +185
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +38
System.Web.Mvc.Controller.<BeginExecuteCore>b1d(IAsyncResult asyncResult, ExecuteCoreState innerState) +29
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +65 System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +52 System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b
5(IAsyncResult asyncResult, ProcessRequestState innerState) +43
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +65
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +607
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +134

Code Being Executed:

                try {
                    using (ReportRepository repo = new ReportRepository()) {
                        repo.BeginTransaction();
                        Report report = repo.GetById(ReportId);
                        report.Templates = new List<Template>();
                        report.Templates.Add(template);
                        repo.Update(report);
                        repo.CommitTransaction();
                    }
                }
                catch (Exception ex) { throw; }

The Report Repository:

    public class ReportRepository : HibernateRepository<Report, int>, IDisposable {
        public ReportRepository() {
            this.session = OpenSession();
        }

        /// <summary>
        /// Delete a report from the database via unique identifier. 
        /// </summary>
        /// <param name="reportId"></param>
        public override void Delete(int reportId) {
            ISession session = OpenSession();
            using (ITransaction tx = session.BeginTransaction()) {
                Report entity = (Report)session.Load(typeof(Report), reportId);
                NHibernate.Context.CurrentSessionContext.Bind(session);
                session.Delete(entity);
                tx.Commit();
            }
        }

        /// <summary>
        /// Retrieve a report from the database via a unique database identifier. 
        /// </summary>
        /// <param name="reportId"></param>
        /// <returns></returns>
        public override Report GetById(int reportId) {
            ISession session = OpenSession();
            return (Report)session.Load(typeof(Report), reportId);
        }

        /// <summary>
        /// Insert a report into the database. 
        /// </summary>
        /// <param name="entity"></param>
        public override void Insert(Report entity) {
            ISession session = OpenSession();
            using (ITransaction tx = session.BeginTransaction()) {
                NHibernate.Context.CurrentSessionContext.Bind(session);
                session.Merge(entity);
                tx.Commit();
            }
        }

        /// <summary>
        /// Update an existing report in the database. 
        /// </summary>
        /// <param name="entity"></param>
        public override void Update(Report entity) {
            ISession session = OpenSession();
            using (ITransaction tx = session.BeginTransaction()) {
                NHibernate.Context.CurrentSessionContext.Bind(session);
                session.Merge(entity);
                tx.Commit();
            }
        }

    }//end class

The Hibernate Mapping file:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class schema="cblock" lazy="false" name="AdHockey.Models.Template, AdHockey" table="&quot;TEMPLATE&quot;" abstract="true">
    <id name="TemplateId" access="property" type="int" column="TEMPLATE_ID" >
      <generator class="native"/>
    </id>
    <discriminator column="CLASS_NAME" type="string"/>

    <property name="ClassName" access="readonly" column="CLASS_NAME" length="64" />
    <property name="AssemblyName" access="readonly" column="ASSEMBLY_NAME" length="64" />
    <property name="TemplateName" access="property" column="TEMPLATE_NAME" length="64" />
    <property name="Order" access="property" type="int" column="&quot;ORDER&quot;" />
    <property name="ReportId" access="property" type="int" column="REPORT_ID" />
    <many-to-one name="Report" access="property" column="REPORT_ID" cascade="all"/>

    <joined-subclass name="AdHockey.Models.BulkTemplate, AdHockey" table="BULK_TEMPLATE">
      <key column="TEMPLATE_ID" />
      <property name="ClrType" access="property" type="int" column="CLR_TYPE" />
      <property name="ValueDescriptor" access="property" type="int" column="VALUE_DESCRIPTOR" />
    </joined-subclass>
    <joined-subclass name="AdHockey.Models.LimiterItem, AdHockey" table="LIMITER_ITEM">
      <key column="TEMPLATE_ID" />
    </joined-subclass>
    <joined-subclass name="AdHockey.Models.TemplateItem, AdHockey" table="TEMPLATE_ITEM">
      <key column="TEMPLATE_ID" />
      <property name="ClrType" access="property" column="CLR_TYPE" />
      <property name="Alias" access="property" column="ALIAS" />
    </joined-subclass>

    <!--<subclass name="AdHockey.Models.BulkTemplate, AdHockey" discriminator-value="AdHockey.BulkTemplate">
      <join table="BULK_TEMPLATE">
        <key column="TEMPLATE_ID" />
        <property name="ClrType" access="property" type="int" column="CLR_TYPE" />
        <property name="ValueDescriptor" access="property" type="int" column="VALUE_DESCRIPTOR" />
      </join>
    </subclass>
    <subclass name="AdHockey.Models.LimiterItem, AdHockey" discriminator-value="AdHockey.LimiterItem">
      <join table="LIMITER_ITEM" >
        <key column="TEMPLATE_ID" />
      </join>
    </subclass>
    <subclass name="AdHockey.Models.TemplateItem, AdHockey" discriminator-value="TemplateItem">
      <join table="TEMPLATE_ITEM">
        <key column="TEMPLATE_ID" />
        <property name="ClrType" access="property" column="CLR_TYPE" />
        <property name="Alias" access="property" column="ALIAS" />
      </join>
    </subclass>-->
  </class>
</hibernate-mapping>

The Report Hibernate mapping file:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
  <class name="AdHockey.Models.Report, AdHockey" table="&quot;REPORT&quot;" lazy="false" schema="cblock">
    <id name="ReportId" access="property" type="int" column="REPORT_ID">
      <generator class="native"/>
    </id>
    <property name="ReportName" access="property" column="REPORT_NAME" length="64" />
    <property name="Description" access="property" column="DESCRIPTION" type="StringClob" />
    <property name="Sql" access="property" column="&quot;SQL&quot;" type="StringClob" />

    <bag name="Templates" access="property" cascade="all-delete-orphan" lazy="false" inverse="false">
      <key>
        <column name="REPORT_ID" />
      </key>
      <one-to-many class="AdHockey.Models.Template, AdHockey" />
    </bag>

  </class>
</hibernate-mapping>

I am also including the base classes for my repository classes.

/*Author: Cameron Block*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace AdHockey.Repositories {

    public interface IRepository<TEntity, TKey> where TEntity : class {
        TEntity GetById(TKey id);
        void Update(TEntity entity);
        void Delete(TKey id);
        void Insert(TEntity entity);
    }//end interface

}//end namespace

/*Author: Cameron Block*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate.Cfg;
using NHibernate;

namespace AdHockey.Repositories {

    public abstract class HibernateRepository<TEntity, TKey> : IRepository<TEntity, TKey>, IDisposable where TEntity : class {
        protected static ISessionFactory sessionFactory;
        protected static Configuration config = null;
        protected ISession session = null;
        protected ITransaction transaction = null;

        protected static ISessionFactory SessionFactory {
            get {
                if (sessionFactory == null) {
                    config = new Configuration();
                    config.Configure();
                    config.AddAssembly("AdHockey");
                    sessionFactory = config.BuildSessionFactory();
                }
                return sessionFactory;
            }
        }

        public ISession Session {
            get { return session; }
        }

        public static ISession OpenSession() {
            return SessionFactory.OpenSession();
        }

        public void BeginTransaction() {
            transaction = session.BeginTransaction();
        }

        public void CommitTransaction() {
            transaction.Commit();
            CloseTransaction();
        }

        public void RollbackTransaction() {
            transaction.Rollback();
            CloseTransaction();
            CloseSession();
        }

        private void CloseSession() {
            session.Close();
            session.Dispose();
            session = null;
        }

        private void CloseTransaction() {
            transaction.Dispose();
            transaction = null;
        }

        public abstract void Delete(TKey id);
        public abstract TEntity GetById(TKey id);
        public abstract void Insert(TEntity entity);
        public abstract void Update(TEntity entity);

        public void Dispose() {
            if (transaction != null) {
                CommitTransaction();
            }
            if(session != null){
                session.Flush();
                CloseSession();
            }

            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private bool disposed = false;

        protected virtual void Dispose(bool disposing) {
            if (!disposed) {
                if (disposing && session != null)
                    session.Dispose();
            }
            disposed = true;
        }//end method

    }//end class

}//end namespace

I am also including the template classes involved:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace AdHockey.Models {

    /// <summary>
    /// Base class for applying parameters and sql drop in's to report sql. 
    /// </summary>
    public class Template {

        /// <summary>
        /// The id of the Template. 
        /// </summary>
        public virtual int TemplateId {
            get; set;
        }

        /// <summary>
        /// The class name of the template inherited by all template types. 
        /// </summary>
        public virtual String ClassName {
            get {
                return this.GetType().Assembly.GetName().Name;
            }
        }

        /// <summary>
        /// The assembly name of the template inherited by all template types. 
        /// </summary>
        public virtual String AssemblyName {
            get {
                return this.GetType().Assembly.GetName().Name;
            }
        }

        public Template() {
        }

        /// <summary>
        /// The name of the Template for usage in the GUI. 
        /// </summary>
        public virtual String TemplateName {
            get; set;
        }

        /// <summary>
        /// The order in which to display the template items on the GUI. 
        /// </summary>
        public virtual int Order {
            get; set;
        }

        /// <summary>
        /// The Report Id which this Template is tethered to. 
        /// </summary>
        public virtual int ReportId {
            get; set;
        }

        /// <summary>
        /// The Report object to which this Template is attached. 
        /// </summary>
        public virtual Report Report {
            get; set;
        }
    }//end class

}//end namespace

/*Author: Cameron Block*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

using Oracle.ManagedDataAccess.Client;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Configuration;

namespace AdHockey.Models {

    /// <summary>
    /// Upload multiple values into a table to preform processing. Turn on bulk template logic from Report object. 
    /// Requires a supporting table structure and the AdHockey package. 
    /// </summary>
    public class BulkTemplate : Template {

        /// <summary>
        /// The name of the values column to be pulled out of the database. 
        /// </summary>
        public virtual String ValueDescriptor {
            get; set;
        }

        private String clrType;

        /// <summary>
        /// The type of value to return from the GUI textbox/Control. 
        /// </summary>
        public virtual String ClrType {
            get {
                return clrType;
            }
            set {
                if (Type.GetType(value) != null)
                    clrType = value;
                else
                    throw new ArgumentException("Not provided a valid .net type. ");
            }
        }

        public BulkTemplate() {
            ValueDescriptor = "VALUES";
        }

    }//end class

}//end namespace

The code also breaks for the BulkTemplate repository that I have created. I hope this is enough to go on, as I am pulling my hair out right now. I think this will be a really cool application once I get it working.

Recommended Answers

All 2 Replies

Don't even bother with inhertiance, allow the C# code to have an interface, but make the mapping files solely oriented toward the persistance of the concrete objects. Essentially it becomes a simple class oriented mapping file. I think I have one mapping for the abstract class Template, but It is essentially just mappings for all the concrete classes with no nhibernate polymorphisism included. It's not really an answer but it works. In addition my properties for the aggregates, the templates each becomes it's own list in a seperate list variable without the polymorphic list. So instead of a list of multiple classes, I get 3 lists with single classes. This could be why a book I read proposed lists of seperate objects as opposed to a polymorphic list of multiple objects. So I have 3 lists of templates, each a different type of template.

the error message is actually quite clear on what is going wrong.

Error Full Text: [ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.

The indices that are valid for a(ny) collection are 0 to length-1. So, if your collection contains 5 elements, the only valid indices you can use, are:
0, 1, 2, 3, 4

try to do myCollection.get(6); or myCollection.get(-1); will result in such an error.

search in the stacktrace which line of your code it leads back to, and add a check for valid index before trying to get the element.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.