You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Fluent NHibernate映射复合键关联时遇异常求助

问题分析与修复方案

嘿,我一眼就揪出问题所在了——你的ClassCMap里的外键列写法犯了个容易忽略的小错误!

错误根源

你在ClassCMap里写了:

References(n => n.ClassB).Columns("ClassBId, ClassAId, Version").Not.Nullable();

这里的问题是:当你把多个列名放在同一个字符串里用逗号分隔时,Fluent NHibernate会把它当成一个完整的列名(而不是三个独立的列)。这就导致NHibernate误以为ClassC的外键只有1列,但ClassB的复合主键有3列,自然就触发了列数不匹配的FKUnmatchingColumnsException。

修复步骤

1. 修正ClassC的外键列映射

把列名拆成独立的字符串参数传给Columns方法,或者用Columns.Add逐个添加,让NHibernate识别出三个独立的外键列:

public ClassCMap() 
{ 
    Table("ClassC"); 
    Id(c => c.Id); 
    // 推荐写法:拆分多个参数
    References(n => n.ClassB)
        .Columns("ClassBId", "ClassAId", "Version")
        .Not.Nullable();
    
    // 或者用Add方式也可以
    // References(n => n.ClassB)
    //     .Columns.Add("ClassBId")
    //     .Columns.Add("ClassAId")
    //     .Columns.Add("Version")
    //     .Not.Nullable();
}

2. 修正ClassBMap里的属性名笔误

你的ClassB类里的集合属性是ClassCCollection,但映射里写的是HasMany(c => c.Edges),这会导致NHibernate找不到对应的属性,得改成:

public ClassBMap() 
{ 
    Table("ClassB"); 
    CompositeId() 
        .KeyProperty(c => c.Id) 
        .KeyReference(c => c.ClassA, "ClassAId") 
        .KeyProperty(c => c.Version); 
    HasMany(c => c.ClassCCollection) // 这里改成和类里一致的属性名
        .Inverse() 
        .Cascade.All().AsList()
        .KeyColumns.Add("ClassBId", "ClassAId", "Version"); 
}

3. 补上ClassB缺失的Version属性

你当前的ClassB类定义里没有Version属性,但映射里用了这个字段作为复合主键的一部分,必须补上:

public class ClassB 
{ 
    public virtual int Id { get; set; } 
    public virtual ClassA ClassA { get; set; } 
    public virtual int Version { get; set; } // 新增这个属性
    public virtual ICollection<ClassC> ClassCCollection { get; set; } 
}

验证效果

做完这三处修改后,NHibernate就能正确识别ClassC的外键是三个列,和ClassB的复合主键列数完全匹配,SchemaUpdate就不会再抛出那个异常了。

内容的提问来源于stack exchange,提问作者xecollons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 07:38:11