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つのグリッドがあります。ユーザー用のグリッド、およびグループ用のグリッド。このウィンドウが読み込まれると、viewModelstartはデータを取得するために必要なクエリを実行します。最初のクエリはすべてのユーザーを取得し、ユーザー内には、他のグリッドにデータを入力するために必要なすべてのデータを含むRightProfilesのリストがあります。ここまでは順調ですね。私たちの問題は、nhibernateがクエリを作成し始め、すべてのRightProfilesのすべてのユーザーを連れてくることです。

彼はそれをすることはできません!必要なデータはすべて揃っています。

-編集済み-

最初の部分は正常に実行されています。ユーザーを検索し、RightProfilesを検索して(グリッドにデータを入力するため)、次に、そのグリッド内でユーザーに許可されているものをマークします。実際、私のウィンドウは問題なく機能します。私たちの問題は、Nhibernate Log内で、関連付けられたRightProfileを持つ関連付けられたユーザーごとに選択を行っていることです。

データがすでにロードされている場合、これらの選択は不要です。これが私の問題です。nhibernateは実行する必要のある選択をはるかに多く行っています。

どうすればこれを変更できますか?

-編集2: -NHibernateログによって生成されたSQLは次のとおりです。

この選択はOKです:

   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' .. >

最高のパフォーマンスを得るには、実際の値を試してみることをお勧めします。

ところで、あなたの例ではabatch-sizeを50に設定すると、クエリが3に減ります。

編集後に編集 するRightProfilexmlのidBagがfetch="join"定義されています。「フェッチ」結合を使用すると、単一の選択を使用して、値の関連付けまたはコレクションを親オブジェクトとともに初期化できます。

フェッチ戦略を変更して選択するとどうなりますか?

<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 に答える