gpt4 book ai didi

c# - 多对多在 NHibernate 中删除具有共同关联的两个 parent

转载 作者:行者123 更新时间:2023-11-30 18:43:21 26 4
gpt4 key购买 nike

我的应用中有 3 个顶级实体:Circuit、Issue、Document

电路可以包含文档,问题可以包含文档。

当我删除一个 Circuit 时,我希望它删除与其关联的文档,除非它被其他东西使用。我希望 Issues 也有同样的行为。当唯一的关联在数据库中的同一个表中时,我让它工作,但如果它在另一个表中,那么它会由于外键约束而失败。

ex 1(这将正确级联,因为从电路到文档只有一个外部约束)
Document1 存在。
Circuit1 存在并包含对 Document1 的引用。
如果我删除 Circuit1,那么它会删除 Document1。

ex 2(这将正确地级联,因为从 Circuit 到 Document 只有外部约束。)
Document1 存在。
Circuit1 存在并包含对 Document1 的引用。
Circuit2 存在并包含对 Document1 的引用。
如果我删除 Circuit1,那么它会被删除,但 Document1 不会被删除,因为 Circuit2 存在。
如果我随后删除 Circuit2,则 Document1 将被删除。

ex 3(这将引发错误,因为当它删除电路时,它发现没有其他电路引用该文档,因此它会尝试删除该文档。但是它不应该,因为有一个对文档有外部约束的问题。)
文档 1 存在。
Circuit1 存在并包含对 Document1 的引用。
Issue1 存在并包含对 Document1 的引用。
如果我删除 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();
}

最佳答案

您需要先清除集合,然后再删除父项。 delete-orphan 导致删除操作级联到子项,因为集合中仍引用该子项。该对象在取消引用之前没有成为孤儿的可能性,因此不会对其进行检查。 Section 10.11 in this documentation解释得很好,但仍然令人困惑。据我了解,delete-orphan 删除父项时有两种可能的结果:

  1. 如果父集合中仍引用子集合,则将其删除。
  2. 如果子项不再在父项集合中引用,那么如果它是孤儿,即没有其他引用,则将其删除。

我认为这会按预期工作:

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

关于c# - 多对多在 NHibernate 中删除具有共同关联的两个 parent ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4521229/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com