我有两个类,供应商和联系人。供应商是Contact的父母。供应商和联系人之间存在一对多的关系。我已将Vendor和Company之间的级联关系设置为none。这意味着(至少对我而言)当我更改供应商的联系人并保存供应商时,此保存操作不应级联到联系人,因此,我对联系人所做的任何更改都不应该持久保存到数据库。
然而,情况并非如此。当我更改联系人的FirstName并保存其父级时,保存操作会级联到Contact。例如,使用下面的测试函数,我看到一个与FirstName =“This_new_first_name_should_not_be_saved”的联系人。最初,我没想到这种变化会持续存在于数据库中。
我只是误解了级联是如何工作的,或者我的代码有问题吗?
test.cs中
[Test]
public void RemoveManyToOneAssociation()
{
var container = BuildContainer();
var vendorRepo = container.Resolve<Repository<Vendor>>(); //Get respository
var contactRepo = container.Resolve<Repository<Contact>>(); //Get repository
var vendor = vendorRepo.FirstOrDefault();
var contact = vendor.Contacts.FirstOrDefault();
contact.FirstName = "This_new_first_name_should_not_be_saved";
vendor.Contacts.Remove(contact);
vendorRepo.Save(vendor);
//The saving action above should not cascade to contacts because we have set cascade to "none"
}
Vendor.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DataAccess"
namespace="DataAccess">
<class name="Vendor">
<id name="Id" type="int" unsaved-value="0">
<generator class="hilo" />
</id>
<property name="VendorName" />
<set name="Contacts" inverse="true" cascade="none">
<key column="VendorID" />
<one-to-many class="Contact"/>
</set>
<many-to-one name="Company" column="CompanyID"></many-to-one>
</class>
</hibernate-mapping>
Contact.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DataAccess"
namespace="DataAccess">
<class name="Contact">
<id name="Id" type="int">
<generator class="hilo" />
</id>
<property name="FirstName" />
<property name="LastName" />
<many-to-one name="Vendor" class="Vendor" column="VendorID"></many-to-one>
</class>
</hibernate-mapping>
Vendor.cs
public class Vendor : Entity<int>
{
public Vendor()
{
}
public Vendor(string name)
{
VendorName = name;
}
public virtual string VendorName { set; get; }
public virtual ISet<Contact> Contacts { set; get; }
public virtual Company Company { set; get; }
public virtual void CopyTo(Vendor target)
{
target.VendorName = VendorName;
target.Company = Company;
}
}
Contact.cs
public class Contact : Entity<int>
{
public Contact()
{
//it's not the best practice to initialize virtual properties in constructor but we're controlling
//the inheritance in this so doing this should be fine
// http://stackoverflow.com/a/469577/89605
FirstName = "";
LastName = "";
}
public Contact(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public virtual string FirstName { set; get; }
public virtual string LastName { set; get; }
public virtual Vendor Vendor { set; get; }
public virtual void CopyTo(Contact contact)
{
contact.FirstName = FirstName;
contact.LastName = LastName;
}
}
更新 * Repository.cs *
public class Repository<T> where T : class
{
private ISession _session;
public Repository(ISession session)
{
_session = session;
}
public virtual T GetById(int id)
{
return _session.Get<T>(id);
}
public virtual T LoadById(int id)
{
return _session.Load<T>(id);
}
public virtual List<T> GetAll()
{
return _session.Query<T>().ToList();
}
public virtual T FirstOrDefault()
{
return _session.Query<T>().FirstOrDefault();
}
public virtual void Save(T entity)
{
using (ITransaction _transaction = _session.BeginTransaction())
{
_session.Save(entity);
_transaction.Commit();
}
}
public virtual void Delete(T entity)
{
using (ITransaction _transaction = _session.BeginTransaction())
{
_session.Delete(entity);
_transaction.Commit();
}
}
}
答案 0 :(得分:4)
正如您已经推断的那样,您误解了级联是如何工作的。更准确地说, NHibernate 的工作原理。
您对已经存在的实体所做的所有更改都会保留在Flush
。
对使用相同会话检索的实体的session.Save()
调用是NO-OP(我必须假设这是Repository<T>.Save()
方法的作用,因为我没有您的来源)< / p>