我有以下数据库架构:
http://lh4.ggpht.com/_SDci0Pf3tzU/SdM3XnAmmxI/AAAAAAAAEps/Ie3xW3ZVNfQ/s400/styleerror.png
这是我的映射文件:
<?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>
Run Code Online (Sandbox Code Playgroud)
这是我的Store实体类:
public partial class Store : BusinessBase<int>
{
#region Declarations
private string _name = String.Empty;
private IList<Employee> _employees = new List<Employee>();
private IList<Product> _products = new List<Product>();
#endregion
#region Constructors
public Store() { }
#endregion
#region Methods
public override int GetHashCode()
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(this.GetType().FullName);
sb.Append(_name);
return sb.ToString().GetHashCode();
}
#endregion
#region Properties
public virtual string Name
{
get { return _name; }
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
partial void OnNameChanging();
partial void OnNameChanged();
public virtual IList<Employee> Employees
{
get { return _employees; }
set
{
OnEmployeesChanging();
_employees = value;
OnEmployeesChanged();
}
}
partial void OnEmployeesChanging();
partial void OnEmployeesChanged();
public virtual IList<Product> Products
{
get { return _products; }
set
{
OnProductsChanging();
_products = value;
OnProductsChanged();
}
}
partial void OnProductsChanging();
partial void OnProductsChanged();
#endregion
}
Run Code Online (Sandbox Code Playgroud)
产品类别:
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
}
Run Code Online (Sandbox Code Playgroud)
Product类的映射:
<?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>
Run Code Online (Sandbox Code Playgroud)
特别奇怪的是,当我将Store对象添加到其中一个产品时,数据库记录不会更新; 尽管新的商店对象存在于数据库中,但似乎并未发生添加:
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();
Run Code Online (Sandbox Code Playgroud)
有什么我想念的吗?
注意:我使用CodeSmith生成上面的代码.
编辑:接受的答案有效.我遇到这个问题的原因是因为
inverse = true,而不是两个.因此,Product或Store应将inverse设置为false.代码生成工具没有正确处理这个问题.这可能与storeproducts表中有代理键的事实有关吗?
如果删除此代理键列Id并将主键放在product_id和store_id列的组合上会发生什么?
我相信,如果你想在storeproducts表上有一个代理键,你将不得不创建另一个实体.
如果要使用代理键,则必须使用idbag映射.
您的Product类和映射如何?我看到你在Store实体的Products集合的映射中指定了'inverse'属性.
如果您这样做(因此您具有双向关联),那么您也应该将Store添加到产品的Stores集合中.从NH文件 - 以来:
仅对关联的反向末端所做的更改不会保留.这意味着NHibernate在内存中有两个表示形式,用于每个双向关联,一个链接从A到B,另一个链接从B到A.如果你考虑.NET对象模型以及我们如何创建一个多对象,这将更容易理解. - C#中的很多关系:
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
Run Code Online (Sandbox Code Playgroud)
非反向侧用于将内存中表示保存到数据库.如果两者都触发更改,我们将获得一个不必要的INSERT/UPDATE,甚至可能是外键冲突!对于双向一对多关联,当然也是如此.
您可以通过将一对多关联映射到同一个表列作为多对一关联并声明多值结尾="真"来映射双向一对多关联.
这意味着,只有一端应该是反向的.将商品添加到商店,应该这样做:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
(检查集合是否已包含要添加的项目非常重要;否则您将最终处于无限循环中.
| 归档时间: |
|
| 查看次数: |
4140 次 |
| 最近记录: |