NHibernate链接表与数据

时间:2011-10-27 16:39:42

标签: sql nhibernate many-to-many metadata

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查询更好,并解决了我的问题。

1 个答案:

答案 0 :(得分:0)

我认为您可以通过FuturesQueryOver实现您的目标。看看以下文章:

Fighting cartesian product (x-join) when using NHibernate 3.0.0

如果你无法从上面想象出如何完成你需要的东西,我可以根据你的需要量身定制这个例子。