NHibernate 的问题

发布于 2024-08-29 02:28:40 字数 4960 浏览 5 评论 0原文

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

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 类的映射:

<?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,包括限制行:

NHibernate: SELECT this_.ProductId as ProductId23_1_, this_.RowVersion as RowVersion23_1_, this_.ProductName as ProductN3_23_1_, this_.BasePrice as 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 为 IsDef ault16_0_,类别1_ .Description 为 Descript5_16_0_,category1_.ParentID 为 ParentID16_0_ FROM Products this_ 内部联接categories_Productscategories3_ on this_.ProductId=categories3_.ProductId inner join 类别category1_ oncategories3_.CategoryId=category1_.CategoryId WHERE Category1_.Name = @p0; @p0 = '动力'

I am trying to get a list of Products that share the Category.

NHibernate returns no product which is wrong.

Here is my Criteria API method :

public IList<Product> GetProductForCategory(string name)
        {

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

        }

Here is my HQL method :

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


        }

Both methods return no product when they should return 2 products.

Here is the Mapping for the Product class :

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

And finally the mapping for the Category class :

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

Can you see what could be the problem ?

if I remove the add line my query is :

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

looking at my watch window now I return 5 products which have Categories attached to them.
The name of the category I am looking for in my initial query appears on 2 products.

So there is something wrong when I add the line :
.Add(Restrictions.Eq("Name", name))

Here is the Sql generated including the Restriction line :

NHibernate: SELECT this_.ProductId as ProductId23_1_, this_.RowVersion as RowVersion23_1_, this_.ProductName as ProductN3_23_1_, this_.BasePrice as BasePrice23_1_, this_.IsTaxable as IsTaxable23_1_, this_.DefaultImageFile as DefaultI6_23_1_, categories3_.ProductId as ProductId, category1_.CategoryId as 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 inner join Categories category1_ on categories3_.CategoryId=category1_.CategoryId WHERE category1_.Name = @p0; @p0 = 'Momemtum'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

旧城空念 2024-09-05 02:28:40

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

HQL 实际上应该如下所示:

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

假设数据库中的数据正确,它应该可以工作。

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

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

要查找这样的错误:

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

It's hard to say just from the query and the mappings. Also interesting would be how you create the data.

The HQL should actually look like this:

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

which should work, assumed that your data in the database is correct.

By the way, you could (should) map the bidirectional many-to-many relation between products and categories in the same table, because it it most probably the same data. Just map it to the same table/columns and make one of the man-to-many relations inverse="true".

You need to make sure that both collections are updated in synch. If you only add the product to the categories, the link is missing in the product. Maintaining the consistency of the model is not responsibility of NHibernate.

To find an error like this:

  • Take a look at the generated SQL (set show_sql to true in the configuration. You'll see it in the console.) When you use SqlServer, you can also use the Profiler.
  • Execute the query in an SQL console.
  • Take a look into the data in the database.
稚气少女 2024-09-05 02:28:40

您的 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 一起使用。

Your Criteria query looks fine - just like dozens I've written.

The problem is with your many-to-many link table.

In the Product mapping you have this:

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

In the Category mapping, you have this:

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

It looks to me as though you've reversed your foreign keys, linking ProductId to FK_Products_Categories instead of FK_Categories_Products.

Something I find useful in this kind of situation is to turn on SQL logging for NHibernate, then look at the generated SQL. Usually this gives me a pretty big clue as to my mapping error. For more, see Configure Log4Net for use with NHibernate.

请恋爱 2024-09-05 02:28:40

真的很抱歉各位。我的映射和代码都很好。问题出在名称参数上。

Really sorry guys. My Mapping and code is fine. The problem was the name parameter.

瀟灑尐姊 2024-09-05 02:28:40

尝试使用分离条件的子查询来生成与以下普通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可能不正确,但也许您可以看到我在这里尝试执行的操作并弄清楚在子查询中使用的正确投影。

try a subquery using detached criteria to produce the equivalent to the following plain 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)

something like this ...

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, the Category.Products.ProductId might not be correct, but maybe you can see what I'm trying to do here and figure out the correct projection to use in the subquery.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文