0

我们正在使用 NHibernate、C# .NET 开发应用程序,并且我们遇到了一个关于映射的问题……情况如下:

首先,我将放置我们的映射文件:

这是 User.hbm.xml 映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="GLib.GSecurity.Domain" namespace="Geraes.GLib.GSecurity.Domain" >

<typedef class="uNhAddIns.UserTypes.EncryptedString, uNhAddIns" name="Encrypted">
  <param name="encryptor">uNhAddIns.UserTypes.uNHAddinsEncryptor, uNhAddIns</param>
  <param name="encryptionKey">myRGBKey</param>
</typedef>

<class name="User" table="S_User" lazy="false" dynamic-update="true">

<id name="Id" column="Id_User" type="Int64">
  <generator class="Geraes.GLib.GDomainBasis.CustomTableHiLoGenerator, GLib.GDomainBasis" />
</id>

<many-to-one name="Plant" column="Id_Plant" class="Plant"
             foreign-key="fk1_User" cascade="none" fetch="join" not-null="true"/>

<property name="Login" column="Login" type="String" length="16" not-null="true" />

<property name="Password" column="Password" type="Encrypted" />

<property name="Name" column="Name" type="String" length="64" not-null="true" />

<property name="Active" column="Active" type="Char" not-null="true" />

 <idbag name="RightProfiles" table="S_User_Right_Profile" generic="true" lazy="false" cascade="save-update" fetch="join">
   <collection-id type="Int64" column="Id_User_Right_Profile">
     <generator class="Geraes.GLib.GDomainBasis.CustomTableHiLoGenerator, GLib.GDomainBasis" />
   </collection-id>
   <key column="Id_User" />
   <many-to-many column="Id_Right_Profile" class="RightProfile" fetch="join"/>
 </idbag>

  </class>

</hibernate-mapping>  

这是 RightProfile.hbm.xml 映射:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="GLib.GSecurity.Domain" namespace="Geraes.GLib.GSecurity.Domain" >

  <class name="RightProfile" table="S_Right_Profile" lazy="false" dynamic-update="true">

    <id name="Id" column="Id_Right_Profile" type="Int64">
      <generator class="Geraes.GLib.GDomainBasis.CustomTableHiLoGenerator, GLib.GDomainBasis" />
    </id>

    <property name="Name" column="Name" type="String" length="20" not-null="true" />

    <property name="Description" column="Description" type="String" length="60" not-null="true" />

    <idbag name="Resources" table="S_Right_Profile_Resource" generic="true" lazy="false" cascade="save-update" fetch="join">
      <collection-id type="Int64" column="Id_Right_Profile_Resource">
        <generator class="Geraes.GLib.GDomainBasis.CustomTableHiLoGenerator, GLib.GDomainBasis" />
      </collection-id>
      <key column="Id_Right_Profile" />
      <many-to-many column="Id_Resource" class="Resource" fetch="join"/>
    </idbag>

    <idbag name="Users" table="S_User_Right_Profile" generic="true" inverse="true" lazy="false" cascade="save-update" fetch="join">
      <collection-id type="Int64" column="Id_User_Right_Profile">
        <generator class="Geraes.GLib.GDomainBasis.CustomTableHiLoGenerator, GLib.GDomainBasis" />
      </collection-id>
      <key column="Id_Right_Profile" />
      <many-to-many column="Id_User" class="User" fetch="join"/>
    </idbag>

  </class>

</hibernate-mapping>  

现在,我们的实体类:

User.cs 实体类:

public class User : BaseEntityEditable
{
    public virtual Plant Plant { get; set; }

    public virtual String Login { get; set; }

    public virtual String Password { get; set; }

    public virtual String Name { get; set; }

    public virtual Char Active { get; set; }

    public virtual IList<RightProfile> RightProfiles { get; set; }

    public override String ToString()
    {
        return Name + " - " + Login;
    }

    public User()
    {
        RightProfiles = new List<RightProfile>();
        Plant = new Plant();
    }
}

RightProfile.cs 实体类:

public class RightProfile : BaseEntityEditable
{
    public virtual String Name { get; set; }

    public virtual String Description { get; set; }

    public virtual IList<Resource> Resources { get; set; }

    public virtual IList<User> Users { get; set; }

    public override String ToString()
    {
        return Name + " - " + Description;
    }

    public RightProfile()
    {
        Resources = new List<Resource>();
        Users = new List<User>();
    }
}

所以,我们的情况是:

我们正在开发一个窗口。在这个窗口中,我们有 2 个网格。用户网格和组网格。当这个窗口被加载时,我们的 viewModel start 会进行必要的查询来带来数据。第一个查询带来所有用户,在用户内部,我们有一个 RightProfile 列表,其中包含填充其他网格所需的所有数据。到目前为止,一切都很好。我们的问题是,nhibernate 开始进行查询,带来所有 RightProfiles 的所有用户。

他不能那样做!我们已经拥有了所有需要的数据!

-- 已编辑 --

我们的第一部分运行正常,我们搜索用户,搜索 RightProfiles(填充网格),然后,我们在该网格内标记允许的用户。事实上,我的窗户工作得很好。我们的问题是,在 Nhibernate Log 中,他正在为每个关联的具有关联的 Right Profile 的用户进行选择。

一旦数据已经加载,这些选择是不必要的。这是我的问题,nhibernate 正在做更多需要做的选择。

我怎么能改变这个?

-- 编辑 2: -- 这是 NHibernate Log 生成的 SQL:

这个选择没问题:

   SELECT
    this_.Id_Right_Profile as Id1_36_3_,
    this_.Name as Name36_3_,
    this_.Description as Descript3_36_3_,
    resources2_.Id_Right_Profile as Id1_5_,
    resource3_.Id_Resource as Id2_5_,
    resources2_.Id_Right_Profile_Resource as Id3_5_,
    resource3_.Id_Resource as Id1_39_0_,
    resource3_.Name as Name39_0_,
    users4_.Id_Right_Profile as Id1_6_,
    user5_.Id_User as Id2_6_,
    users4_.Id_User_Right_Profile as Id3_6_,
    user5_.Id_User as Id1_42_1_,
    user5_.Id_Plant as Id2_42_1_,
    user5_.Login as Login42_1_,
    user5_.Password as Password42_1_,
    user5_.Name as Name42_1_,
    user5_.Active as Active42_1_,
    plant6_.Id_Plant as Id1_41_2_,
    plant6_.Name as Name41_2_,
    plant6_.Description as Descript3_41_2_ 
FROM
    S_Right_Profile this_ 
left outer join
    S_Right_Profile_Resource resources2_ 
        on this_.Id_Right_Profile=resources2_.Id_Right_Profile 
left outer join
    S_Resource resource3_ 
        on resources2_.Id_Resource=resource3_.Id_Resource 
left outer join
    S_User_Right_Profile users4_ 
        on this_.Id_Right_Profile=users4_.Id_Right_Profile 
left outer join
    S_User user5_ 
        on users4_.Id_User=user5_.Id_User 
left outer join
    S_Plant plant6_ 
        on user5_.Id_Plant=plant6_.Id_Plant 
ORDER BY
    this_.Name asc 

在我看来,这个选择是不必要的(它对每个用户重复):

SELECT
    rightprofi0_.Id_User as Id2_1_,
    rightprofi0_.Id_Right_Profile as Id1_1_,
    rightprofi0_.Id_User_Right_Profile as Id3_1_,
    rightprofi1_.Id_Right_Profile as Id1_36_0_,
    rightprofi1_.Name as Name36_0_,
    rightprofi1_.Description as Descript3_36_0_ 
FROM
    S_User_Right_Profile rightprofi0_ 
left outer join
    S_Right_Profile rightprofi1_ 
        on rightprofi0_.Id_Right_Profile=rightprofi1_.Id_Right_Profile 
WHERE
    rightprofi0_.Id_User=:p0;
:p0 = 10807 [Type: Int64 (0)] 
4

2 回答 2

1

您是否尝试过在您的 idBag 上设置批量大小?

 <idbag batch-size='50' .. >

您可能希望使用实际值来获得最佳性能。

顺便说一句,在您的示例中将 a 设置batch-size为 50 会将您的查询减少到 3。

编辑后编辑 RightProfile xml 中的 idBag 已fetch="join"定义。“获取”连接允许使用单个选择来初始化值的关联或集合以及它们的父对象。

如果将 fetch 策略更改为 select 会发生什么?

<idbag name="Users" table="S_User_Right_Profile" lazy="true" fetch="select".. .
于 2012-04-11T15:19:07.593 回答
0

解决了!

只需将惰性选项设置为 true,现在 NHibernate 不会执行那些额外的选择

=D

感谢大家!

于 2012-04-12T13:48:17.737 回答