将不可变结构映射为NHibernate中的组件

Pau*_*ner 9 nhibernate struct nhibernate-mapping

我正在测试NHibernate是我公司ORM需求的解决方案.为此,我基于学校制作了一个小型测试模型,为NHibernate提供了一些有用的边缘案例.

我在查找如何在不使用IUserType接口的情况下将自定义结构映射为实体的组件时遇到了问题.我要强调的是,域类与NHibernate代码在一个单独的程序集中是一个重要的要求,并且域程序集没有对NHibernate的引用.

自定义结构Time用于表示以小时和分钟为单位的时间.这是一个非常简单的不可变结构,仅用于说明自定义结构的问题.构造函数接受一个小时和分钟的参数,作为表单中的整数hhmm.

public struct Time
{
    public Time(int hoursAndMinutes)
    {
        // Initialize Structure //
    }

    public int Hours { get; private set; }

    public int Minutes { get; private set; }

    public int HoursAndMinutes { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)

此结构用作Lesson类的一个组件,用于存储课程开始的时间:

public class Lesson
{
    public int ID { get; private set; }
    public Teacher Teacher { get; internal set; }
    public DayOfWeek Day { get; set; }
    public Time StartTime { get; set; } // <-- Custom Type
    public int Periods { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

该类直接映射到此表:

CREATE TABLE Lessons
(
    ID INT,
    Subject NVARCHAR(128)
    TeacherID INT,
    Day VARCHAR(9),
    StartTime INT, // <-- Maps to custom type.
    Periods INT
)
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法将这个结构映射为Lesson类的一个组件,以便NHibernate将读取结构上的属性值(像任何其他组件一样)来获取列的值,但是将初始化一个新的实例通过将列值读取到实体中时将列值传递给构造函数的结构.

如果您有任何建议,那就是超级.如果你想告诉我,如果不使用它就无法实现IUserType,那也是一个很好的答案.

Nic*_*cki 16

据我所知,有三种攻击计划.

  • 您可以将组件直接映射到自定义类型的属性中.在这个例子中,让NHibernate设置HoursAndMinutes属性,更改该属性的setter中的代码以适当地更新HoursMinutes属性,并让构造函数调用,this.HoursAndMinutes = hoursAndMinutes;以便更新HoursMinutes属性的相同代码被执行,无论是使用构造函数还是HoursAndMinutes酒店使用了setter .如果你没有使用ORM并且知道它会干掉那个属性,你会这样写吗?可能不是.但这不是世界末日,评论可以解释一切.

  • 你写一个IUserTypeICompositeUserType实现.实际上,它们恰好适用于这种情况,并且您可以灵活地实例化结构,但是您可以在NullSafeGet()实现中随意提取数据,然后在实现中提取数据NullSafeSet().MyModel.NHibernateCrap.dll如果你愿意的话,把它放在另一个组件中.您的模型/域不需要知道IUserType实现或NHibernate存在 - 这是映射文件指定的全部内容.

  • 您可以使用Miki Watts在其答案中描述的基于代码的解决方法.也就是说,NHibernate映射中的组件映射到模型类型中的字段或私有属性,这些属性执行一些魔术手动以将它们转换为应用程序使用的公共属性,反之亦然.(它与我提供的第一个选项类似;唯一的区别是,在他的场景中,该字段是一种解决方法,它允许遗留数据库泄漏到类实现中,但不会泄漏到应用程序或模型的其他部分.对于小的,孤立的情况,或者如果遗留数据库只是生活中的事实,那么我认为这是完全合理的.)

为了直接和现实地回答你的问题,NHibernate不会调用具有参数的构造函数,句点 - 它只是它的工作方式,它会新闻一个对象,然后开始设置和反思它 - 除非你开始做奇怪的事情带代理的东西或告诉它使用你的IUserType实现.没有机制可以<constructor><arg>HoursAndMinutes</arg></constructor>在映射文件或类似的东西中说出类似的东西.不要担心并且喜欢炸弹.

既然IUserType是NHibernate提供的机制来做这些事情,我真的不明白为什么人们不想使用它.

祝好运!