Nhibernate 类映射和级联属性

Posted

技术标签:

【中文标题】Nhibernate 类映射和级联属性【英文标题】:Nhibernate class mapping and cascade property 【发布时间】:2015-11-01 18:52:14 【问题描述】:

我们有一个Address 实体,它有一个引用City 表的外键。一个Address 只引用一个City,但一个City 应该能够被许多Addresses 引用。

public class Address : Entity

    public virtual string AddressLine1  get; set; 

    public virtual string AddressLine2  get; set; 

    public virtual City City  get; set; 


public class City : Entity
       
    public virtual string CityName  get; set; 

这是Address 类映射。

public class AddressClassMapping : ClassMapping<Address>

    public AddressClassMapping()
    
        this.Schema("dbo");
        this.Table("addresses");
        this.Cache(e => e.Usage(CacheUsage.ReadWrite));
        this.Id(e => e.Id, 
                m =>  m.Column("id_address"); m.Generator(Generators.Native););
        this.Property(e => e.AddressLine1, 
                      m =>  m.Column("address_line_1"); m.NotNullable(true); );
        this.Property(e => e.AddressLine2, 
                      m =>  .Column("address_line_2"); 
                      m.NotNullable(true); );
        this.ManyToOne(
            e => e.City,
            m =>
            
                m.Column("id_city");
                m.Cascade(Cascade.All);
            );
    

我应该如何更改类映射以便:

    当我删除一个城市时,该城市的所有地址都会被删除? 当我删除地址时,城市不受影响? 我可以通过更新外键来更新 Address 的 City 属性吗?

到目前为止,我已经使用了Cascade 属性,并且遇到了以下问题:更新地址的城市会导致更新 City 表,或者我无法在不违反外键约束的情况下删除地址。

【问题讨论】:

【参考方案1】:

上面显示的many-to-one 部分(这里也讨论了NHibernate Many-to-one cascade)可以设置为这些值

// xml
cascade="all|none|save-update|delete" 
// maping by code
Cascade.All | Cascade.None | Cascade.Persist | Cascade.Remove
// fluent 
Cascade.All() | Cascade.SaveUpdate() | Cascade.None() | Cascade.Delete() 

(在此处阅读更多信息Mapping-by-Code - ManyToOne)

这将涵盖点数……以上都不是。因为没有任何要求要求从地址级联到城市。

第3点:

    我可以通过更新外键来更新 Address 的 City 属性吗?

与级联无关。这是标准行为,即使没有级联也可以工作,因为它会更改地址表中的值。完全没有接触城市。

涵盖第 2 点:

    当我删除地址时,城市不受影响?

好吧,我们应该完全删除级联,因为......在这个方向上不需要它。但是,此设置将适合第 2 点

this.ManyToOne(
    e => e.City,
    m =>
    
        m.Column("id_city");
        m.Cascade(Cascade.Persist);

涵盖第一点:

    当我删除一个城市时,该城市的所有地址都会被删除?

我们必须做很多事情。我们需要扩展 POCO 关系并引入一对多映射。这将满足需要:

public class City : Entity
       
    public virtual IList<Address> Addresses  get; set; 

映射

代码映射:

Set(x => x.Addresses, c =>

   ...
   c.Cascade(Cascade.All.Include(Cascade.DeleteOrphans));

流畅版

HasMany(x => x.Addresses)
    ...
    Cascade.AllDeleteOrphan();

(在此处阅读更多内容Mapping-by-Code - Set and Bag)

【讨论】:

谢谢!你能解释一下第二个sn-p的意义吗? m.Cascade.SaveUpdate(); 行有什么作用? 很抱歉,我使用的是 fluent 版本(正如您的标签告诉我的那样),而我应该使用代码映射 - 现在已修复,希望对您有所帮助 我仍然不明白第二个 sn-p 的目的 :( 当我说“2。当我删除地址时,城市没有被触及?”我的意思是说城市行仍会保留。 一般来说。在多对一上进行级联是非常特殊的。因此,您的解决方案很简单(正如我所写的) - 删除该级联。仅将其保留在城市一侧。这将满足您的所有需求。

以上是关于Nhibernate 类映射和级联属性的主要内容,如果未能解决你的问题,请参考以下文章

hibernate初步2

流畅的 NHibernate。更改级联选项时是不是需要重新创建数据库?

SQL 级联删除与级联更新的方法

Mybatis 多对多(易百教程)

如何告诉 Fluent NHibernate 不要映射类属性

具有相同类型属性的 NHibernate 映射类