nhibernate - Fluent Nhibernate 复合键映射

标签 nhibernate fluent-nhibernate fluent-nhibernate-mapping

我试图弄清楚这个问题很长一段时间。我有一个 hacky 的方法来让它工作。

我只想知道这在 Fluent NHibernate 映射中是否可行。

假设我有两个表,例如:

Table ComissionLevel
{
    Year,
    ComissionLevelID,

    ... other properties ....
}
primary key (Year,ComissionLevelID)

Table ClientCommission
{
    Year,
    ClientID,
    CommissionLevelID_1,
    CommissionLevelID_2,

    ... other properties ...
}
primary key (Year,ClientID)
foreign key CommissionLevel1 (Year,CommissionLevelID_1)
foreign key CommissionLevel2 (Year,CommissionLevelID_2)

目前我的映射如下:
public ComissionLevelMap()
{
  Schema("XXXX");
  Table("ComissionLevel");
  LazyLoad();
  CompositeId()
    .KeyProperty(x => x.Year, set => {
        set.ColumnName("Year");
        set.Access.Property(); } )
    .KeyProperty(x => x.CommissionLevelID, set => {
        set.ColumnName("CommissionLevelID");
        set.Length(10);
        set.Access.Property(); } );

  HasMany<ClientCommission>(x => x.ClientCommissions)
    .Access.Property()
    .AsSet()
    .Cascade.AllDeleteOrphan()
    .LazyLoad()
    .Inverse()
    .Generic()
    .KeyColumns.Add("Year", mapping => mapping.Name("Year")
                                                         .SqlType("NUMBER")
                                                         .Nullable())
    .KeyColumns.Add("CommissionLevelID_1", mapping => mapping.Name("CommissionLevelID_1")
                                                         .SqlType("VARCHAR2")
                                                         .Nullable()
                                                         .Length(10));
  HasMany<ClientCommission>(x => x.ClientCommission2s)
    .Access.Property()
    .AsSet()
    .Cascade.AllDeleteOrphan()
    .LazyLoad()
    .Inverse()
    .Generic()
    .KeyColumns.Add("Year", mapping => mapping.Name("Year")
                                                         .SqlType("NUMBER")
                                                         .Nullable())
    .KeyColumns.Add("CommissionLevelID_2", mapping => mapping.Name("CommissionLevelID_2")
                                                         .SqlType("VARCHAR2")
                                                         .Nullable()
                                                         .Length(10));
}

public ClientCommissionMap()
{
  Schema("XXXXX");
  Table("ClientCommission");
  LazyLoad();
  CompositeId()
    .KeyProperty(x => x.ClientID, set => {
        set.ColumnName("ClientID");
        set.Length(10);
        set.Access.Property(); } )
    .KeyProperty(x => x.Year, set => {
        set.ColumnName("Year");
        set.Access.Property(); } );
  References(x => x.ComissionLevel1)
    .Class<ComissionLevel>()
    .Access.Property()
    .Cascade.None()
    .LazyLoad()
    .Insert()
    .Update()
    .Columns("Year", "CommissionLevelID_1");
  References(x => x.ComissionLevel2)
    .Class<ComissionLevel>()
    .Access.Property()
    .Cascade.None()
    .LazyLoad()
    .Insert()
    .Update()
    .Columns("Year", "CommissionLevelID_2");

}

我现在的问题是每当我创建一个 CommissionLevel 并将 ClientCommission 分配给它的集合时,如果我通过调用 session.save(CommissionLevel) 保存它们,它会抛出一个异常
<Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index>.

我的问题是:
  • NHibernate 会自动保存关系吗?喜欢:
        ClientCommission commission = new ClientCommission{Year = 2012, ClientID =SomeGuid};
        CommissionLevel  newCommissionLevel = new CommissionLevel{Year = 2012, CommissionLevelID =NewCommissionLevelGuid};
    
        newCommissionLevel.ClientCommission1s.Add(commission);
        newCommissionLevel.ClientCommission2s.Add(commission);
    
        CommissionLevelRepo.Save(newCommissionLevel);
    

    当我调用 CommissionLevelRepo.Save(newCommissionLevel) 时,NHibernate 是否也会更新 ClientCommission.ComissionLevel1 和 ClientCommission.ComissionLevel2

  • 或者我必须说
    ClientCommission.ComissionLevel1 = newCommissionLevel; 
    ClientCommission.ComissionLevel2 = newCommissionLevel; 
    
  • 对于我得到的异常(exception),这是因为 NHibernate 没有生成正确的列,它似乎会生成三个 Year 列。因为如果我手动创建两个名为 ComissionLevelID1 和 CommissionLevelID2 的属性,禁用 ClientCommission 上的 .Insert() 和 .Update() 它将正确保存它。

  • 有人可以告诉我映射这两个类的正确方法吗?

    非常感谢。

    最佳答案

    简答:您不能为多个引用共享列

    长答案: NHibernate 处理每个引用彼此独立,但确实消除了插入语句中的重复列,因此引用尝试访问不再存在的列。这样做是因为如果对象模型中的 to 引用之间的共享列不同,则它无法确定哪个是正确的。

    如果您可以更改数据库架构并使 ID 唯一,则在 ID 和引用中一起忽略年份。

    更新:

    你可以简化一些映射

    CompositeId()
        .KeyProperty(x => x.Year, set => {
            set.ColumnName("Year");
            set.Access.Property(); } )
        .KeyProperty(x => x.CommissionLevelID, set => {
            set.ColumnName("CommissionLevelID");
            set.Length(10);
            set.Access.Property(); } );
    
    // to
    CompositeId()
        .KeyProperty(x => x.Year)  // columnname is equal propertyname by default
        .KeyProperty(x => x.CommissionLevelID, set => set.Length(10).Access.Property());  // property is default access and can also be left out
    
    
    .SqlType("VARCHAR2").Length(10)
    // to
    .Length(10) or .SqlType("VARCHAR2")
    // because length is ignored when sqltype is specified
    

    关于nhibernate - Fluent Nhibernate 复合键映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11286892/

    相关文章:

    mysql - 使用 NHibernate 从带有外键的 MySQL 表中获取数据

    fluent-nhibernate - 类别/子类别树的 Fluent NHibernate 映射

    nhibernate - 流利的NHibernate-不必要的更新

    c# - 如何将复合外键映射到 FluentNHibernate 中的非主唯一键?

    c# - 显示日期范围内的数据

    NHibernate Linq 提供程序问题

    nhibernate - CaSTLe ActiveRecord 表名称冲突

    c# - FluentNHibernate 中的 ClassMapping<T>.Property() 等效项

    nhibernate - Fluent NHibernate 表命名约定不起作用

    c# - 使用鉴别器的 Fluent NHibernate 的多级继承