我有遗留数据库映射问题。数据库将其所有查找值(代码/描述)存储在一个表中,由类型代码字段区分。引用它的表使用一列(代码,没有类型代码)。代码表没有主键约束(!)。
我有一个看起来像这样的课程:
public class Code
{
[StringLength(8)]
public virtual string CodeValue { get; set; }
[StringLength(2000)]
public virtual string Description { get; set; }
public virtual long? OrderBy { get; set; }
public virtual DateTime? StopDate { get; set; }
}
我的初始映射看起来像这样:
public class CodesMap : ClassMap<Code>
{
public CodesMap()
{
Table("CODES");
Id(x => x.CodeValue).Column("CODE_CODE").GeneratedBy.Assigned();
Map(x => x.Description).Column("DESCRIPTION");
Map(x => x.OrderBy).Column("ORDER_BY");
DiscriminateSubClassesOnColumn("TYPE_CODE", "INVALID")
.SqlType("VARCHAR2");
}
}
然后有一堆子类只有它们的鉴别器值不同。
另一个映射可能会将其引用为:
...
References<FacilityType>(x => x.Type).Column("FACIL_TYPE_CODE").ReadOnly();
...
现在,这一切都很好,并且一切正常,因为该引用知道了类,因此知道了查询的鉴别器值,除了...我只是遇到了CODE_CODE在两者之间不唯一的情况同一会话中不同类型的对象(两种代码的子类型)。糟糕。
CODE_CODE和TYPE_CODE是唯一的,所以正确的做法应该是将它们用作复合键。但是后来我在其他类映射中的引用变得不可能,因为那些表只有一个列外键(显然没有在表上定义FK约束)。
如果不在代码表上添加代理键,我该怎么办?
答案 0 :(得分:2)
如果我们需要将查找值映射为只读,那么解决方案将非常简单。我们将显式映射每个子类,而不是显式继承。鉴别器将被移动到 WHERE 子句:
public FacilityTypeMap()
{
Table("CODES");
// here we will use explicit runtime discriminator
// injected by NHibernate into each SELECT .. FROM clause for this type
Where(" TYPE_CODE = 'FACIL_TYPE' " )
Id(x => x.CodeValue).Column("CODE_CODE").GeneratedBy.Assigned();
Map(x => x.Description).Column("DESCRIPTION");
Map(x => x.OrderBy).Column("ORDER_BY");
// no more inheritance
// DiscriminateSubClassesOnColumn("TYPE_CODE", "INVALID")
// .SqlType("VARCHAR2");
}
这非常适用于SELECT。我们只需要为每个Discriminator ==每个派生类型重复该映射。
请参阅5.1.3. class:
<class
name="ClassName" (1)
table="tableName" (2)
...
where="arbitrary sql where condition" (11)
(11)
where
(可选)指定在检索此类对象时要使用的任意SQLWHERE
条件
如果我们还需要使用这个类进行插入,我们还需要做更多的步骤。将列'TYPE_CODE'
明确映射为例如判别器,并在构造函数中设置它以纠正值(例如'FACIL_TYPE'
)。它可以是映射为.Not.Update()
string _discriminator = "FACIL_TYPE";
public virtual string Discriminator { get { return _discriminator; } protected set {} }
...
// mapping
Map(x => x.Discriminator, "TYPE_CODE").Not.Update()