代码之家  ›  专栏  ›  技术社区  ›  Tom Bushell

Fluent NHibernate自动映射在尝试提交列表时抛出“StaleStateException”<>

  •  4
  • Tom Bushell  · 技术社区  · 15 年前

    提交Order.OrderItems属性(IList)时,以下代码引发StaleStateException异常。例外情况全文如下:

    NHibernate.dll中发生类型为“NHibernate.StaleStateException”的未处理异常

    其他信息:意外的行计数:0;预期:1

    我刚刚开始使用NHibernate,这对我来说毫无意义。有人能解释一下怎么回事吗?

    如果我把这行注释掉 OrderItems=OrderItems

    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; }
        }
    }
    
    3 回复  |  直到 13 年前
        1
  •  3
  •   Darin Dimitrov    15 年前

    你需要先保存 orderItems 在尝试保存 order

    session.Save(orderItems[0]);
    session.Save(orderItems[1]);
    session.Save(order);
    
        2
  •  2
  •   Tom Bushell    15 年前

    自从发布这个问题以来,我了解到获得级联保存的最简单方法是 添加默认级联约定 .

        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;
        }
    
        3
  •  1
  •   Derek Ekins    15 年前

    您可能需要告诉它将保存级联到Order上的OrderItems。

    大概是这样的: (来自 here

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