每个子类策略的表中列名错误,层次结构中有抽象类

时间:2011-10-06 09:30:48

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

考虑以下类层次结构:

public abstract class Entity
{
    public virtual int Id { get; private set; }
}

public class ConfiguredBlockEntity : Entity
{
    public virtual ScheduledGreetingEntity ScheduledGreeting { get; set; }
}

public abstract class ConfiguredVariableEditableBlockEntity
    : ConfiguredBlockEntity
{
    public virtual VariableEditableBlockEntity TemplateBlock { get; set; }
}

public class ConfiguredPhoneNumberBlockEntity
    : ConfiguredVariableEditableBlockEntity
{
    public virtual string PhoneNumber { get; set; }
}

我正在使用Fluent NHibernate的自动功能。
这将创建以下表结构:

create table "BlockEntity" (
    Id INT IDENTITY NOT NULL,
   ExecutionOrder INT null,
   Name NVARCHAR(255) null,
   BlockType NVARCHAR(255) null,
   GreetingId INT null,
   primary key (Id)
);

create table "ConfiguredBlockEntity" (
    Id INT IDENTITY NOT NULL,
   ScheduledGreetingId INT null,
   primary key (Id)
);

create table ConfiguredPhoneNumberBlockEntity (
    ConfiguredVariableEditableBlockId INT not null,
   PhoneNumber NVARCHAR(255) null,
   VariableEditableBlockId INT null,
   primary key (ConfiguredVariableEditableBlockId)
);

alter table ConfiguredPhoneNumberBlockEntity 
    add constraint FK87F9EFC9BB9A4B52 
    foreign key (ConfiguredVariableEditableBlockId) 
    references "ConfiguredBlockEntity";

此结果存在一些问题:

  1. ConfiguredPhoneNumberBlockEntity有一列是主键和一个基类的外键(列ConfiguredVariableEditableBlockId。这看起来很奇怪,不符合我通常设计表格的方式。如果我手动设计了这个表,它会有一个Id列是PK,而ConfiguredBlockId列是FK。我可以通过流畅或自动化以某种方式更改它吗?
  2. PK / FK列名为ConfiguredVariableEditableBlockId,但没有表ConfiguredVariableEditableBlock,因为它是一个抽象基类,其属性已合并到ConfiguredPhoneNumberBlockEntity表中。此列引用表ConfiguredBlockEntity,因此应相应地命名。 如何以流畅或自动化方式解决此问题?

1 个答案:

答案 0 :(得分:2)

  1. 继承表不需要额外的Id列,它永远不会单独读取或通过id读取。通常它与baseclass-table连接。因此FNH默认使用此设计。您可以使用FluentMappings强制执行您的设计,隐藏属性ID为Readonly(无值的额外工作)。

  2. class MyJoinedSubclassConvention : IJoinedSubclassConvention,
                                       IJoinedSubclassConventionAcceptance
    {
        public void Accept(IAcceptanceCriteria<IJoinedSubclassInspector> criteria)
        {
            criteria.Expect(x => x.Name == "ConfiguredPhoneNumberBlockEntity");
        }
    
        public void Apply(IJoinedSubclassInstance instance)
        {
            instance.Key.Column("baseclassId");
        }
    }
    
  3. 编辑:或更一般的

    class MyJoinedSubclassConvention : IJoinedSubclassConvention
    {
        public void Apply(IJoinedSubclassInstance instance)
        {
            Type basetype = instance.Extends;
            while (basetype.IsAbstract)
            {
                basetype = basetype.BaseType;
            }
            instance.Key.Column(basetype.Name + "Id");
        }
    }