希望你能帮我解决我遇到的映射问题。目前我有一个视图返回如下内容:
姓名|标题|价格|日期|格式| FormatPriority |
示例数据可能是:
鲍勃|积分| 340 | 01/01/2010 | BAR | 10 |我想要的是一个域模型,如下所示:
string Name;
字符串标题;
int Price;
日期时间日期;
IEnumerable格式;
格式类将具有:
字符串类型
int Priority
目前我们在Fluent NHibernate中使用ClassMap方法(不是自动配置)。我们如何映射这个? Component似乎不支持集合,这不是HasMany关系,因为它作为同一查询的一部分返回。
任何想法??
由于
本
答案 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个组件。
讨厌,我知道。