我遇到了一个名为ScheduledJobs的数据库表,其中包含大量的列和一个具有相同gazillion属性的匹配C#对象。我对它的设计并不感到兴奋,并希望使用每子类表策略来分解它。而不是
public class ScheduledJobs
{
public int ID { get; set; } // always needed
public int JobTypeID { get; set; } // always needed to distinguish A from B
public int Foo { get; set; } // needed by Job A
public int Bar { get; set; } // needed by Job B
}
我有
public abstract class ScheduledJob
{
public int ID { get; set; }
public ScheduledJobType JobType { get; set; }
}
public class ScheduledJobA : ScheduledJob
{
public int Foo { get; set; }
}
public class ScheduledJobB : ScheduledJob
{
public int Bar { get; set; }
}
我重写了NHibernate .hbm.xml文件(没有流利,抱歉):
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="ScheduledJob" table="ScheduledJobs" abstract="true" lazy="false">
<id name="ID" column="ID" type="Int32" unsaved-value="0">
<generator class="identity" />
</id>
<many-to-one name="ScheduledJobType" column="JobTypeID" class="ScheduledJobType" />
<joined-subclass name="ScheduledJobA" table="ScheduledJobsA" lazy="false">
<key column="JobID" />
<property name="Foo" type="Int32" />
</joined-subclass>
<joined-subclass name="ScheduledJobB" table="ScheduledJobsB" lazy="false">
<key column="JobID" />
<property name="Bar" type="Int32" />
</joined-subclass>
</class>
</hibernate-mapping>
大!我的麻烦是,我无法弄清楚如何明智地获取子类作业。一张大桌子的好处是不必担心类型或铸造:
ScheduledJob job = Repository.ScheduledJob.Get(id);
在我的设置中,我有相同的ID(这应该足够了;它仍然是唯一的),但我不知道这种类型:我必须获取抽象作业,检查JobTypeID,找到相关的C#子类,并在该子类下重新获取它。
如果需要,我可以引入JobTypeID。我仍然需要将该ID与与之关联的作业子类表配对。
简而言之,我需要能够让我从NHibernate收到的ScheduledJob对象成为正确的子类,尽可能少的干预。在这里使用鉴别器的能力会很棒,但官方文件说不允许这样做。这种设计让我觉得我从根本上误解了某些东西;随时指出我正确的方向。
谢谢!
答案 0 :(得分:1)
在我的设置中,我有相同的ID(这应该足够了;它仍然是 独特的,但我不知道这种类型:我必须获取摘要 job,检查JobTypeID,找到关联的C#子类,然后重新获取 它在那个子类下。
实际上,您既不需要检查JobTypeID
,也不必再次获取它。这是NHibernate的工作:在初始获取时,它将确定适当的派生类型并自动为您实例化此类型的对象。
如果需要在获取对象后查询类型,可以使用C#类型检查和转换:
ScheduledJob job = Repository.ScheduledJob.Get(id);
if (job is ScheduledJobA)
{
ScheduledJobA jobA = (ScheduledJobA)jobA;
ProcessJobA(jobA);
}
else if (job is ScheduledJobB)
{
ScheduledJobB jobB = (ScheduledJobB)jobB;
ProcessJobB(jobB);
}