免責聲明:這是這樣一個龐大的黑客攻擊,它的痛苦,我將它張貼。
這是基於您提供的模式,因此可能需要修改以適應不同的設計。可能有更好的方法來做到這一點,但希望這應該讓你至少再次去。
問題是你的模型和查詢有一點不匹配。您的查詢返回多個行,您打算使用多個組件的單個實體,但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個組件。
討厭,我知道。
雖然我確信這會起作用,但我接受了您的建議並改變了視圖返回數據的方式。我現在每個關係都有觀點...希望它能工作:) – 2010-07-04 13:17:30