gpt4 book ai didi

c# - 流利的 NHibernate : Cascade delete from one side only on Many-to-Many relationship

转载 作者:太空宇宙 更新时间:2023-11-03 11:50:27 25 4
gpt4 key购买 nike

我正在尝试编写正确的 map 配置,以允许我仅从多对多关系设置的一侧删除。

下面是我的 map 和实体类的代码结构以及实际程序(伪)代码和 SQL 模式。相当简单直接。

我们有一个人表和一个文件表。然后我们有一个 personfile 表,因为一个人可以有很多文件,同样,一个文件可以分配给很多人。

现在,当我删除一个人的记录时,personfile 和属于该人的文件中的相关记录也被删除。到目前为止一切顺利。

如果我删除一个文件(如下面的 Program.cs 所示),我希望它从 personfile 和 file 中删除,而不是从 person 中删除。

但是按照我设置的方式,NHibernate 只调用文件表上的删除,这会导致错误。例如。

ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`personfile`, CONSTRAINT  `FK_PersonFile2` FOREIGN KEY (`FileID`) REFERENCES `file` (`FileID`))

我确实将 Cascade.Delete() 添加到 FileMap,但是当我这样做时,从文件表中删除也会从人员表中删除。

重申一下,我最终想要的是调用 Delete(file),这反过来会删除 personfile 表和 file 表中的记录,但不会删除 person 表中的记录。

我是否应该改为获取人员记录,然后从 person.Files[] 集合中删除文件记录,然后调用 SaveOrUpdate()?

考虑这个场景。

首先确保我们在所有表中都有正确的数据。

mysql> SELECT f.FileID, p.PersonID, p.Name, f.Filename
-> FROM personfile pf
-> LEFT OUTER JOIN file f on pf.FileID = f.FileID
-> LEFT OUTER JOIN person p on pf.PersonID = p.PersonID
-> ;
+--------+----------+------+-------------+
| FileID | PersonID | Name | Filename |
+--------+----------+------+-------------+
| 1 | 1 | John | Apples.jpg |
| 2 | 1 | John | Oranges.jpg |
| 3 | 2 | Bob | Grapes.jpg |
+--------+----------+------+-------------+
3 rows in set (0.00 sec)

现在在正常情况下,如果您尝试仅删除文件(这是 NHibernate 根据我的设置尝试执行的操作),这就是预期的结果。

mysql> DELETE FROM file WHERE file.FileID = 2;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`test`.`pe
rsonfile`, CONSTRAINT `FK_PersonFile2` FOREIGN KEY (`FileID`) REFERENCES `file` (`FileID`))

我想让 NHibernate 做的是这样的事情,首先删除关系表中的记录,然后删除实际文件表中的记录。查询不必具体,只要最终结果相同即可。

mysql> DELETE pf, f
-> FROM personfile pf
-> LEFT OUTER JOIN file f on pf.FileID = f.FileID
-> LEFT OUTER JOIN person p on pf.PersonID = p.PersonID
-> WHERE pf.FileID = 2
-> ;
Query OK, 2 rows affected (0.05 sec)

上述删除的结果是有效的。

mysql> SELECT f.FileID, p.PersonID, p.Name, f.Filename
-> FROM personfile pf
-> LEFT OUTER JOIN file f on pf.FileID = f.FileID
-> LEFT OUTER JOIN person p on pf.PersonID = p.PersonID
-> ;
+--------+----------+------+------------+
| FileID | PersonID | Name | Filename |
+--------+----------+------+------------+
| 1 | 1 | John | Apples.jpg |
| 3 | 2 | Bob | Grapes.jpg |
+--------+----------+------+------------+
2 rows in set (0.00 sec)

Program.cs

File file = db.Session.Load<File>(2);

session.Delete(file);

transaction.Commit();

映射

public class FileMap : ClassMap<File>
{
public FileMap()
{
Id(x => x.FileID)
.GeneratedBy.Identity();
Map(x => x.Filename)

HasManyToMany(x => x.Persons)
.Table("PersonFile")
.Inverse()
.ParentKeyColumn("FileID")
.ChildKeyColumn("PersonID");
}
}

public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
Id(x => x.PersonID)
.GeneratedBy.Identity();
Map(x => x.Name)

HasManyToMany(x => x.Files)
.Table("PersonFile")
.Cascade.Delete()
.ParentKeyColumn("PersonID")
.ChildKeyColumn("FileID");
}
}

实体

public class File
{
public virtual uint FileID { get; set; }
public virtual string Filename { get; set; }

public virtual IList<Person> Persons { get; set; }
}

public class Person
{
public virtual uint PersonID { get; private set; }
public virtual string Name { get; set; }

public virtual IList<File> Files { get; set; }
}

SQL

CREATE TABLE `file` (
`FileID` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`FileID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `person` (
`PersonID` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`PersonID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `personfile` (
`PersonID` int(11) unsigned NOT NULL DEFAULT '0',
`FileID` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`PersonID`,`FileID`),
KEY `FK_PersonFile2` (`FileID`),
CONSTRAINT `FK_PersonFile1` FOREIGN KEY (`PersonID`) REFERENCES `person` (`PersonID`),
CONSTRAINT `FK_PersonFile2` FOREIGN KEY (`FileID`) REFERENCES `file` (`FileID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

最佳答案

在删除文件之前尝试调用 File.Persons.Clear() 从文件中删除链接的人物。

我很好奇这个要求;第二句话似乎与它相矛盾,因为您可以删除链接到与您要删除的人不同的人的文件记录。

We have a person table, and a file table. We then have a personfile table since a person can have many files and likewise, a file can be assigned to many persons.

Now, when I delete a person record, the related records in personfile and file belonging to the person are deleted. So far so good.

关于c# - 流利的 NHibernate : Cascade delete from one side only on Many-to-Many relationship,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2241041/

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