我正在尝试获取共享该类别的产品列表。
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'
答案 0 :(得分:2)
很难从查询和映射中说出来。同样有趣的是如何创建数据。
HQL实际上应该是这样的:
select p
from Product p join p.Categories c
where c.Name = :name
应该有效,假设您的数据库中的数据是正确的。
顺便说一句,您可以(应该)映射同一个表中产品和类别之间的双向多对多关系,因为它很可能是相同的数据。只需将其映射到相同的表/列,然后创建一对多关系inverse="true"
。
您需要确保两个集合同步更新。如果仅将产品添加到类别,则产品中缺少该链接。保持模型的一致性不是NHibernate的责任。
要查找如下错误:
show_sql
设置为true。您将在控制台中看到它。)使用SqlServer时,您也可以使用Profiler。答案 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>
我觉得你好像已经改掉了你的外键,将ProductId
与FK_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可能不正确,但也许你可以看到我在这里想做的事情,并找出在子查询中使用的正确投影。