【问题标题】:how to flatten a model with NHibernate如何使用 NHibernate 展平模型
【发布时间】:2012-09-18 21:50:41
【问题描述】:

假设我有三个表 Products、Languages 和 ProductTranslations,如下所示:

(1) 产品编号
(1) 标准名称
(1) 价格

(2) 语言 ID
(2) 语言名称

(3) ProductTranslationId
(3) 产品编号
(3) 语言标识
(3) 本地名称
(3) 本地描述

在我的对象模型中,我需要一个包含以下内容的单个对象(单个类映射)

(3) ProductTranslationId
(2) 语言
(3) 本地名称
(3) 本地描述
(1) 价格

这个对象只用于显示,所以只读(不可变)就可以了。

ProductTranslationId 唯一标识一行。

如有必要,此对象还可以包含 LanguageID 和 ProductID 值。重要的特征是,这需要包含来自该一对多关系的 ONE 一侧的 Language 和 Price 值。

我可以看到如何使用多对一在 3 个单独的类中执行此操作,但是如何使用一个类执行此操作,其中 ProductTranslationId 是 值?

是否有不需要在数据库中创建视图的替代方法?

【问题讨论】:

    标签: nhibernate nhibernate-mapping one-to-many many-to-one


    【解决方案1】:

    选项 1

    // FluentNHibernate Mapping
    public class ProductTranslationDtoMap : ClassMap<ProductTranslationDto>
    {
        public ProductTranslationDtoMap()
        {
            ReadOnly();
            Table(" ProductTranslation");
            Id(x => x.Id, "ProductTranslationId");
    
            Map(x => x.Language).Formula("(SELECT l.LanguageName FROM Language l WHERE l.LanguageId = LanguageId)");  // simple and highly portable sql formula
            Map(x => x.LocalName);
            Map(x => x.LocalDescription);
            Map(x => x.Price).Formula("(SELECT p.Price FROM Products p WHERE p.ProductId =  ProductId)");
        }
    }
    

    选项 2

    Product prod = null;
    Language lang = null;
    TranslationDto alias = null;
    var results = session.QueryOver<ProductTranslation>()
        .JoinAlias(pt => pt.Language, () => lang)
        .JoinAlias(pt => pt.Product, () => prod)
        .SelectList(list => list
            .Select(pt => pt.Id).WithAlias(() => alias.ProductTranslationId)
            .Select(() => lang.Name).WithAlias(() => alias.Language)
            ...)
        .TransformUsing(Transformers.AliasToBean<TranslationDto>())
        .List<TranslationDto>();
    

    【讨论】:

    • 谢谢菲罗。不确定我是否完全理解选项 1。那是使用 HQL 还是 SQL?我之所以问是因为我正在尝试(希望)避免使用特定的 SQL 方言以实现可移植性。选项 2 是有道理的(我认为),但对我来说澄清一下。这是我的数据访问层的代码,而不是我的映射文件。这也需要 4 个类来支持我的示例:Product、Language、TranslationDto 和 ProductTranslation。这就是你提议的吗?您是否建议无法将这 3 个表映射到一个类?另外,什么是 Transformers.AliasToBean?我不使用 Java 有关系吗?
    • 1. 公式是 SQL 2. 我假设您已经有不同表的类,那么选项 2 很好 3. Transformers.AliasToBean() 继承了 Hibernate 的名称,但它是一个 NHibernate 类,它将别名名称映射到属性
    【解决方案2】:

    除了使用 NHibernate 映射之外,您还可以使用 AutoMapper 之类的类映射器来创建复杂对象图的平面表示。如果您的数据库架构发生更改,其优点是可以减少维护一个休眠映射(尽管 Firo 的流利变体提供编译器语法检查)。缺点当然是速度,因为您首先必须让 nhibernate 创建复杂的对象图,然后将该图转换为平面对象。如果您只需要这个平面对象,则最好使用单个 NH 映射。如果您考虑创建更多视图,类映射器可能值得一看。

    【讨论】:

    • AutoMapper 很棒。我同意。除了 ProductDTO 之外,这也需要我有 Product、Language 和 ProductTranslation 类,并且有(最少的)代码来调用 AutoMapper 来转换模式。我的问题是,NHibernate 有没有办法将 3 个表之间的关系映射到一个类(实体)中?这可能吗?
    • 如果您还没有映射单独的类,自动映射器确实需要比单个 NH 映射更多的工作。在这种情况下,您应该尝试 Firos answer 中的选项之一。
    猜你喜欢
    • 2010-11-22
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 2011-06-18
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多