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, IDictionary
2 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>b3d() +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.WrappedAsyncVoid
1.CallEndDelegate(IAsyncResult asyncResult) +36
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38
System.Web.Mvc.MvcHandler.<BeginProcessRequest>b5(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=""TEMPLATE"" 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=""ORDER"" />
<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=""REPORT"" 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=""SQL"" 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.