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);
           }
        }
    }