-1

カテゴリを共有する製品のリストを取得しようとしています。

Hibernate は間違った製品を返しません。

ここに私の基準APIメソッドがあります:

public IList<Product> GetProductForCategory(string name)
        {

            return _session.CreateCriteria(typeof(Product))
                .CreateCriteria("Categories")
                .Add(Restrictions.Eq("Name", name))
                .List<Product>();

        }

これが私のHQLメソッドです:

public IList<Product> GetProductForCategory(string name)
        {
            return _session.CreateQuery("select from Product p, p.Categories.elements c where c.Name = :name").SetString("name",name).List<Product>();


        }

どちらのメソッドも、2 つの製品を返す必要がある場合に製品を返しません。

Product クラスのマッピングは次のとおりです。

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="CBL.CoderForTraders.DomainModel" namespace="CBL.CoderForTraders.DomainModel">
  <class name="Product" table="Products" >
    <id name="_persistenceId" column="ProductId" type="Guid" access="field" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="assigned" />
    </id>
    <version name="_persistenceVersion" column="RowVersion" access="field" type="int" unsaved-value="0" />

    <property name="Name" column="ProductName" type="String" not-null="true"/>
    <property name="Price" column="BasePrice" type="Decimal" not-null="true" />
    <property name="IsTaxable" column="IsTaxable" type="Boolean" not-null="true" />
    <property name="DefaultImage" column="DefaultImageFile" type="String"/>

    <bag name="Descriptors" table="ProductDescriptors">
      <key column="ProductId" foreign-key="FK_Product_Descriptors"/>
      <one-to-many class="Descriptor"/>
    </bag>
    <bag name="Categories"  table="Categories_Products" >
      <key column="ProductId" foreign-key="FK_Products_Categories"/>
      <many-to-many class="Category" column="CategoryId"></many-to-many>
    </bag>

    <bag name="Orders" generic="true" table="OrderProduct" >
      <key column="ProductId" foreign-key="FK_Products_Orders"/>
           <many-to-many column="OrderId" class="Order" />
    </bag>


  </class>
</hibernate-mapping>

最後に、Category クラスのマッピング:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="CBL.CoderForTraders.DomainModel" namespace="CBL.CoderForTraders.DomainModel" default-access="field.camelcase-underscore" default-lazy="true">

  <class name="Category" table="Categories" >
    <id name="_persistenceId" column="CategoryId" type="Guid" access="field" unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="assigned" />
    </id>
    <version name="_persistenceVersion" column="RowVersion" access="field" type="int" unsaved-value="0" />

    <property name="Name" column="Name" type="String" not-null="true"/>
    <property name="IsDefault" column="IsDefault" type="Boolean" not-null="true" />
    <property name="Description" column="Description" type="String" not-null="true" />

    <many-to-one name="Parent" column="ParentID"></many-to-one>

    <bag name="SubCategories" inverse="true">
      <key column="ParentID" foreign-key="FK_Category_ParentCategory" />
      <one-to-many class="Category"/>
    </bag>
    <bag name="Products" table="Categories_Products">
      <key column="CategoryId" foreign-key="FK_Categories_Products" />
      <many-to-many column="ProductId" class="Product"></many-to-many>
    </bag>
  </class>
</hibernate-mapping>

何が問題なのか分かりますか?

add 行を削除すると、クエリは次のようになります。

return _session.CreateCriteria(typeof(Product))
                .CreateCriteria("Categories")
                .List<Product>();

ウォッチ ウィンドウを見ると、カテゴリが関連付けられた 5 つの製品が返されます。最初のクエリで探しているカテゴリの名前が 2 つの製品に表示されます。

したがって、行を追加すると何か問題があります: .Add(Restrictions.Eq("Name", name))

制限行を含む生成された SQL を次に示します。

NHibernate: this_.ProductId を ProductId23_1_ として、this_.RowVersion を RowVersion23_1_ として、this_.ProductName を ProductN3_23_1_ として、this_.BasePrice を BasePrice23_1_ として、this_.IsTaxable を IsTaxable23_1_ として、this_.DefaultImageFile を DefaultI6_23_1_ として、categories3_.ProductId を ProductId として、category1_.CategoryId を CategoryId として選択します。 、category1_.CategoryId を CategoryId16_0_ として、category1_.RowVersion を RowVersion16_0_ として、category1_.Name を Name16_0_ として、category1_.IsDefault を IsDefault16_0_ として、category1_.Description を Descript5_16_0_ として、category1_.ParentID を ParentID16_0_ として。 ProductId 内部結合 Categoriescategory1_ on Categories3_.CategoryId=category1_.CategoryId WHERE category1_.Name = @p0; @p0 = 'モメンタム'

4

4 に答える 4

2

クエリとマッピングだけではわかりません。また、データの作成方法も興味深いでしょう。

HQL は実際には次のようになります。

select p
from Product p join p.Categories c 
where c.Name = :name

データベース内のデータが正しいと仮定すると、これは機能するはずです。

ちなみに、おそらく同じデータである可能性が高いため、同じテーブル内の製品とカテゴリ間の双方向の多対多の関係をマッピングできます (すべきです)。それを同じテーブル/列にマップし、man-to-many relationship の 1 つを作成するだけですinverse="true"

両方のコレクションが同期して更新されていることを確認する必要があります。製品をカテゴリに追加するだけの場合、製品にリンクがありません。モデルの一貫性を維持することは、NHibernate の責任ではありません。

次のようなエラーを見つけるには:

  • 生成された SQL を見てください (show_sql構成で true に設定されています。コンソールに表示されます)。SqlServer を使用する場合は、Profiler も使用できます。
  • SQL コンソールでクエリを実行します。
  • データベース内のデータを調べます。
于 2010-04-16T07:20:41.573 に答える
1

あなたの Criteria クエリは問題ないように見えます - 私が書いた何十ものように。

問題は、多対多のリンク テーブルにあります。

マッピングには次のProductものがあります。

<bag name="Categories"  table="Categories_Products" >
  <key column="ProductId" foreign-key="FK_Products_Categories"/>
  <many-to-many class="Category" column="CategoryId"></many-to-many>
</bag>

マッピングには、次のCategoryものがあります。

<bag name="Products" table="Categories_Products">
  <key column="CategoryId" foreign-key="FK_Categories_Products" />
  <many-to-many column="ProductId" class="Product"></many-to-many>
</bag>

の代わりににリンクProductIdして、外部キーを逆にしたように見えます。FK_Products_CategoriesFK_Categories_Products

この種の状況で役立つと思うのは、NHibernate の SQL ログをオンにして、生成された SQL を確認することです。通常、これにより、マッピング エラーに関するかなり大きな手がかりが得られます。詳細については、NHibernate で使用するために Log4Net を構成する を参照してください。

于 2010-04-16T07:10:44.797 に答える
0

本当にごめんなさい。私のマッピングとコードは問題ありません。問題は name パラメータでした。

于 2010-04-17T02:10:46.400 に答える
-1

次の単純なSQLと同等のものを生成するために、切り離された基準を使用してサブクエリを試してください

select * from Products where ProductId in (select distinct cp.ProductId from Categories_Products cp inner join Categories c on cp.CategoryId = c.CategoryId and c.Name = name)

このようなもの ...

DetachedCriteria subCriteria = DetachedCriteria.For(typeof(Category))
    .SetResultTransformer(new DistinctRootEntityResultTransformer())
    .SetProjection(Projections.Property("Category.Products.ProductId"))
    .Add(Restrictions.PropertyEq("Name", name));

return _session.CreateCriteria.For(typeof(Product))
    .Add(Subqueries.PropertyIn("ProductId", subCriteria))
    .List<Product>();

Ack、Category.Products.ProductId は正しくない可能性がありますが、ここで何をしようとしているのかを見て、サブクエリで使用する正しいプロジェクションを理解できるかもしれません。

于 2010-04-16T05:47:02.043 に答える