NHibernate:多对多关系不起作用
我有以下数据库架构: 这是我的映射文件:NHibernate:多对多关系不起作用,nhibernate,Nhibernate,我有以下数据库架构: 这是我的映射文件: <?xml version="1.0" encoding="utf-8" ?> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="CodeSmithSampel.Generated.BusinessObjects" assembly="CodeSmithSampel"> <class name="CodeSmithSampel.Gene
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="CodeSmithSampel.Generated.BusinessObjects" assembly="CodeSmithSampel">
<class name="CodeSmithSampel.Generated.BusinessObjects.Store, CodeSmithSampel" table="store" lazy="true">
<id name="Id" column="Id">
<generator class="native" />
</id>
<property name="Name" column="Name" />
<bag name="Employees" lazy="true" cascade="all-delete-orphan" inverse="true" >
<key column="Store_id"></key>
<one-to-many class="Employee"></one-to-many>
</bag>
<bag name="Products" table="storeproduct" lazy="true" cascade="all" inverse="true" >
<key column="Store_id"></key>
<many-to-many column="Product_id" class="Product" />
</bag>
</class>
</hibernate-mapping>
有什么我错过的吗
注意:我使用CodeSmith生成上述代码。
编辑:接受的答案有效。我陷入这个问题的原因是
inverse=true
,而不是两个。因此,无论是产品还是商店,都应该将反方向设置为false。代码生成工具没有正确处理此问题这是否与storeproducts表中有代理项有关 如果删除此代理键列Id,并将主键放在product_Id和store_Id列的组合上,会发生什么情况 我相信,如果您想在storeproducts表上有一个代理键,您必须创建另一个实体 如果要使用代理键,则必须使用idbag映射 您的产品类和映射看起来如何? 我看到您在Store实体的Products集合映射中指定了“inverse”属性 如果您这样做(因此您有一个双向关联),那么您也应该将商店添加到产品的商店集合中。 自-来自NH文档-: 仅对反向端点所做的更改 不会持久化关联的属性。 这意味着NHibernate有两个 在内存中表示每个 双向关联,一个链接 从A到B和从B到B的另一个链接 答:如果您 考虑一下.NET对象模型和 我们如何创建多对多模型 C#中的关系: 非反转侧用于保存 的内存中表示形式 数据库我们会得到一份不必要的工作 插入/更新,甚至可能是 外键冲突,如果两者都会 触发改变!当然,情况也是如此 双向的也适用 一对多协会 您可以映射一个双向 通过映射 一对多关联到同一个 表列作为多对一 并宣布 多值end inverse=“true” 这意味着,只有一端应该是相反的。 向商店添加产品时,应按以下方式进行:
public class Store
{
public void AddProduct( Product p )
{
if( _products.Contains (p) == false )
{
_products.Add (p);
p.AddStore(this);
}
}
}
public class Product
{
public void AddStore( Store s )
{
if( _stores.Contains (s) == false )
{
_stores.Add (s);
s.AddProduct(this);
}
}
}
(检查集合是否已包含要添加的项非常重要;否则,您将进入无限循环。我尝试按照您的建议更改数据库。但是没有,它仍然不起作用。更新了我的帖子;您能显示(相关)吗)产品类的代码和映射?我已经更新了问题,以包括产品类及其映射两端都设置为反向?您应该只有一个反向端,并在两端建立关联(请参阅我的更新)。这是明确的答案。TY。
public partial class Product : BusinessBase<int>
{
#region Declarations
private float _price = default(Single);
private string _name = null;
private IList<Store> _stores = new List<Store>();
#endregion
#region Constructors
public Product() { }
#endregion
#region Methods
public override int GetHashCode()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(this.GetType().FullName);
sb.Append(_price);
sb.Append(_name);
return sb.ToString().GetHashCode();
}
#endregion
#region Properties
public virtual float Price
{
get { return _price; }
set
{
OnPriceChanging();
_price = value;
OnPriceChanged();
}
}
partial void OnPriceChanging();
partial void OnPriceChanged();
public virtual string Name
{
get { return _name; }
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
partial void OnNameChanging();
partial void OnNameChanged();
public virtual IList<Store> Stores
{
get { return _stores; }
set
{
OnStoresChanging();
_stores = value;
OnStoresChanged();
}
}
partial void OnStoresChanging();
partial void OnStoresChanged();
#endregion
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="CodeSmithSampel.Generated.BusinessObjects" assembly="CodeSmithSampel">
<class name="CodeSmithSampel.Generated.BusinessObjects.Product, CodeSmithSampel" table="product" lazy="true">
<id name="Id" column="Id">
<generator class="native" />
</id>
<property name="Price" column="Price" />
<property name="Name" column="Name" />
<bag name="Stores" table="storeproduct" lazy="true" cascade="all" inverse="true" >
<key column="Product_id"></key>
<many-to-many column="Store_id" class="Store" />
</bag>
</class>
</hibernate-mapping>
IManagerFactory managerFactory = new ManagerFactory();
var productManager = managerFactory.GetProductManager();
var myProduct= productManager.GetById(2);
var myStore = new Store();
myStore.Name = "new Store"; //a "new store" entry is created in the Store table
myProduct.Stores.Add(myStore); // but this "new store" is not linked to the myproduct, as it should.
productManager.Session.CommitChanges();
category.Items.Add(item); // The category now "knows" about the relationship
item.Categories.Add(category); // The item now "knows" about the relationship
session.Update(item); // No effect, nothing will be saved!
session.Update(category); // The relationship will be saved
public class Store
{
public void AddProduct( Product p )
{
if( _products.Contains (p) == false )
{
_products.Add (p);
p.AddStore(this);
}
}
}
public class Product
{
public void AddStore( Store s )
{
if( _stores.Contains (s) == false )
{
_stores.Add (s);
s.AddProduct(this);
}
}
}