Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 流畅的NHibernate:仅在多对多关系上从一侧级联删除_C#_Fluent Nhibernate - Fatal编程技术网

C# 流畅的NHibernate:仅在多对多关系上从一侧级联删除

C# 流畅的NHibernate:仅在多对多关系上从一侧级联删除,c#,fluent-nhibernate,C#,Fluent Nhibernate,我正在尝试编写正确的映射配置,允许我在多对多关系设置中仅从一侧删除 下面是我的Map和Entity类的代码结构,以及实际的程序(psuedo)代码和SQL模式。相当简单和直接 我们有一个person表和一个file表。然后我们有一个personfile表,因为一个人可以有许多文件,同样,一个文件可以分配给许多人 现在,当我删除个人记录时,personfile和file中属于该个人的相关记录将被删除。到目前为止还不错 如果我删除一个文件(如下图所示),我希望它从personfile和file中删除

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

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

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

现在,当我删除个人记录时,personfile和file中属于该个人的相关记录将被删除。到目前为止还不错

如果我删除一个文件(如下图所示),我希望它从personfile和file中删除,但不从person中删除

然而,按照我的设置方式,NHibernate只调用deleteonfile表,这会导致错误。例如

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`))
我确实向FileMap添加了Cascade.Delete(),但当我这样做时,从文件表中删除也会从person表中删除

重申一下,我最终想要的是调用Delete(file),它将从personfile表和file表(而不是person表)中删除记录

我应该改为获取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这样做,首先删除关系表中的记录,然后删除ATualFile表中的记录。 只要最终结果相同,查询不必是特定的

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

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

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

我们有一个person表和一个file表。然后我们有一张单人桌 因为一个人可以有很多文件和 同样,可以将文件分配给 很多人

现在,当我删除个人记录时, personfile和中的相关记录 属于此人的文件是 删除。到目前为止还不错

为我工作

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

Session.Flush();

Session.CreateQuery("delete from File").ExecuteUpdate();