SQL 2008 | .NET 4.0 | NHibernate 3.1 | NHibernate.Castle 3.1 | Castle.Core 2.5.2
所以我有一个包含元数据的链接表,就像这个问题的作者NHibernate Mapping a Many to Many with Data on Join Table
一样最初,我的映射就像这个问题的答案一样,因为它似乎是处理它的最简约的方法。但是,在打开show_sql
并观察发生了什么之后,ID查找最终产生了N + 1个查询,其中N是关联数。
观察此示例数据库,该数据库类似于我的实际数据,以类似sql的语法
定义CREATE TABLE [User]
(
Id int PRIMARY KEY
)
CREATE TABLE UserPref
(
Id int PRIMARY KEY,
Name varchar(32)
)
CREATE TABLE UserPrefAssociation
(
UserId int,
PrefId int,
Value varchar(32)
)
我将以下代码与此用户一对多对象映射IList<UserPrefAssociation> Preferences { get; set; }
public IDictionary<string, string> GeneratePrefDict()
{
return Preferences
.ToDictionary(i => i.UserPref.Name, i => i.Value);
}
当然,这很有效,但如前所述,每个i.UserPref.Name
都是SQL的附加查询。
在SQL中玩之后,我找到了完成我想要的查询。那么我的问题就是如何用NHibernate做到这一点?
SELECT UserPref.Name, UserPrefAssociation.Value
FROM [User]
INNER JOIN UserPrefAssociation ON [User].Id = UserPrefAssociation.UserId
INNER JOIN UserPref ON UserPrefAssociation.UserPrefId = UserPref.Id
WHERE [User].Id = 1
~~~~解决~~~~~
using NHibernate.Linq;
...
public IDictionary<string, string> GeneratePrefDict(ISession s)
{
return
(from entry in s.Query<User_UserPref>()
where entry.User == this
select new
{
key = entry.UserPref.Name,
value = entry.Value
})
.ToDictionary(i => i.key, i => i.value);
}
生成此SQL
NHibernate: select userpref1_.Name as col_0_0_, user_userp0_.Value as col_1_0_ f
rom User_UserPref user_userp0_ left outer join UserPref userpref1_ on user_userp
0_.UserPrefId=userpref1_.Id where user_userp0_.UserId=@p0;@p0 = 1 [Type: Int32 (
0)]
哪个比N + 1查询更好,并解决了我的问题。
答案 0 :(得分:0)
我认为您可以通过Futures
和QueryOver
实现您的目标。看看以下文章:
Fighting cartesian product (x-join) when using NHibernate 3.0.0
如果你无法从上面想象出如何完成你需要的东西,我可以根据你的需要量身定制这个例子。