流畅的NHibernate:来自单个查询的IEnumerable组件映射?

时间:2010-07-01 21:12:02

标签: nhibernate fluent-nhibernate nhibernate-mapping

希望你能帮我解决我遇到的映射问题。目前我有一个视图返回如下内容:

姓名|标题|价格|日期|格式| FormatPriority |

示例数据可能是:

鲍勃|积分| 340 | 01/01/2010 | BAR | 10 |
鲍勃|积分| 340 | 01/01/2010 | FOO | 20 |
鲍勃|积分| 340 | 01/01/2010 | WOO | 40 |

我想要的是一个域模型,如下所示:

string Name;
字符串标题;
int Price;
日期时间日期;
IEnumerable格式;

格式类将具有:

字符串类型
int Priority

目前我们在Fluent NHibernate中使用ClassMap方法(不是自动配置)。我们如何映射这个? Component似乎不支持集合,这不是HasMany关系,因为它作为同一查询的一部分返回。

任何想法??

由于

1 个答案:

答案 0 :(得分:3)

免责声明:这是一个非常大的黑客,我很难发布它。

这是基于您提供的架构,因此可能需要对其进行修改以适应不同的设计。可能有一个更好的方法来做到这一点,但希望这至少会让你再次前进。

问题是您的模型和查询有点不匹配。您的查询返回多个行,您打算将其用于具有多个组件的单个实体,但NHibernate可以将其解释为多个实体,每个实体都包含一个组件。

NHibernate支持组件集合,但仅限于它们存储在单独的表/视图中。这些组件通过外键连接回实体表。 如果您可以更改设计以支持此功能,请执行此操作!

如果没有,我能想到的唯一选择是你的观点上的自我加入。它不会产生最优化的查询,但它应该可以解决问题。

你没有提到你的实体被称为什么,所以我选择了Transaction

public class Transaction
{
    public virtual string Name { get; set; }
    public virtual string Title { get; set; }
    public virtual decimal Price { get; set; }
    public virtual DateTime Date { get; set; }
    public virtual ISet<Format> Formats { get; set; }
}

public class Format
{
    public virtual string Type { get; set; }
    public virtual int Priority { get; set; }

    // OVERRIDE EQUALITY MEMBERS!
}

我使用的映射是:

public class TransactionMap : ClassMap<Transaction>
{
    public TransactionMap()
    {
        Table("vwTransactions");
        Id(x => x.Name);
        Map(x => x.Title);
        Map(x => x.Price);
        Map(x => x.Date);
        HasMany(x => x.Formats)
            .Table("vwTransactions")
            .KeyColumn("Name")
            .Component(c =>
            {
                c.Map(x => x.Type, "Format");
                c.Map(x => x.Priority, "FormatPriority");
            })
            .Fetch.Join();
    }
}

因此,您可以看到映射指向vwTransactions视图。您没有在架构中指定ID,因此我使用Name作为标识(这很重要)。现在跳到HasMany,你可以看到它也指向vwTransactions; NHibernate会看到这个,并在视图上进行自我加入。然后,键列设置为Name,与实体Id相同;这样NHibernate将使用它来解析组件和实体之间的引用,而不是尝试使用整数外键。 Fetch.Join将迫使NH热切地获取这种关系,所以至少我们在那里省了一点。最后要注意的是,Formats属性是ISet,如果你不这样做,你最终会得到重复的组件。

如果您现在为Transaction创建条件(或hql)查询,您将使用其组件返回您的实体;但是,由于每个实体带回多行,您将获得重复项。这很常见,可以使用DistinctRootEntity转换器轻松解决。

var transactions = session.CreateCriteria(typeof(Transaction))
  .SetResultTransformer(Transformers.DistinctRootEntity)
  .List<Transaction>();

应该是这样,你现在最终只有一个实体(基于你的数据集)有3个组件。

讨厌,我知道。