流畅的NHibernate - 如何使用鉴别器创建每子类表映射?

时间:2012-03-27 10:57:12

标签: c# nhibernate fluent-nhibernate fluent-nhibernate-mapping

我在SO和google上看了很多关于nhibernate / fluent-nhibernate中的子类映射的问题,并没有设法找到与我有同样问题的人。我遵循了fluent-nhibernate wiki(http://wiki.fluentnhibernate.org/Fluent_mapping#Subclasses)的基本指令,但这没有帮助。

我有一个名为Operation的基本实体 - 它有一个与之关联的基表,然后我有子表UnpaidCheque,Refund等 - 每个子表的主键是一个外键,OperationId( PK)来自Operation表。

当我创建持久性规范并尝试验证我的映射时,它尝试将所有列保存到Operation表,而不是保存到Operation表,然后将Unpaid Check的特定列保存到UnpaidCheque表。

错误是:

could not insert: [UnpaidCheque][SQL: INSERT INTO Account.Operation (PaymentId, Amount, UnpaidOn, UnpaidByUserId, OperationType) VALUES (?, ?, ?, ?, 'U'); select SCOPE_IDENTITY()]
  ----> System.Data.SqlClient.SqlException : Invalid column name 'UnpaidOn'.
Invalid column name 'UnpaidByUserId'.

正如您所看到的,它正在尝试在UnpaidByUserId和UnpaidOn列中保存值,这些列是子表/类的成员而不是基础。

从好的方面来说,它试图在“操作类型”列中插入“U”的事实向我表明它似乎正在为类类型设置正确的描述符值。我已经指定了operationtype的唯一地方是在类映射中的DiscriminatorValue()调用中,我没有在其他地方明确地设置它。

类层次结构如下:

public class Operation
    {
        public virtual long OperationId { get; set; }
        public virtual string OperationType { get; set; }
        public virtual long? PaymentId { get; set; }
        public virtual decimal Amount { get; set; }
    }

public class UnpaidCheque : Operation
    {
        public virtual DateTime UnpaidOn { get; set; }
        public virtual long UnpaidByUserId { get; set; }
    }

类映射是:

public class OperationMap : ClassMap<Operation>
    {
        public OperationMap()
        {
            Schema("Account");
            Table("Operation");
            LazyLoad();
            Id(_ => _.OperationId).Column("OperationId").GeneratedBy.Identity();
            Map(_ => _.PaymentId).Column("PaymentId").Nullable();
            Map(_ => _.Amount).Column("Amount").Not.Nullable();

            DiscriminateSubClassesOnColumn("OperationType");
        }
    }
public class UnpaidChequeMap : SubclassMap<UnpaidCheque>
{
    public UnpaidChequeMap()
        {
            Schema("Account");
            Table("UnpaidCheque");
            LazyLoad();
            DiscriminatorValue("U");
            KeyColumn("OperationId");
            Map(_ => _.UnpaidOn).Column("UnpaidOn").Not.Nullable();
            Map(_ => _.UnpaidByUserId).Column("UnpaidByUserId").Not.Nullable();
        }
}

除了在子类映射中添加KeyColumn()之外,我看不到任何与示例不同的内容,但是我也得到了相同的错误消息。任何人都可以对我错过的内容有所了解,或者我想要实现的目标是否得到了nhibernate的支持?据我所知,它应该是。

提前致谢!

2 个答案:

答案 0 :(得分:2)

要使用带有鉴别器的table-per-subclass,可以使用以下方法:

public class UnpaidChequeMap : SubclassMap<UnpaidCheque>
{
    public UnpaidChequeMap()
    {
        Schema("Account");
        DiscriminatorValue("U");
        Join("UnpaidCheque", j =>
        {
            j.KeyColumn("OperationId");
            j.Map(_ => _.UnpaidOn).Column("UnpaidOn").Not.Nullable();
            j.Map(_ => _.UnpaidByUserId).Column("UnpaidByUserId").Not.Nullable();
        }
    }
}

答案 1 :(得分:1)

我们找到了解决方案:

描述符仅适用于所有子类存储在数据库中的同一个表中的映射。

删除行:

DiscriminateSubClassesOnColumn("OperationType");

来自父映射和

DiscriminatorValue("U");

从子映射,随后从数据库中删除列解决了问题。