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

标签 nhibernate struct nhibernate-mapping

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

我在找出如何将自定义结构映射为实体的组件时遇到问题 不使用 IUserType接口(interface) .我应该强调,域类与我们的 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; }
}

此结构用作 Lesson 的组件。类来存储类(class)开始的时间:
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; }
}

此类直接映射到此表:
CREATE TABLE Lessons
(
    ID INT,
    Subject NVARCHAR(128)
    TeacherID INT,
    Day VARCHAR(9),
    StartTime INT, // <-- Maps to custom type.
    Periods INT
)

我正在寻找一种方法来将此结构映射为 Lesson 的组件。类,以便 NHibernate 将读取结构上的属性值(与任何其他组件一样)以获取列的值,但在从列到实体中。

如果您有任何建议,那就太好了。如果你想告诉我这不能不使用 IUserType 来完成,这也是一个很好的答案。

最佳答案

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

  • 您可以将组件直接映射到自定义类型的属性中。在这个例子中,让 NHibernate 设置 HoursAndMinutes属性,更改该属性的 setter 中的代码以更新 HoursMinutes适当的属性,并让构造函数调用 this.HoursAndMinutes = hoursAndMinutes;所以更新 Hours 的代码相同和 Minutes无论是使用构造函数还是 HoursAndMinutes 上的 setter ,属性都会被执行使用属性。如果您不使用 ORM 并且知道它会欺骗该属性,您会这样写吗?可能不是。但这不是世界末日,评论可以解释一切。
  • 你写一个 IUserTypeICompositeUserType执行。确实,它们正是针对这种情况而存在的,并且可以让您灵活地在 NullSafeGet() 中随心所欲地实例化结构。在 NullSafeSet() 中实现并提取数据执行。把它放在另一个程序集中,比如 MyModel.NHibernateCrap.dll , 如果你喜欢。您的模型/域无需知道 IUserType实现或 NHibernate 存在——这都是映射文件指定的。
  • 您使用 Miki Watts 在他的回答中描述的基于代码的解决方法。也就是说,您在 NHibernate 映射中的组件映射到模型类型中的字段或私有(private)属性,这些字段或私有(private)属性会做一些神奇的挥手以将它们转换为应用程序使用的公共(public)属性,反之亦然。 (它类似于我提供的第一个选项;唯一的区别是,在他的场景中,该字段是一种解决方法,它允许遗留数据库泄漏到类实现中,但不会泄漏到应用程序或模型的其他部分。对于小型、孤立的案例,或者如果遗留数据库只是一个事实,那么我认为这是完全合理的。)

  • 直接、真实地回答您的问题, NHibernate 不会调用有参数的构造函数,句号 ——这就是它的工作原理,它通知一个对象,然后开始设置和反射(reflect)它——除非你开始用代理做奇怪的事情或告诉它使用你的IUserType执行。没有机制可以说出像 <constructor><arg>HoursAndMinutes</arg></constructor> 这样的话在映射文件或类似文件中。别担心,爱炸弹。

    由于IUserType是 NHibernate 为做这些事情提供的机制,我真的不明白为什么一个人不想使用它。

    祝你好运!

    关于nhibernate - 将不可变结构映射为 NHibernate 中的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1985002/

    相关文章:

    c - 如何实现继承: error: conflicting declaration ‘typedef struct

    nhibernate - 命名查询未知错误尝试使用 Fluent NHibernate 调用存储过程

    复合键的 JPA 映射问题

    c# - 代码中的 nHibernate 3.2 数据库配置?

    reflection - 使用 Go 反射包获取结构字段标签

    c - 重用命名结构作为嵌套结构会触发 GCC 中的重新定义错误

    c# - NHibernate:读取 mysql Blob 字段 - 值返回为 "System.Byte[]"

    asp.net - Nhibernate异常:"Unknown column ' **.**_id'在 'field list'“

    nhibernate - nhibernate 中的 SQL Server FileStream 类型

    创建触发器时出现 SQLiteException « "ON"附近的逻辑错误 »