使用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
相关产品推荐
相关产品推荐

