我的应用中有3个顶级实体:电路,问题,文档
电路可以包含文档,问题可以包含文档。
当我删除一个电路时,我希望它删除与之相关的文档,除非它被其他东西使用。我希望问题与此相同。当唯一的关联在db中的同一个表中时,我有它工作,但如果它在另一个表中,那么它会因外键约束而失败。
ex 1(这将正确级联,因为从电路到文档只有外来约束)
Document1存在。
Circuit1存在并包含对Document1的引用
如果我删除Circuit1,那么它会删除Document1。
ex 2(这将正确级联,因为从电路到文档只有外来约束。)
Document1存在。
Circuit1存在并包含对Document1的引用
Circuit2存在并包含对Document1的引用
如果删除Circuit1,则删除它,但不删除Document1,因为Circuit2存在
如果我然后删除Circuit2,则删除Document1。
ex 3(这将引发错误,因为当它删除电路时,它看到没有其他电路引用该文档,因此它试图删除该文档。但它不应该,因为有一个对文档有外来约束的问题。)
文件1存在。
Circuit1存在并包含对Document1的引用
Issue1存在并包含对Document1的引用
如果我删除Circuit1,那么它会失败,因为它试图删除Document1,但Issues1仍然有一个引用。
DB:
这个想法不会让上传图像,所以这里是数据库的ERD:http://lh3.ggpht.com/_jZWhe7NXay8/TROJhOd7qlI/AAAAAAAAAGU/rkni3oEANvc/CircuitIssues.gif
型号:
public class Circuit
{
public virtual int CircuitID { get; set; }
public virtual string CJON { get; set; }
public virtual IList<Document> Documents { get; set; }
}
public class Issue
{
public virtual int IssueID { get; set; }
public virtual string Summary { get; set; }
public virtual IList<Model.Document> Documents { get; set; }
}
public class Document
{
public virtual int DocumentID { get; set; }
public virtual string Data { get; set; }
}
映射文件:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="Model">
<class name="Circuit" table="Circuit">
<id name="CircuitID">
<column name="CircuitID" not-null="true"/>
<generator class="identity" />
</id>
<property name="CJON" column="CJON" type="string" not-null="true"/>
<bag name="Documents" table="CircuitDocument" cascade="save-update,delete-orphan">
<key column="CircuitID"/>
<many-to-many class="Document">
<column name="DocumentID" not-null="true"/>
</many-to-many>
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="Model">
<class name="Issue" table="Issue">
<id name="IssueID">
<column name="IssueID" not-null="true"/>
<generator class="identity" />
</id>
<property name="Summary" column="Summary" type="string" not-null="true"/>
<bag name="Documents" table="IssueDocument" cascade="save-update,delete-orphan">
<key column="IssueID"/>
<many-to-many class="Document">
<column name="DocumentID" not-null="true"/>
</many-to-many>
</bag>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Model" assembly="Model">
<class name="Document" table="Document">
<id name="DocumentID">
<column name="DocumentID" not-null="true"/>
<generator class="identity" />
</id>
<property name="Data" column="Data" type="string" not-null="true"/>
</class>
</hibernate-mapping>
代码:
using (ISession session = sessionFactory.OpenSession())
{
var doc = new Model.Document() { Data = "Doc" };
var circuit = new Model.Circuit() { CJON = "circ" };
circuit.Documents = new List<Model.Document>(new Model.Document[] { doc });
var issue = new Model.Issue() { Summary = "iss" };
issue.Documents = new List<Model.Document>(new Model.Document[] { doc });
session.Save(circuit);
session.Save(issue);
session.Flush();
}
using (ISession session = sessionFactory.OpenSession())
{
foreach (var item in session.CreateCriteria<Model.Circuit>().List<Model.Circuit>())
{
session.Delete(item);
}
//this flush fails, because there is a reference to a child document from issue
session.Flush();
foreach (var item in session.CreateCriteria<Model.Issue>().List<Model.Issue>())
{
session.Delete(item);
}
session.Flush();
}
答案 0 :(得分:0)
您需要在删除父级之前清除该集合。 delete-orphan
导致删除操作级联到子级,因为子级仍在集合中引用。在取消对象之前,该对象不具有成为孤儿的可能性,因此不会检查该对象。 Section 10.11 in this documentation解释得很好,但仍然令人困惑。据我了解,删除父项时delete-orphan
有两种可能的结果:
我认为这会按预期运作:
using (ISession session = sessionFactory.OpenSession())
{
foreach (var item in session.CreateCriteria<Model.Circuit>().List<Model.Circuit>())
{
item.Documents.Clear();
session.Delete(item);
}
session.Flush();
foreach (var item in session.CreateCriteria<Model.Issue>().List<Model.Issue>())
{
item.Documents.Clear();
session.Delete(item);
}
session.Flush();
}