NHibernate 的问题
我正在尝试获取共享该类别的产品列表。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
仅从查询和映射很难说。同样有趣的是您如何创建数据。
HQL 实际上应该如下所示:
假设数据库中的数据正确,它应该可以工作。
顺便说一句,您可以(应该)在同一个表中映射产品和类别之间的双向多对多关系,因为它很可能是相同的数据。只需将其映射到相同的表/列并建立人对多关系之一
inverse="true"
。您需要确保两个集合同步更新。如果您仅将产品添加到类别中,则产品中会缺少链接。维护模型的一致性不是 NHibernate 的责任。
要查找这样的错误:
show_sql
设置为 true。您将在控制台中看到它。)当您使用 SqlServer 时,您还可以使用探查器。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:
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:
show_sql
to true in the configuration. You'll see it in the console.) When you use SqlServer, you can also use the Profiler.您的 Criteria 查询看起来不错 - 就像我写的几十个一样。
问题出在您的多对多链接表上。
在
Product
映射中,您有这样的:在
Category
映射中,您有这样的:在我看来,好像您已经颠倒了外键,链接了
ProductId
到FK_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:In the
Category
mapping, you have this:It looks to me as though you've reversed your foreign keys, linking
ProductId
toFK_Products_Categories
instead ofFK_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.
真的很抱歉各位。我的映射和代码都很好。问题出在名称参数上。
Really sorry guys. My Mapping and code is fine. The problem was the name parameter.
尝试使用分离条件的子查询来生成与以下普通sql等效的内容,
如下所示...
确认,Category.Products.ProductId可能不正确,但也许您可以看到我在这里尝试执行的操作并弄清楚在子查询中使用的正确投影。
try a subquery using detached criteria to produce the equivalent to the following plain sql
something like this ...
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.