Nhibernate 中的父子映射

Posted

技术标签:

【中文标题】Nhibernate 中的父子映射【英文标题】:Parent and child mapping in Nhibernate 【发布时间】:2013-10-05 15:28:37 【问题描述】:

我在数据库中有两个表:Order 和 OrderLine。 OrderLine 有一个不可可为空的列 (OrderId),外键指向 Order.Id。

在代码中我有两个类:Order 和 OrderLine。 Order 有一个 OrderLines 集合,但 OrderLine 没有对 Order 的引用。

如果不引入从 OrderLine 到 Order 的引用,或者在 OrderLine 中维护一个带有订单 ID 的私有字段,如this blog post (variation 3) 所示,您不能映射此关系是正确的吗?

提前致谢……

以下代码显示了实体和映射

namespace NhibernateMappingTests

    [TestClass]
    public class MappingExample2
    
        [TestMethod]
        public void InsertTest()
        
            using (var session = NHibernateHelper.OpenSession())
            
                using (var transaction = session.BeginTransaction())
                
                    Order order = new Order();
                    order.AddOrderLine(new OrderLine());
                    session.Save(order);
                    transaction.Commit();
                
            
        
    

    public class Order
    
        public Order()
        
            OrderLines = new List<OrderLine>();
        

        public int Id  get; set; 
        public IList<OrderLine> OrderLines  get; set; 

        public void AddOrderLine(OrderLine orderLine)
        
            OrderLines.Add(orderLine);
        
    

    public class OrderLine
    
        public int Id  get; set; 
    

    public class OrderMap : ClassMap<Order>
    
        public OrderMap()
        
            Not.LazyLoad();
            Id(x => x.Id).GeneratedBy.Identity();
            HasMany(x => x.OrderLines)
                .AsBag()
                .Cascade.All()
                .KeyColumn("OrderId");
        
    

    public class OrderLineMap : ClassMap<OrderLine>
    
        public OrderLineMap()
        
            Not.LazyLoad();
            Id(x => x.Id).GeneratedBy.Identity();
        
    

    public class NHibernateHelper
    
        private static ISessionFactory _sessionFactory;

        private static ISessionFactory SessionFactory
        
            get
            
                if (_sessionFactory == null)
                    InitializeSessionFactory();

                return _sessionFactory;
            
        

        private static void InitializeSessionFactory()
        
            _sessionFactory = Fluently.Configure()
                .Database(MsSqlConfiguration.MsSql2008.ConnectionString(@"data source=(local)\db01;initial catalog=MyDatabase;persist security info=false;packet size=4096;integrated security=sspi;").ShowSql())
                .Mappings(m => m.FluentMappings.AddFromAssemblyOf<TimeSeries>())
                //.ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
                .BuildSessionFactory();
        

        public static ISession OpenSession()
        
            return SessionFactory.OpenSession();
        
    

它会导致以下异常:

测试方法 NhibernateMappingTests.MappingExample2.InsertTest 抛出异常: NHibernate.Exceptions.GenericADOException:无法插入:[NhibernateMappingTests.OrderLine] [SQL:INSERT INTO [OrderLine] 默认值;选择 SCOPE_IDENTITY()] ---> System.Data.SqlClient.SqlException:无法将值 NULL 插入到列“OrderId”、表“MyDatabase.dbo.OrderLine”中;列不允许空值。插入失败。

【问题讨论】:

【参考方案1】:

您实际上只能在一侧映射关系,这无关紧要。

虽然在这种情况下会执行更新语句。要修复异常,您只需将映射更改为

HasMany(x => x.OrderLines) 
  .AsBag() 
  .Cascade.AllDeleteOrphan() // or .All
   .KeyColumn("OrderId")
   .Not.KeyNullable();

【讨论】:

好吧,如果你不想拥有双向映射/导航属性,就不要映射它。它应该只在一侧使用映射。 但似乎 NHibernate 更喜欢使用 OrderLine.OrderId = NULL 进行插入,然后再更新 OrderLine.OrderId = xx。但是 OrderLine.OrderId not 可以为空,因此我得到了 Foreingkey 违规。 发布您的映射和实体代码,我或许可以为您提供帮助。 我已经用您请求的实体和映射更新了问题。 您的代码实际上对我来说很好。我还手动将列更改为不可为空,但它仍然有效。并且它不会产生任何无效的 sql 插入...您确定在遇到问题时保存了订单吗?如果您只保存 OrderLine,这是行不通的。现在我不能 100% 确定我是否正确理解了您的问题 .

以上是关于Nhibernate 中的父子映射的主要内容,如果未能解决你的问题,请参考以下文章

Fluent 映射和 NHibernate Xml 配置

防止 NHibernate 将 Returning 子句添加到生成的插入语句中

如何在 Fluent NHibernate 中将一对一关系映射为复合键的一部分

如何通过代码将 Id 映射到 NHibernate 映射中的私有支持字段?

NHibernate 中的映射表枚举

在 NHibernate 中查询未映射的列