NHibernate的问题

时间:2010-04-16 04:53:06

标签: nhibernate nhibernate-mapping hql criteria-api

我正在尝试获取共享该类别的产品列表。

NHibernate不会返回错误的产品。

以下是我的Criteria 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类的Mapping:

<?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>

你能看出可能出现什么问题吗?

如果我删除添加行,我的查询是:

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

现在看着我的观察窗口我返回了5个附有类别的产品。 我在初始查询中查找的类别的名称显示在2个产品上。

添加该行时出现问题: .Add(Restrictions.Eq(“名称”,姓名))

这是生成的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_ FROM Products this_ inner join Categories__Products categories__ on this_.ProductId = categories3_.ProductId内部联接类别category__ on categories3_.CategoryId = category1_.CategoryId WHERE category1_.Name = @ p0; @ p0 ='Momemtum'

4 个答案:

答案 0 :(得分:2)

很难从查询和映射中说出来。同样有趣的是如何创建数据。

HQL实际上应该是这样的:

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

应该有效,假设您的数据库中的数据是正确的。

顺便说一句,您可以(应该)映射同一个表中产品和类别之间的双向多对多关系,因为它很可能是相同的数据。只需将其映射到相同的表/列,然后创建一对多关系inverse="true"

您需要确保两个集合同步更新。如果仅将产品添加到类别,则产品中缺少该链接。保持模型的一致性不是NHibernate的责任。

要查找如下错误:

  • 在配置中查看生成的SQL(将show_sql设置为true。您将在控制台中看到它。)使用SqlServer时,您也可以使用Profiler。
  • 在SQL控制台中执行查询。
  • 查看数据库中的数据。

答案 1 :(得分: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>

我觉得你好像已经改掉了你的外键,将ProductIdFK_Products_Categories联系起来而不是FK_Categories_Products

我认为在这种情况下有用的东西是打开NHibernate的SQL日志记录,然后查看生成的SQL。通常这给我一个很大的线索,我的映射错误。有关更多信息,请参阅Configure Log4Net for use with NHibernate

答案 2 :(得分:0)

真的很抱歉。我的映射和代码很好。问题是名称参数。

答案 3 :(得分:-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可能不正确,但也许你可以看到我在这里想做的事情,并找出在子查询中使用的正确投影。