The following code throws a StaleStateException when the...">

Fluent NHibernate AutoMapping throws a "StaleStateException" when trying to copy a list <>

The following code throws a StaleStateException when the Order.OrderItems (IList) property is Commited. Full text of exception:

An unhandled exception of type "NHibernate.StaleStateException" occurred in NHibernate.dll

Additional information: Unexpected number of lines: 0; expected: 1

I just started using NHibernate, and that means absolutely nothing to me. Can anyone explain what is wrong?

Most of the code is added below. Sorry, so many, but I thought it was better than maybe leaving something important.

If I comment out the line OrderItems = orderItems , everything else works fine.

 using System; using System.Collections.Generic; using System.IO; using AutomappingSample.Domain; using FluentNHibernate.AutoMap; using FluentNHibernate.Cfg; using FluentNHibernate.Cfg.Db; using NHibernate; using NHibernate.Cfg; using NHibernate.Tool.hbm2ddl; namespace AutomappingSample { class Program { private const string DbFile = "AutomappingSample.db"; private const bool useSqlServerCe = true; static void Main() { var factory = CreateSessionFactory(); using (var session = factory.OpenSession()) using(var tx = session.BeginTransaction()) { var product1 = new Product { Name = "Apples", UnitPrice = 4.5m, Discontinued = true }; var product2 = new Product { Name = "Pears", UnitPrice = 3.5m, Discontinued = false }; session.Save(product1); session.Save(product2); var customer = new Customer { FirstName = "John", LastName = "Doe", }; session.Save(customer); var orderItems = new List<OrderItem> { new OrderItem {Id = 1, Quantity = 100, Product = product1}, new OrderItem {Id = 2, Quantity = 200, Product = product2}, }; var order = new Order() { Customer = customer, Id = 1, OrderDate = DateTime.Now, // CAUSES FOLLOWING EXCEPTION WHEN COMMIT: // An unhandled exception of type 'NHibernate.StaleStateException' // occurred in NHibernate.dll // // Additional information: Unexpected row count: 0; expected: 1 OrderItems = orderItems }; session.Save(order); // EXCEPTION IS THROWN HERE tx.Commit(); } Console.WriteLine("Hit enter to exit..."); Console.ReadLine(); } private static ISessionFactory CreateSessionFactory() { IPersistenceConfigurer persistenceConfigurer; if (useSqlServerCe) persistenceConfigurer = MsSqlCeConfiguration.Standard.ConnectionString(c => c.Is("Data Source=AutomappingSample.sdf")); else persistenceConfigurer = SQLiteConfiguration.Standard.UsingFile(DbFile); return Fluently.Configure() .Database(persistenceConfigurer) .Mappings(m => m.AutoMappings.Add( AutoPersistenceModel .MapEntitiesFromAssemblyOf<Customer>() .WithSetup(s => { s.IsBaseType = type => type == typeof (EntityBase); }) .Where(t => t.Namespace.EndsWith("Domain")) .ConventionDiscovery.Add<MyStringLengthConvention>() .ConventionDiscovery.Add<MyIdConvention>() .ConventionDiscovery.Add<MyForeignKeyConvention>() )) .ExposeConfiguration(BuildSchema) .BuildSessionFactory(); } private static void BuildSchema(Configuration config) { // delete the existing db on each run (only for SQLite) if (File.Exists(DbFile)) File.Delete(DbFile); // this NHibernate tool takes a configuration (with mapping info in) // and exports a database schema from it new SchemaExport(config) .Create(true, true); } } } 

 namespace AutomappingSample.Domain { public class EntityBase { public virtual int Id { get; set; } } } 

 using System; using System.Collections.Generic; namespace AutomappingSample.Domain { public class Order : EntityBase { public virtual DateTime OrderDate { get; set; } public virtual Customer Customer { get; set; } public virtual IList<OrderItem> OrderItems { get; set; } } } 

 namespace AutomappingSample.Domain { public class OrderItem : EntityBase { public virtual int Quantity { get; set; } public virtual Product Product { get; set; } } } 
+4
source share
3 answers

After posting the question, I found out that the easiest way to get cascading saves is to add a default convention .

See the section in the code below that runs "var autoPersistanceModel = ..."

  private static ISessionFactory CreateSessionFactory() { ISessionFactory sessionFactory = null; // Automapped XML files will be exported to project's // ...\bin\x86\Debug\AutoMapExport directory // See ".ExportTo()" below const string autoMapExportDir = "AutoMapExport"; if( !Directory.Exists(autoMapExportDir) ) Directory.CreateDirectory(autoMapExportDir); try { var autoPersistenceModel = AutoMap.AssemblyOf<DlsAppOverlordExportRunData>() // Only map entities in the DlsAppAutomapped namespace .Where(t => t.Namespace == "DlsAppAutomapped") // Do cascading saves on all entities so lists // will be automatically saved .Conventions.Add( DefaultCascade.All() ) ; sessionFactory = Fluently.Configure() .Database(SQLiteConfiguration.Standard .UsingFile(DbFile) // Display generated SQL on Console .ShowSql() ) .Mappings(m => m.AutoMappings.Add(autoPersistenceModel) // Save XML mapping files to this dir .ExportTo(autoMapExportDir) ) .ExposeConfiguration(BuildSchema) .BuildSessionFactory() ; } catch (Exception e) { Debug.WriteLine(e); } return sessionFactory; } 
+2
source

You must save orderItems first before trying to save order :

 session.Save(orderItems[0]); session.Save(orderItems[1]); session.Save(order); 
+3
source

You may need to specify that it cascades the save in OrderItems to order.

Something like this: (from here )

 .Override<Order>(map => { map.HasMany(x => x.OrderItems) .Cascade.All(); }); 
+1
source

All Articles