我正在学习nHibernate,我正在尝试一对多的映射。以下是产品和产品类型的两个表格。
namespace NHibernateSample.Models
{
public class Product
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual string Category { get; set; }
public virtual bool Discontinued { get; set; }
public virtual IList<ProductType> ProductTypes { get; set; }
}
}
以下是我的映射XML
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSample"
namespace="NHibernateSample.Models">
<!-- more mapping info here -->
<class name="Product">
<id name="Id">
<generator class="guid" />
</id>
<property name="Name" />
<property name="Category" />
<property name="Discontinued" />
<bag name="ProductTypes">
<key column="ProductID" />
<one-to-many class="NHibernateSample.Models.ProductType,NHibernateSample" />
</bag>
</class>
</hibernate-mapping>
产品类型xml:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHibernateSample"
namespace="NHibernateSample.Models">
<!-- more mapping info here -->
<class name="ProductType">
<id name="ProductTypeID">
<generator class="increment"/>
</id>
<property name="ProductType1" column="ProductType"/>
<property name="ProductID" />
<many-to-one name="Product" class="Product">
<column name="ProductID" sql-type="int" not-null="true"/>
</many-to-one>
</class>
</hibernate-mapping>
映射在配置
中mapping assembly="NHibernateSample" />
当我尝试配置和构建会话工厂时
var cfg = new Configuration();
cfg.Configure();
m_SessionFactory = cfg.BuildSessionFactory();
我得到的错误是&#34;关联引用未映射的类:NHibernateSample.Models.ProductType&#34;但是我在bin文件夹中看到了hbm文件。
如果我明确添加程序集,
Assembly thisAssembly = typeof(Product).Assembly;
cfg.AddAssembly(thisAssembly);
我得到另一个错误说&#34;复制集合角色映射NHibernateSample.Models.Product.ProductTypes&#34;
我做错了什么?这不是我应该映射外键的方式吗? 提前致谢
答案 0 :(得分:1)
第一个问题似乎与.hbm.xml文件的错误设置有关..它总是必须有(参见例如MappingException: No persister for - NHibernate - Persisting an Adapter)
<mapping assembly="MyProject.Data" />
(参见配置)第二个问题(评论中)
我在这里插入一个产品。我想插入一些ProductType 数据库如
prod.ProductTypes = new
....我该怎么做Product prod = new Product(); prod.Name = "Q3"; prod.Category = "Audi"; prod.Discontinued = false; session.Save(prod); ...
解决方案是调整集合的映射以使用级联:
<class name="Product">
<id name="Id">
<generator class="guid" />
</id>
<property name="Name" />
<property name="Category" />
<property name="Discontinued" />
<bag name="ProductTypes"
lazy="true" inverse="true" batch-size="25" cascade="all-delete-orphan"
>
<key column="ProductID" />
<one-to-many class="NHibernateSample.Models.ProductType,NHibernateSample" />
</bag>
</class>
(<bag>
上的所有这些设置 - 检查here)
我会调整这个POCO定义
public class Product
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual string Category { get; set; }
public virtual bool Discontinued { get; set; }
//public virtual IList<ProductType> ProductTypes { get; set; }
IList<ProductType> _productTypes;
public virtual IList<ProductType> ProductTypes
{
get { return _productTypes ?? (_productTypes = new List<ProductType>()); }
set { _productTypes = value; }
}
}
(这只是为了确保列表是由NHibernate在加载时启动的,还是由我们在其他情况下启动的)
然后我们只需分配双方
// product
Product prod = new Product();
prod.Name = "Q3"; prod.Category = "Audi";
prod.Discontinued = false;
// product type
ProductType productType = new ProudctType();
...
// both sides assigned
prod.ProductTypes.Add(productType);
productType.Product = prod;
session.Save(prod);
我们还应该将映射调整为值类型属性
的只读<property name="ProductID" insert="false" update="false" />
<many-to-one name="Product" class="Product">
<column name="ProductID" sql-type="int" not-null="true"/>
</many-to-one>
要获得更多细节,我不会错过这个: