Overriding component columns in IAutoMappingOverride - fluent-nhibernate

I have created an override that looks like this:
public class ProjectMappingOverride : IAutoMappingOverride<Project> {
public void Override(AutoMapping<Project> mapping) {
mapping.Component(p => p.OwnerNotifyReasons).ColumnPrefix("NotifyOwner");
mapping.Component(p => p.ContactNotifyReasons).ColumnPrefix("NotifyContacts");
}
}
However, this throws an exception:
System.InvalidOperationException: Tried to add component 'OwnerNotifyReasons' when already added.
d:\Development\FluentNHibernate\src\FluentNHibernate\MappingModel\MappedMembers.cs(134,0): at FluentNHibernate.MappingModel.MappedMembers.AddComponent(IComponentMapping componentMapping)
d:\Development\FluentNHibernate\src\FluentNHibernate\MappingModel\ClassBased\ClassMappingBase.cs(115,0): at FluentNHibernate.MappingModel.ClassBased.ClassMappingBase.AddComponent(IComponentMapping componentMapping)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\Steps\ComponentStep.cs(39,0): at FluentNHibernate.Automapping.Steps.ComponentStep.Map(ClassMappingBase classMap, Member member)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoMapper.cs(161,0): at FluentNHibernate.Automapping.AutoMapper.TryMapProperty(ClassMappingBase mapping, Member member, IList`1 mappedMembers)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoMapper.cs(149,0): at FluentNHibernate.Automapping.AutoMapper.<>c__DisplayClass13.<ProcessClass>b__12(Member x)
d:\Development\FluentNHibernate\src\FluentNHibernate\Utils\CollectionExtensions.cs(15,0): at FluentNHibernate.Utils.CollectionExtensions.Each[T](IEnumerable`1 enumerable, Action`1 each)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoMapper.cs(147,0): at FluentNHibernate.Automapping.AutoMapper.ProcessClass(ClassMappingBase mapping, Type entityType, IList`1 mappedMembers)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoMapper.cs(43,0): at FluentNHibernate.Automapping.AutoMapper.MergeMap(Type classType, ClassMappingBase mapping, IList`1 mappedMembers)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoMapper.cs(176,0): at FluentNHibernate.Automapping.AutoMapper.Map(Type classType, List`1 types)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoPersistenceModel.cs(185,0): at FluentNHibernate.Automapping.AutoPersistenceModel.AddMapping(Type type)
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoPersistenceModel.cs(153,0): at FluentNHibernate.Automapping.AutoPersistenceModel.CompileMappings()
d:\Development\FluentNHibernate\src\FluentNHibernate\Automapping\AutoPersistenceModel.cs(175,0): at FluentNHibernate.Automapping.AutoPersistenceModel.Configure(Configuration configuration)
d:\Development\FluentNHibernate\src\FluentNHibernate\Cfg\AutoMappingsContainer.cs(84,0): at FluentNHibernate.Cfg.AutoMappingsContainer.Apply(Configuration cfg)
d:\Development\FluentNHibernate\src\FluentNHibernate\Cfg\MappingConfiguration.cs(74,0): at FluentNHibernate.Cfg.MappingConfiguration.Apply(Configuration cfg)
d:\Development\FluentNHibernate\src\FluentNHibernate\Cfg\FluentConfiguration.cs(130,0): at FluentNHibernate.Cfg.FluentConfiguration.BuildConfiguration()
What am I doing wrong?

This is a bug in Fluent NHibernate. I'd written a fix, but it is not accepted yet.
The pull request is located here: http://github.com/jagregory/fluent-nhibernate/pull/106

Related

Add-Migration error: Object reference not set to an instance of an object

I'm using code-first concept and just tried adding a new class to the Models folder in hope to create a new table in SQL server database. i've added
Public Overridable Property Diagnosis As DbSet(Of Diagnosis)
in the DBContext.vb.
Then in the package manager console, i entered Add-Migration Diagnosis. But below error comes out. Why is this? Can anyone help me out please?
Object reference not set to an instance of an object.
Full error in Package Manager Console:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.UI.ParseChildrenAttribute.GetHashCode()
at System.Collections.Generic.ObjectEqualityComparer`1.GetHashCode(T obj)
at System.Linq.Set`1.InternalGetHashCode(TElement value)
at System.Linq.Set`1.Find(TElement value, Boolean add)
at System.Linq.Enumerable.<ExceptIterator>d__72`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at System.Data.Entity.ModelConfiguration.Utilities.AttributeProvider.<GetAttributes>b__3(PropertyInfo pi)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at System.Data.Entity.ModelConfiguration.Utilities.AttributeProvider.GetAttributes(PropertyInfo propertyInfo)
at System.Data.Entity.ModelConfiguration.Conventions.PropertyAttributeConfigurationConvention`1.<.ctor>b__0(ConventionTypeConfiguration ec)
at System.Data.Entity.ModelConfiguration.Conventions.TypeConvention.ApplyCore(Type memberInfo, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Conventions.TypeConventionBase.Apply(Type memberInfo, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Conventions.Convention.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Configuration.ConventionsConfiguration.ApplyModelConfiguration(Type type, ModelConfiguration modelConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapComplexType(Type type, Boolean discoverNested)
at System.Data.Entity.ModelConfiguration.Mappers.PropertyMapper.MapPrimitiveOrComplexOrEnumProperty(PropertyInfo propertyInfo, Func`1 structuralTypeConfiguration, Boolean discoverComplexTypes)
at System.Data.Entity.ModelConfiguration.Mappers.PropertyMapper.MapIfNotNavigationProperty(PropertyInfo propertyInfo, EntityType entityType, Func`1 entityTypeConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.<>c__DisplayClass14.<MapEntityType>b__e(PropertyMapper m, PropertyInfo p)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapStructuralElements[TStructuralTypeConfiguration](Type type, ICollection`1 annotations, Action`2 propertyMappingAction, Func`1 structuralTypeConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
at System.Data.Entity.ModelConfiguration.Mappers.NavigationPropertyMapper.Map(PropertyInfo propertyInfo, EntityType entityType, Func`1 entityTypeConfiguration)
at System.Data.Entity.ModelConfiguration.Mappers.TypeMapper.MapEntityType(Type type)
at System.Data.Entity.DbModelBuilder.MapTypes(EdmModel model)
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.LazyInternalContext.get_ModelBeingInitialized()
at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
at System.Data.Entity.Utilities.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(DbContext context)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState, Boolean calledByCreateDatabase)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
at System.Data.Entity.Migrations.Design.MigrationScaffolder..ctor(DbMigrationsConfiguration migrationsConfiguration)
at System.Data.Entity.Migrations.Design.ToolingFacade.ScaffoldRunner.Run()
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
at System.Data.Entity.Migrations.Design.ToolingFacade.Scaffold(String migrationName, String language, String rootNamespace, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.Execute(String name, Boolean force, Boolean ignoreChanges)
at System.Data.Entity.Migrations.AddMigrationCommand.<>c__DisplayClass2.<.ctor>b__0()
at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Object reference not set to an instance of an object.
I don't know if this is relevant or not, but in my web.config, there is a Default Connection that is already pre-set when i first created my project. When i first did Enable-Migrations i had to specify which connection it was. I've removed that line but it still doesn't work.
Previously when i did the add-migration, it didn't work because i simply created a class and added declaration of the respective strings, integer, etc. as variables like this:
Public Property id As String
Now it suddenly popped into my mind that i had to give a more elaborate description on each of the variables such as below:
<Key>
<StringLength(20)>
Public Property id As String
Now it works =')

database column to constant value without the need for a property in the entity class with mapping by code

this is almost the same as this question except using NH's mapping-by-code.
I really need the virtual properties because i also want to use SchemaExport to create the database for different rdbms without the need to create/maintain scripts for each.
Maybe there is a MbC Guru who knows how to do it with MbC
Update: the obvious simple code
Property("dummyProperty", c =>
{
c.Column("legacyColumn");
c.Access(typeof(MyPropertyAccessor));
});
does not work
NHibernate.MappingException: Unable to instantiate mapping class (see InnerException): Test.MbC.GroupMap ---> System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> NHibernate.MappingException: Member not found. The member 'dummyProperty' does not exists in type Test.Data.Group
bei NHibernate.Mapping.ByCode.Impl.CustomizersImpl.PropertyContainerCustomizer`1.GetPropertyOrFieldMatchingNameOrThrow(String memberName)
bei NHibernate.Mapping.ByCode.Impl.CustomizersImpl.PropertyContainerCustomizer`1.RegisterNoVisiblePropertyMapping(String notVisiblePropertyOrFieldName, Action`1 mapping)
bei
...
neither does this, because god knows why MbC checks internally with reflection, that the property does exist on the class.
var parameter = Expression.Parameter(typeof(T), "x");
Expression body = Expression.Property(parameter, new GetterPropertyInfo(typeof(T), defaultgetter));
body = Expression.Convert(body, typeof(object));
var lambda = Expression.Lambda<Func<T, object>>(body, parameter);
Property(lambda, m =>
{
m.Column(defaultgetter.PropertyName);
m.Access(propertyAccessorType);
});
and even disabling the test with reflection through overriding RegisterProperty() in ClassMapping it still throws while building the hbm complaining:
System.ArgumentOutOfRangeException: Can't add a property of another graph
Parametername: property
bei NHibernate.Mapping.ByCode.Impl.AbstractBasePropertyContainerMapper.Proper
ty(MemberInfo property, Action`1 mapping)
bei NHibernate.Mapping.ByCode.ModelMapper.MapProperty(MemberInfo member, Prop
ertyPath propertyPath, IMinimalPlainPropertyContainerMapper propertiesContainer)
bei NHibernate.Mapping.ByCode.ModelMapper.MapProperties(Type propertiesContai
nerType, IEnumerable`1 propertiesToMap, IPropertyContainerMapper propertiesConta
iner, PropertyPath path)
bei NHibernate.Mapping.ByCode.ModelMapper.MapProperties(Type propertiesContai
nerType, IEnumerable`1 propertiesToMap, IPropertyContainerMapper propertiesConta
iner)
bei NHibernate.Mapping.ByCode.ModelMapper.MapRootClass(Type type, HbmMapping
mapping)
bei NHibernate.Mapping.ByCode.ModelMapper.CompileMappingFor(IEnumerable`1 typ
es)
Mapping by code should be more flexible than FNH? Where?
After investing a lot of time trying to do this rather simple mapping in MbC i concede and throw aboard MbC again.
Even simple Mapping like this is not remotely possible with the oh so flexible MbC
public class MyClassMap : ClassMap<MyClass>
{
public MyClassMap()
{
Map(x => this.VirtualProp, "legacyColumn").Default("123").Access.None();
}
public long VirtualProp { get; set; }
}
the advantage here is that i can use SchemaExport to create a compatible schema for the legacy app without polluting my domain classes
You can do it pretty much in the same way as in the linked question. Implementation of PropertyAccessor stays the same. To use it within mapping-by-code, map the column using string overload (the name of the property is required but not really used in this case) and attach the accessor:
Property("dummyPropertyNameForConstant", c =>
{
c.Column("ConstantColumn");
c.Access(typeof(CustomAccessor));
});

Selecting CompostiteUserTypes with Linq To nHibernate (v1)

We've a mature nHibernate project that has started using the linq provider in nHibernate contrib. As we are using nHibernate 2.0 we can't use the new provider under development in the trunk (against nHibernate 3.0).
Whilst limited it's proved to be a perfect for our needs apart from one issue - whenever I select a CompositeUserType I get an error ''
I'm not sure the Linq to nHibernate provider v1 can understand these types. Does anyone know for sure ? UI'm trying with the source and not finding much joy. I'm hoping someone can help and show me how.
And now the example.... for the given ActiveRecord type...
[ActiveRecord]
public class Product : IHoldPrice
{
[PrimaryKey(PrimaryKeyType.Guid)]
public virtual Guid Key { get; set; }
[Property(NotNull = true, Length = 250)]
public virtual string Name { get; set;}
[CompositeUserType(typeof (PriceUserType), new[] {"Price_Value", "Price_DateChanged"})]
public virtual IPrice CurrentPrice { get; set; }
}
When I try the following statement I get an error:
(from p in Session.Linq<Product>()
.Where(p => p.Key == productKey)
.Select(p => new
{
p.Key,
p.CurrentPrice
}))
.FirstOrDefault();
Error:
‘property does not map to a single column: CurrentPrice’
Stack:
‘property does not map to a single column: CurrentPrice’
Stack:
NHibernate.QueryException: property does not map to a single column: CurrentPrice
at NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetColumn(ICriteria criteria, String propertyName)
at NHibernate.Criterion.PropertyProjection.ToSqlString(ICriteria criteria, Int32 loc, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters)
at NHibernate.Criterion.ProjectionList.ToSqlString(ICriteria criteria, Int32 loc, ICriteriaQuery criteriaQuery, IDictionary`2 enabledFilters)
at NHibernate.Loader.Criteria.CriteriaQueryTranslator.GetSelect(IDictionary`2 enabledFilters)
at NHibernate.Loader.Criteria.CriteriaJoinWalker..ctor(IOuterJoinLoadable persister, CriteriaQueryTranslator translator, ISessionFactoryImplementor factory, ICriteria criteria, String rootEntityName, IDictionary`2 enabledFilters)
at NHibernate.Loader.Criteria.CriteriaLoader..ctor(IOuterJoinLoadable persister, ISessionFactoryImplementor factory, CriteriaImpl rootCriteria, String rootEntityName, IDictionary`2 enabledFilters)
at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)
at NHibernate.Impl.CriteriaImpl.List(IList results)
at NHibernate.Impl.CriteriaImpl.List[T]()
at NHibernate.Linq.Visitors.ImmediateResultsVisitor`1.GetElementList(MethodCallExpression call, Int32 count)
at NHibernate.Linq.Visitors.ImmediateResultsVisitor`1.HandleFirstOrDefaultCall(MethodCallExpression call)
at NHibernate.Linq.Visitors.ImmediateResultsVisitor`1.VisitMethodCall(MethodCallExpression call)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.ImmediateResultsVisitor`1.GetResults(MethodCallExpression expr)
at NHibernate.Linq.Visitors.RootVisitor.HandleImmediateResultsCall(MethodCallExpression call)
at NHibernate.Linq.Visitors.RootVisitor.VisitMethodCall(MethodCallExpression expr)
at NHibernate.Linq.Visitors.ExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.NHibernateExpressionVisitor.Visit(Expression exp)
at NHibernate.Linq.Visitors.NHibernateQueryTranslator.Translate(Expression expression, QueryOptions queryOptions)
at NHibernate.Linq.NHibernateQueryProvider.TranslateExpression(Expression expression)
at NHibernate.Linq.NHibernateQueryProvider.Execute(Expression expression)
at NHibernate.Linq.QueryProvider.System.Linq.IQueryProvider.Execute[T](Expression expression)
at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
Note - No I can't use Criteria and no Hql won't do right now, and I know the new Linq provider is much better.
Ok we upgraded to NH v3.0 and it's solved - can select.

NHibernate: Collection was modified; enumeration operation may not execute

I'm currently struggling with this "Collection was modified; enumeration operation may not execute" issue.
I have searched about this error message, and it's all related to the foreach statement. I do have the some foreach statements, but they are just simply representing the data. I did not using any remove or add inside the foreach statement.
NOTE:
The error randomly happens (about 4-5 times a day).
The application is the MVC website.
There are about 5 users operate this applications (about 150 orders a day). Could it be some another users modified the collection, and then occur this error?
I have log4net setup and the settings can be found here
Make sure that the controller has a parameterless public constructor I do have parameterless public constructor in AdminProductController
Does anyone know why this happen and how to resolve this issue?
A friend (Oskar) mentioned that
"Theory: Maybe the problem is that
your configuration and session factory
is initialized on the first request
after application restart. If a second
request comes in before the first
request is finished, maybe it will
also try to initialize and then
triggering this problem somehow."
Many thanks.
Daoming
Here is the error message:
System.InvalidOperationException
Collection was modified; enumeration operation may not execute.
System.InvalidOperationException: An error occurred when trying to create a controller of type 'WebController.Controllers.Admin.AdminProductController'. Make sure that the controller has a parameterless public constructor. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> NHibernate.MappingException: Could not configure datastore from input stream DomainModel.Entities.Mappings.OrderProductVariant.hbm.xml ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
at System.Xml.Schema.XmlSchemaSet.AddSchemaToSet(XmlSchema schema)
at System.Xml.Schema.XmlSchemaSet.Add(String targetNamespace, XmlSchema schema)
at System.Xml.Schema.XmlSchemaSet.Add(XmlSchema schema)
at NHibernate.Cfg.Configuration.LoadMappingDocument(XmlReader hbmReader, String name)
at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
--- End of inner exception stack trace ---
at NHibernate.Cfg.Configuration.LogAndThrow(Exception exception)
at NHibernate.Cfg.Configuration.AddInputStream(Stream xmlInputStream, String name)
at NHibernate.Cfg.Configuration.AddResource(String path, Assembly assembly)
at NHibernate.Cfg.Configuration.AddAssembly(Assembly assembly)
at DomainModel.RepositoryBase..ctor()
at WebController.Controllers._baseController..ctor()
at WebController.Controllers.Admin.AdminProductController..ctor()
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
--- End of inner exception stack trace ---
at System.RuntimeType.CreateInstanceImpl(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean fillCache)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
--- End of inner exception stack trace ---
at System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType)
at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
Oskar is right. Two separate threads are trying to initialize the session factory at the same time. Suggest you put some locking around the initialization code, perhaps just using the lock keyword and a suitable synchronization object. We've used a pattern like this, using one of the locks from the Wintellect PowerThreading library:
using (_lock.WaitToRead())
{
if (Factory != null) return Factory;
}
using (_lock.WaitToWrite())
{
if (Factory != null) return Factory;
Factory = ConfigureFactory();
return Factory;
}
You could more simply just use the lock keyword and a double-check locking pattern like so:
class NestedSessionManager
{
internal static SessionManager _sessionManager;
private static readonly object _syncRoot = new object();
internal static SessionManager sessionManager
{
get
{
if (_sessionManager != null) return _sessionManager;
lock (_syncRoot)
{
if (_sessionManager != null) return _sessionManager;
_sessionManager = new SessionManager();
return _sessionManager;
}
}
}
}

ArgumentOutOfRangeException : Index was out of range

I'm getting this weird ArgumentOutOfRangeException whenever I use the
PersitenceSpecification class for verifying an entity that has a
reference to a value object.
public class CatalogItem : DomainEntity
{
internal virtual Manufacturer Manufacturer { get; private
set; }
internal virtual String Name { get; private set; }
protected CatalogItem()
{}
public CatalogItem(String name, String manufacturer)
{
Name = name;
Manufacturer = new Manufacturer(manufacturer);
}
}
public class CatalogItemMapping : ClassMap<CatalogItem>
{
public CatalogItemMapping()
{
Id(catalogItem => catalogItem.Id);
Component<Manufacturer>(category => category.Manufacturer,
m => m.Map(manufacturer =>
manufacturer.Name));
Map(catalogItem => catalogItem.Name);
Map(Reveal.Property<CatalogItem>("Price"));
}
}
[TestFixture]
public class When_verifying_the_class_mapping_of_a_catalog_item
: NHibernateSpecification
{
[Test]
public void Then_a_catalog_object_should_be_persistable()
{
new PersistenceSpecification<CatalogItem>(Session)
.VerifyTheMappings();
}
}
[TestFixture]
public class NHibernateSpecification
: Specification
{
protected ISession Session { get; private set; }
protected override void Establish_context()
{
var configuration = new SQLiteConfiguration()
.InMemory()
.ShowSql()
.ToProperties();
var sessionSource = new SessionSource(configuration, new
RetailerPersistenceModel());
Session = sessionSource.CreateSession();
sessionSource.BuildSchema(Session);
ProvideInitialData(Session);
Session.Flush();
Session.Clear();
}
protected override void Dispose_context()
{
Session.Dispose();
Session = null;
}
protected virtual void ProvideInitialData(ISession session)
{}
}
Here's the error I'm getting:
TestCase
'Then_a_catalog_object_should_be_persistable' not executed:
System.ArgumentOutOfRangeException :
Index was out of range. Must be
non-negative and less than the size of
the collection. Parameter name: index
at System.ThrowHelper.ThrowArgumentOutOfRangeException
(ExceptionArgument argument,
ExceptionResource resource)
at System.ThrowHelper.ThrowArgumentOutOfRangeException()
at System.Collections.Generic.List1.get_Item(Int32
index)
at System.Data.SQLite.SQLiteParameterCollection.GetParameter(Int32
index)
at System.Data.Common.DbParameterCollection.System.Collections.IList.get_Item
(Int32 index)
at NHibernate.Type.GuidType.Set(IDbCommand
cmd, Object value, Int32 index)
at NHibernate.Type.NullableType.NullSafeSet(IDbCommand
cmd, Object value, Int32 index)
at NHibernate.Type.NullableType.NullSafeSet(IDbCommand
st, Object value, Int32 index,
ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate
(Object id, Object[] fields, Object
rowId, Boolean[] includeProperty,
Boolean[][] includeColumns, Int32
table, IDbCommand statement,
ISessionImplementor session, Int32
index)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object
id, Object[] fields, Boolean[]
notNull, Int32 j, SqlCommandInfo sql,
Object obj, ISessionImplementor
session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object
id, Object[] fields, Object obj,
ISessionImplementor session)
at NHibernate.Action.EntityInsertAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable
executable)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList
list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions
(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush
(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
d:\Builds\FluentNH\src\FluentNHibernate\Testing
\PersistenceSpecification.cs(127,0):
at
FluentNHibernate.Testing.PersistenceSpecification1.TransactionalSave
(Object propertyValue)
d:\Builds\FluentNH\src\FluentNHibernate\Testing
\PersistenceSpecification.cs(105,0):
at
FluentNHibernate.Testing.PersistenceSpecification`1.VerifyTheMappings
()
C:\Source\SupplyChain\Tests\Retailer.IntegrationTests\Mappings
\CatalogItemMappingSpecifications.cs(14,0):
at
SupplyChain.Retailer.IntegrationTests.Mappings.When_verifying_the_class_mapping_of_a_catalog_item.Then_a_catalog_object_should_be_persistable
()
Sorry for the long post, but this one got me busy for a couple of
hours now. This might not be caused by FNH as I found this JIRA ticket
of NH itself that mentions something similar:
http://forum.hibernate.org/viewtopic.php?p=2395409
I'm still hoping that I'm doing something wrong in my code :-). Any
thought?
Thanks in advance
I found the solution to this problem which resulted from my own
stupidity in the first place. It all became clear to me as soon as I
generated the hbm files from the fluent NH mapping.
<class name="CatalogItem" table="`CatalogItem`" xmlns="urn:nhibernate-
mapping-2.2" optimistic-lock="version">
...
<property name="Name" length="100" type="String">
<column name="Name" />
</property>
...
<component name="Manufacturer" insert="false" update="true">
<property name="Name" length="100" type="String">
<column name="Name" />
</property>
</component>
</class>
Notice that the column for the Name property and the column for the
Manufacturer component are both mapped to the same column. That's why
this resulted into an ArgumentOutOfRangeException, because there were
more arguments than there were column names. I solved this by
explicitely specifying a column name for the component mapping:
Component(catalogItem => catalogItem.Manufacturer,
m => m.Map(manufacturer => manufacturer.Name,
"Manufacturer"));
Another lesson learned.
In my case, I was mapping two properties to the same column with Fluent NHibernate.
Your CatalogItem doesn't seem to have a Price property, which seems odd when you're using the Reveal helper.
Yes, I removed that one for reducing some of the noise. I guess I forgot to remove it from the mapping as well. After doing some more investigation, I noticed that it has something to do with Manufacturer being mapped as a component. When I used a plain-old string instead of a separate class, everything works fine.
In my particular case I was adding property as well as ID (using attributes) over the same .NET property. This resulted in the same error.
Old question, but if someone runs into the same problem as I did, it may help to know that this Fluent Nhibernate issue (ColumnPrefix only applied to first Component mapping inside a ComponentMap) can give the same exception since the columns prefixes are not always applied.
The other answers for this question are correct. But there is another case where NHibernate outputs the same message with different stack trace. The stack trace can be found in this question.
As this is one of the top questions that popup when I search online with exact error message, I thought it would be helpful for others to know how I fixed it. There is a documented issue for this error on NHibernate's GitHub repository. Here is the link - https://github.com/nhibernate/nhibernate-core/issues/1319.
The error has been fixed in latest NHibernate at the time of writing this answer. For older versions such as 3.1.0 (the version I was working with when facing the error), setting format_sql property to false in nhibernate.config file fixes the issue. More details about the error and workaround can be found in the GitHub issue and NHibernate doc.