NHibernate:映射成员是未映射的类的实例

时间:2013-12-02 13:27:11

标签: c# nhibernate mapping

我正在使用NHibernate的程序,我有以下问题: 我的一些类的成员是基本上只定义一些处理程序的类的实例。

例如

public class Foo
{
    virtual public ResultHandler handler {get; set;}
    virtual void Bar()
    {
       ...
       handler.HandleResult(...);
    }
}

public abstract class ResultHandler
{
    abstract public void HandleResult(...);
}

public class ResultPrint : ResultHandler
{
    override public void HandleResult(...)
    {
        ...
    }
}

public class ResultExport : ResultHandler
{
    override public void HandleResult(...)
    {
        ...
    }
}

现在ResultPrint和ResultExport没有任何成员,因此它们不必映射到数据库中的表,但是当我存储/检索Foo的实例时,我想以某种方式存储&加载成员“handler”。

我可以将类名存储在字符串中并使用反射来加载它(但是在重命名类的情况下这会不稳定,这会浪费数据库中的空间)。存储单个字节就足够了 - 但我如何告诉NHibernate呢?

我能想到的最好的方法是映射像

这样的虚拟成员
virtual public byte HandlerClass
{
    get
    {
        if(handler == null)
            return 0;
        switch(handler.GetType())
        {
            case typeof(ResultPrint):
                return 1;
            ... 
        }
    }
    set
    {
        switch(value)
        {
            case 0:
                handler = null;
                break;
            case 1:
                handler = new ResultPrint();
                break;
            ...
        }
    }
}

但对于应该是常见用例的事情来说,这是非常复杂的...... 必须有一种“干净”的方式让NHibernate自己做到这一点。 任何人都可以帮助我吗?

亲切的问候

AlgoMan

编辑:我正在使用基于XML的映射btw。

2 个答案:

答案 0 :(得分:1)

我认为,虽然具体类ResultPrint和ResultExport不是任何实例成员,但抽象类ResultHandler有一些成员要保存在数据库中。

您可以将ResultHandler,ResultPrint和ResultExport映射到一个带有鉴别器列的表中。

例如:

<class name="ResultHandler" abstract="true" table="ResultHandlers">
    <id name="Id">
        <generator class="identity"/> <!-- WHATEVER IS YOUR IDENTITY HERE! -->
    </id>
    <discriminator column="type" not-null="true" type="System.String"/>

    <subclass name="ResultPrint" discriminator-value="print">
    </subclass>

    <subclass name="ResultExport" discriminator-value="export">
    </subclass>
</class>

除了普通列之外,ResultHandlers表还必须有一个附加列来映射子类,在上面的映射示例中,这些列是“类型”列。

当子类为ResultPrint时,当这些类中的一个对象首次保存在数据库中时,此列将自动填充为ResultExport的“print”或“export”。

答案 1 :(得分:0)

正如您所指出的,您的ResultHandler个对象不需要保留。 事实上,这似乎并不像NH问题。

只需保留一些允许重建正确ResultHandler的数据来保持你的Foo状态对我来说似乎是正确的方法。

唯一的问题是ResultHandler不应该处理从一个字节构建Foo的逻辑。它应该属于一个专用类,并且可以重用(如果你愿意的话,也许你可以使用一些依赖注入机制)

这会导致类似:

private byte _handlerClass;
virtual public byte HandlerClass{
               get{return _handlerClass; }
               set{_handlerClass = value; _handler =null;}
             }

private ResultHandler _handler;   
public virtual ResultHandler Handler
{
    get{
       return _handler ?? (_handler = HandlerServiceLocator.GetHandler(HandlerClass));
    }
}

然后,从一个字节构建ResultHandler的专用类:

public class HandlerServiceLocator
{

  public static ResultHandler GetHandler(byte value)
  {
        switch(value)
        {
            case 0:
                return null;
            case 1:
                return  new ResultPrint();
            ...
        }
        return null;
  }
}