NHibernate 通过代码 ManyToOne 与 CompositeIdentity 进行映射
Posted
技术标签:
【中文标题】NHibernate 通过代码 ManyToOne 与 CompositeIdentity 进行映射【英文标题】:NHibernate mapping by code ManyToOne with CompositeIdentity 【发布时间】:2013-06-24 08:52:21 【问题描述】:我正在尝试使用 NHibernate 3.3.3 将我的 FluentNHibernate 映射转换为 NHibernate Mapping By-code。目标是升级到 NHibernate 3.3.3 并减少分发的程序集的数量。我在将 FluentNHibernate 的引用映射转换为多对一映射时遇到了一些问题。
我的许多实体都有需要翻译的描述。为此,我使用了一个文本表,其中包含所有可用语言的这些文本。我使用文本 ID 来引用文本表,然后在数据访问对象中过滤所需的语言。这项工作使用 NHibernate 3.1 和 FluentNHibernate 创建,使用 NHibernate 3.3.3 和映射代码但是我只是一个 MappingException 说:属性映射的列数错误:Category.Description 类型:Text。
我的新映射哪里出错了?或者这种类型的映射在 NHibernate 3.3.3 中是不可能的。
这是文本表(SQL-server 2008)。
CREATE TABLE Texts (
ID int NOT NULL,
languageID nvarchar(10) NOT NULL,
Singular nvarchar(max) NOT NULL,
Plural nvarchar(max) NULL,
CONSTRAINT PK_Texts PRIMARY KEY CLUSTERED (ID ASC, languageID ASC)
WITH (PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
文本类:
public class Text
public Text(int id, string language, string singular, string plural)
this.ID = new TextCompositeID(id, language);
this.Singular = singular;
this.Plural = plural;
public TextCompositeID ID get; private set;
public string Plural get; private set;
public string Singular get; set;
public override bool Equals(object obj)
var text = (Text)obj;
if (text == null)
return false;
return this.ID.Equals(text.ID);
public override int GetHashCode()
return this.ID.GetHashCode();
这里以 Category 类为例:
public class Category
public int ID get; set;
public Text Description get; set;
Category 类的 FluentNHibernate xml 映射如下所示:
<class xmlns="urn:nhibernate-mapping-2.2"
mutable="true"
name="Category"
lazy="false"
table="Category"
where="IsObsolete=0">
<id name="ID" type="System.Int32">
<column name="ID" not-null="true" />
<generator class="native" />
</id>
<many-to-one cascade="none"
class="Text"
name="Description">
<column name="TextID"
not-null="true"
unique="false" />
</many-to-one>
</class>
由此生成:
public class CategoryMap : ClassMap<Category>
public CategoryMap()
this.Table("Category");
Not.LazyLoad();
this.Where("IsObsolete=0");
Id(x => x.ID)
.Column("ID")
.GeneratedBy.Native()
.Not.Nullable();
References(x => x.Description)
.Column("DescriptionID")
.Cascade.None()
.Not.Unique()
.Not.Nullable();
这是我创建的 NHibernate ClassMapping:
public CategoryMap()
this.Lazy(false);
this.Mutable(true);
this.Table("Category");
this.Where("IsObsolete=0");
this.Id(
x => x.ID,
map =>
map.Column("ID");
map.Generator(Generators.Native);
);
this.ManyToOne(
x => x.Description,
map =>
map.Cascade(Cascade.None);
map.Class(typeof(Text));
map.Column("TextID");
map.Fetch(FetchKind.Join);
map.Lazy(LazyRelation.NoLazy);
map.ForeignKey("none");
);
从这里我得到这个 xml 映射:
<class name="Category"
lazy="false"
table="Category"
where="IsObsolete=0">
<id name="ID"
column="ID"
type="Int32">
<generator class="native" />
</id>
<many-to-one name="Description"
class="Text"
column="TextID"
fetch="join"
foreign-key="none"
lazy="false" />
</class>
【问题讨论】:
【参考方案1】:我自己找到了答案。我不得不从 Text 类中删除复合 ID:
public class Text
public Text(int id, string language, string singular, string plural)
this.ID = id;
this.LanguageID = language;
this.Singular = singular;
this.Plural = plural;
public int ID get; private set;
public string LanguageID get; private set;
public string Plural get; private set;
public string Singular get; set;
public override bool Equals(object obj)
var text = (Text)obj;
if (text == null)
return false;
return this.ID.Equals(text.ID);
public override int GetHashCode()
return this.ID.GetHashCode();
类别映射已变为:
public CategoryMap()
this.Lazy(false);
this.Mutable(true);
this.Table("Category");
this.Where("IsObsolete=0");
this.Id(
x => x.ID,
map =>
map.Column("ID");
map.Generator(Generators.Native);
);
this.ManyToOne(
x => x.Description,
map =>
map.Column("TextID");
map.Fetch(FetchKind.Join);
map.ForeignKey("none");
map.Lazy(LazyRelation.NoLazy);
);
在数据访问对象中,旧的 QueryOver 查询现在可以让我得到所需的结果。
【讨论】:
以上是关于NHibernate 通过代码 ManyToOne 与 CompositeIdentity 进行映射的主要内容,如果未能解决你的问题,请参考以下文章
如何通过代码将 Id 映射到 NHibernate 映射中的私有支持字段?
通过 NHibernate 代码映射将 GUID 属性作为外键映射到其他实体
Hibernate ManyToOne Mappings 多对一关联映射