我不是NHibernate专家,所以这可能是该部门缺乏理解。我有两个简单的实体,具有多对多的关系
public class Category
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual bool Visible { get; set; }
public virtual IList<Product> Products { get; set; }
}
和
public class Product
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
public virtual bool Visible { get; set; }
public virtual IList<Category> Categories { get; set; }
}
我的配置是
public static void BuildFactory()
{
_factory = Fluently.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString(_connectionString)
.ShowSql()
)
.Mappings(m =>
m.AutoMappings.Add(
AutoMap.AssemblyOf<Database>()
.Where(t => t.Namespace == "FancyStore.Models.Catalog")
.Override<Product>(k =>
k.HasManyToMany(x => x.Categories)
.Table("ProductsToCategories")
.ParentKeyColumn("Product_id")
.ChildKeyColumn("Category_id")
.Cascade.AllDeleteOrphan())
.Override<Category>(k =>
k.HasManyToMany(x => x.Products)
.Table("ProductsToCategories")
.ParentKeyColumn("Category_id")
.ChildKeyColumn("Product_id")
.Cascade.AllDeleteOrphan().Inverse())
)
)
.ExposeConfiguration(SetConfiguration)
.BuildConfiguration()
.BuildSessionFactory();
}
所以我开始没有覆盖(稍后在一些谷歌搜索后添加它们),并使用ExportSchema生成我的模式。 ExportSchema知道多对多关系(即使没有覆盖),因为它生成了一个连接表(ProductsToCategories
)。
我想添加一些简单的测试数据,所以我就这样做了
using (var db = new Repository<Category>())
{
for (int i = 0; i < 6; i++)
{
var cat = new Category
{
Name = "Things" + i,
Description = "Things that are things",
Visible = true,
Products = new List<Product>()
};
for (int k = 0; k < 6; k++)
{
var prod = new Product
{
Name = "Product" + k,
Description = "Product for " + cat.Name,
Visible = true,
Categories = new List<Category>(new[] { cat })
};
cat.Products.Add(prod);
}
db.Save(cat);
}
}
这样可以正确保存产品和类别,但不会保存连接表中的任何关系。查看sql对category.Products的调用生成,它实际上是在查找产品的连接表(并且无法找到任何,因为它是空的)
非常感谢任何帮助: - )
编辑:删除了仍然发生的反向问题:(
EDIT2 :
以下是目录和产品的映射文件(注意:名称有点傻,但这只是一种快速的原型 - 这种交易)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="FancyStore.Models.Catalog.Product, FancyStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Product`">
<id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Id" />
<generator class="identity" />
</id>
<property name="Name" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Name" />
</property>
<property name="Description" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Description" />
</property>
<property name="Price" type="System.Decimal, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Price" />
</property>
<property name="Visible" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Visible" />
</property>
<bag cascade="all-delete-orphan" inverse="true" name="Categories" table="ProductsToCategories">
<key>
<column name="Product_id" />
</key>
<many-to-many class="FancyStore.Models.Catalog.Category, FancyStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<column name="Category_id" />
</many-to-many>
</bag>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true">
<class xmlns="urn:nhibernate-mapping-2.2" name="FancyStore.Models.Catalog.Category, FancyStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Category`">
<id name="Id" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Id" />
<generator class="identity" />
</id>
<property name="Name" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Name" />
</property>
<property name="Description" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Description" />
</property>
<property name="Visible" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Visible" />
</property>
<bag cascade="all-delete-orphan" name="Products" table="ProductsToCategories">
<key>
<column name="Category_id" />
</key>
<many-to-many class="FancyStore.Models.Catalog.Product, FancyStore, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<column name="Product_id" />
</many-to-many>
</bag>
</class>
</hibernate-mapping>
答案 0 :(得分:2)
我可能会弄错,但看起来你把双方的关系标记为“反向”。
您应该只为关系的一方执行此操作,并确保在另一方打电话给Save
。
另外,我认为在您保存之前双方的关系必须有效(除了您已经在做的事情之外,还要cat
添加prod.Categories
)。
我对这些关系的理解无疑是模糊的,但这是我几个月来的研究提出来的(并解决了我自己的一些问题)。
答案 1 :(得分:2)
答案 2 :(得分:0)
你对该关联的错误方面有反过来。反向意味着“另一方管理这种关联”。
您需要的是删除类别上的反转并将其放在产品上,或将产品更改为“拥有”实体,如下所示:
//make sure to add it to BOTH sides of the association
product.Categories.Add(cat);
cat.Products.Add(product);
db.Save(cat); //if Product has Inverse
/* or */
db.Save(prod); //if Category has Inverse
答案 3 :(得分:0)
如果要在自动化之前首先应用Product和Category的流畅映射,那该怎么办?例如,
public class Product
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
public virtual bool Visible { get; set; }
public virtual IList<Category> Categories { get; set; }
public Product()
{
Categories = new List<Category>();
}
}
public class ProductMap : ClassMap<Product>
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Description);
Map(x => x.Price);
Map(x => x.Visible);
HasManyToMany(x => x.Categories)
.Table("ProductsToCategories")
.ParentKeyColumn("Product_id")
.ChildKeyColumn("Category_id")
.Cascade.AllDeleteOrphan();
}
public class Category
{
public virtual int Id { get; private set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual bool Visible { get; set; }
public virtual IList<Product> Products { get; set; }
public Category()
{
Products = new List<Product>();
}
}
public class CategoryMap : ClassMap<Category>
{
Id(x => x.Id);
Map(x => x.Name);
Map(x => x.Description);
Map(x => x.Visible);
HasManyToMany(x => x.Products)
.Table("ProductsToCategories")
.ParentKeyColumn("Category_id")
.ChildKeyColumn("Product_id")
.Cascade.AllDeleteOrphan().Inverse();
}
配置,
public static void BuildFactory()
{
_factory = Fluently.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString(_connectionString)
.ShowSql()
)
.Mappings(m => {
m.FluentMappings.AddFromAssemblyOf<Database>();
m.AutoMappings.Add(
AutoMap.AssemblyOf<Database>()
.Where(t => t.Namespace == "FancyStore.Models.Catalog"));
})
.ExposeConfiguration(SetConfiguration)
.BuildConfiguration()
.BuildSessionFactory();
}