В моем приложении есть три объекта верхнего уровня: Схема, Проблема, Документ
Схемы могут содержать документы, а Проблемы могут содержать документы.
Когда я удаляю схему, я хочу, чтобы онаудалить документы, связанные с ним, если он не используется чем-то другим.Я хотел бы такое же поведение с проблемами.У меня это работает, когда единственная ассоциация находится в той же таблице в БД, но если она находится в другой таблице, то происходит сбой из-за ограничений внешнего ключа.
ex 1 ( Это будет каскадно правильно, поскольку существует только внешнее ограничение из канала в документ )
документ существует.
канал1 существует и содержит ссылку на документ1.
Если я удаляю цепь1, то он удаляет вместе с ней документ1.
ex 2 ( Это будет каскадно корректно, потому что существует только внешнее ограничение от Цепи к документу. )
Документ1 существует.
Схема1 существует и содержит ссылку на Документ1.
Circuit2 существует и содержит ссылку на Document1.
Если я удаляю Circuit1, то она удаляется, но Document1 не удаляется, поскольку Circuit2 существует.
Если я затем удаляю Circuit2, то Document1 удаляется.
ex 3 ( Это вызовет ошибку, потому что, когда он удаляет канал, он видит, что нет никаких других каналов, которые ссылаются на документ, поэтому он пытается удалить документ. Однако не должен, потому чтосуществует проблема, имеющая внешнее ограничение для документа. )
документ существует.
схема1 существует и содержит ссылку на документ 1.
проблема 1 существует и содержит ссылку на документ 1.
Если я удаляю Circuit1, то это терпит неудачу, потому что это пытается удалить Document1, но у Issues1 все еще есть ссылка.
БД:
Эта мысль не позволит загрузить изображение, поэтому вот 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();
}