-1

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

NHibernate 不返回错误的产品。

这是我的标准 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>

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

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

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

现在看着我的监视窗口,我返回了 5 个附加了类别的产品。我在初始查询中查找的类别名称出现在 2 个产品上。

所以当我添加行时出现问题: .Add(Restrictions.Eq("Name", name))

这是生成的 Sql,包括 Restriction 行:

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 作为, category1_.CategoryId as CategoryId16_0_, category1_.RowVersion as RowVersion16_0_, category1_.Name as Name16_0_, category1_.IsDefault as IsDefault16_0_, category1_.Description as Descript5_16_0_, category1_.ParentID as ParentID16_0_ FROM Products this_inner join Categories_Products categories3_ on this_.ProductId=categories3_。 ProductId 内连接 Categories category1_ 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 关系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>

在我看来,好像您已经反转了外键,链接ProductIdFK_Products_Categories而不是FK_Categories_Products.

我发现在这种情况下有用的是打开 NHibernate 的 SQL 日志记录,然后查看生成的 SQL。通常这会给我一个关于我的映射错误的很大线索。有关更多信息,请参阅配置 Log4Net 以与 NHibernate 一起使用

于 2010-04-16T07:10:44.797 回答
0

真的对不起各位。我的映射和代码很好。问题是名称参数。

于 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>();

确认,Category.Products.ProductId 可能不正确,但也许您可以看到我在这里尝试做的事情并找出要在子查询中使用的正确投影。

于 2010-04-16T05:47:02.043 回答