2010-09-10 80 views
0

我有4個數據庫表(頻道,用戶,消息,User2Channel),並根據實體類:NHibernate的許多一對多和SELECT N + 1問題

class **Channel** { 
int ChannelId {get;set;} 
int ISet<User> UsersToChannel {get;set;} 
... 
} 
class **Message** { 
int MessageId {get;set;} 
Channel Channel {get;set;} 
User User {get;set;} 
... 
} 
class **User**{ 
int UserId {get;set;} 
ISet<Channel> Channels {get;set;} 
... 
} 

我使用fluentnhibernate映射:

class **ChannelMap** { 
    ChannelMap(){ 
     ... 
     HasManyToMany(x => x.UsersInChannel) 
       .AsSet() 
       .Cascade.All().Inverse() 
       .Table("User2Channel") 
       .Not.LazyLoad(); 
    } 
} 
class **UserMap** { 
    UserMap(){ 
     HasManyToMany(x => x.Channels) 
       .AsSet() 
       .Cascade.All() 
       .Table("User2Channel") 
       .Not.LazyLoad(); 
    } 
} 

我在此代碼加載消息:

... 
var query = session.CreateQuery(@"select m from Message m"); 
var msgs = query.List<Message>(); 
... 

在探查我看到許多疑問是這樣的:

SELECT ... FROM User2Channel WHERE ChannelId=654 
SELECT ... FROM User2Channel WHERE ChannelId=655 
etc 

請!幫我!我如何解決這個問題?如果我擁有數千個頻道 - 我也會收到很多數據庫查詢!

回答

2

您可以使用批量加載它們。這是一個不太乾擾的選項(意思是說:你不需要在你的域代碼中做任何事情)。

我不知道流利。因此,這是您需要的xml映射:

<set name="Channels" ... batch-size="50"> 
    ... 
</set> 

這可以讓NH一次預取50個通道。它會詢問他們是這樣的:

SELECT ... FROM User2Channel WHERE ChannelId IN (654, 655, 656, ... 704) 

這使得N+1一個N/50+1

+0

斯蒂芬是對的。另外,執行查詢時的多個查詢由您添加的'Not.LazyLoad'引起。 – 2010-09-12 17:31:11

+0

感謝評論迭戈。如果linq查詢具有Fetch語句並且映射中指定了Not.LazyLoad,則會導致調用2個查詢。刪除了映射中的Not.LazyLoad,並且都很棒。 – Chev 2011-04-16 10:16:42