Вот пример, который делает то, что я думаю, вы пытаетесь сделать. Дайте мне знать, если я неправильно понял, что вы пытаетесь сделать.
Имеются следующие "доменные" классы:
public class Person
{
private IList<Pet> pets;
protected Person()
{ }
public Person(string name)
{
Name = name;
pets = new List<Pet>();
}
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual IEnumerable<Pet> Pets
{
get { return pets; }
}
public virtual void AddPet(Pet pet)
{
pets.Add(pet);
}
public virtual void RemovePet(Pet pet)
{
pets.Remove(pet);
}
}
public class Pet
{
protected Pet()
{ }
public Pet(string name)
{
Name = name;
}
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
}
Со следующим отображением:
public class PersonMap : ClassMap<Person>
{
public PersonMap()
{
LazyLoad();
Id(x => x.Id).GeneratedBy.GuidComb();
Map(x => x.Name);
HasMany(x => x.Pets)
.Cascade.AllDeleteOrphan()
.Access.AsLowerCaseField()
.SetAttribute("lazy", "false");
}
}
public class PetMap : ClassMap<Pet>
{
public PetMap()
{
Id(x => x.Id).GeneratedBy.GuidComb();
Map(x => x.Name);
}
}
Этот тест:
[Test]
public void CanDeleteChildren()
{
Person person = new Person("joe");
Pet dog = new Pet("dog");
Pet cat = new Pet("cat");
person.AddPet(dog);
person.AddPet(cat);
Repository.Save(person);
UnitOfWork.Commit();
CreateSession();
UnitOfWork.BeginTransaction();
Person retrievedPerson = Repository.Get<Person>(person.Id);
Repository.Evict(retrievedPerson);
retrievedPerson.Name = "Evicted";
Assert.AreEqual(2, retrievedPerson.Pets.Count());
retrievedPerson.RemovePet(retrievedPerson.Pets.First());
Assert.AreEqual(1, retrievedPerson.Pets.Count());
Repository.Save(retrievedPerson);
UnitOfWork.Commit();
CreateSession();
UnitOfWork.BeginTransaction();
retrievedPerson = Repository.Get<Person>(person.Id);
Assert.AreEqual(1, retrievedPerson.Pets.Count());
}
запускается и генерирует следующий sql:
DeletingChildrenOfEvictedObject.CanDeleteChildren: прошло
NHibernate: INSERT INTO [Person] (Name, Id) VALUES (@ p0, @ p1); @ p0 = 'joe', @ p1 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate: INSERT INTO [Pet] (Name, Id) VALUES (@ p0, @ p1); @ p0 = 'собака', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb'
NHibernate: INSERT INTO [Pet] (Name, Id) VALUES (@ p0, @ p1); @ p0 = 'cat', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate: ОБНОВЛЕНИЕ [Pet] SET Person_id = @ p0 WHERE Id = @ p1; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb'
NHibernate: ОБНОВЛЕНИЕ [Pet] SET Person_id = @ p0 WHERE Id = @ p1; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate: ВЫБЕРИТЕ person0_.Id как Id5_0_, person0_.Name как Name5_0_ ИЗ [Person] person0_ ГДЕ person0_.Id=@p0; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate: ВЫБЕРИТЕ pets0_.Person_id как Person3_1_, pets0_.Id как Id1_, pets0_.Id как Id6_0_, pets0_.Name как Имя6_0_ ИЗ [Pet] pets0_ WHERE pets0_.Person_id=@p0; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate: ОБНОВЛЕНИЕ [Персона] SET Name = @ p0 WHERE Id = @ p1; @ p0 = 'Выселенный', @ p1 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate: ОБНОВЛЕНИЕ [Pet] SET Name = @ p0 WHERE Id = @ p1; @ p0 = 'собака', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb'
NHibernate: ОБНОВЛЕНИЕ [Pet] SET Person_id = null WHERE Person_id = @ p0 AND Id = @ p1; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate: УДАЛИТЬ [Pet] WHERE Id = @ p0; @ p0 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate: ВЫБЕРИТЕ person0_.Id как Id5_0_, person0_.Name как Name5_0_ ИЗ [Person] person0_ ГДЕ person0_.Id=@p0; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate: ВЫБЕРИТЕ pets0_.Person_id как Person3_1_, pets0_.Id как Id1_, pets0_.Id как Id6_0_, pets0_.Name как Имя6_0_ ИЗ [Pet] pets0_ WHERE pets0_.Person_id=@p0; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
Обратите внимание на УДАЛЕНИЕ ОТ [Pet] ...
Итак, что вам нужно сделать, это вручную передать объект Person (в этом примере) с измененными коллекциями, и он должен иметь возможность определять, что удалять. Убедитесь, что у вас установлен атрибут Cascade.AllDeleteOrphan ().