Fluent NHibernate Automapping wirft „StaleStateException“, wenn versuchen, eine Liste Commit <>

StackOverflow https://stackoverflow.com/questions/1652272

Frage

Der folgende Code führt eine StaleStateException Ausnahme, wenn die Order.OrderItems Eigenschaft (ein IList) Commited ist. Der vollständige Wortlaut der Ausnahme ist:

Eine nicht behandelte Ausnahme des Typs 'NHibernate.StaleStateException' aufgetreten in NHibernate.dll

Weitere Informationen: Unerwartete Zeilenanzahl: 0; erwartet: 1

Ich habe gerade angefangen NHibernate, und das bedeutet absolut nichts für mich. Kann mir jemand erklären, was falsch ist?

Der meiste Code ist unten angehängt. Leider ist es so sehr, aber ich dachte, dass besser ist, als vielleicht etwas Wichtiges auslassen.

Wenn ich die Zeile aus kommentieren Orderitems = Orderitems , alles andere funktioniert gut.

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; }
    }
}
War es hilfreich?

Lösung 2

Da die Frage der Veröffentlichung, ich habe gelernt, dass der einfachste Weg, Kaskadierung zu erhalten speichert ist auf hinzufügen eine DefaultCascade Konvention .

unten, dass der Abschnitt im Code anzeigen beginnt "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;
    }

Andere Tipps

Sie müssen zuerst orderItems speichern, bevor Sie den order speichern:

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

Unter Umständen müssen Sie ihnen sagen, das spart das Orderitem auf Bestellung kaskadieren.

So etwas wie folgt aus: (Von hier )

.Override<Order>(map =>
{
  map.HasMany(x => x.OrderItems)
    .Cascade.All();
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top