다음은 내가하려는 일을 보여주는 예입니다. 당신이하려는 일을 오해 한 적이 있다면 알려주세요.
다음 "도메인"클래스를 감안할 때 :
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 : Passed NHibernate : INSERT INTO [Person] (Name, Id) VALUES (@ p0, @ p1); @ p0 = 'joe', @ p1 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate : INSERT INTO [이름] ID VALUES (@ p0, @ p1); @ p0 = '개', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb'
NHibernate : INSERT INTO [애완 동물] (이름, ID) VALUES (@ p0, @ p1); @ p0 = 'cat', @ p1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate : UPDATE [애완 동물] SET Person_id = @ p0 WHERE Id = @ p1; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'@ P1 = '464e59c7-74d0-4317-9c22-9bf801013abb'
NHibernate에 : UPDATE [동물] SET person_id로 P0 = @ WHERE 식 @ P1; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'@ P1 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate에 [이용시 FROM Name5_0_ 같은 Id5_0_, person0_.Name로 person0_.Id를 선택 ] person0_ 어디서 [email protected]; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate에 : Person3_1_, Id1_ 같은 pets0_.Id, Id6_0_ 같은 pets0_.Id, pets0_.Name Name6_0_ 같은 FROM [동물] pets0_로 pets0_.Person_id를 선택 [email protected]; @ p0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate : UPDATE [Person] SET Name = @ p0 WHERE Id = @ p1; @ p0 = 'Evicted', @ p1 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate : UPDATE [애완 동물] SET 이름 = @ p0 WHERE Id = @ p1; @ p0 = 'dog', @ p1 = '464e59c7-74d0-4317-9c22-9bf801013abb' NHibernate : UPDATE [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에 [동물]에서 삭제 WHERE 식 @ P0; @ P0 = '010c2fd9-59c4-4e66-94fb-9bf801013abb'
NHibernate에 : Id5_0_, FROM 등 Name5_0_ person0_.Name [PERSON] person0_ [email protected]로 person0_.Id을 선택; @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'
NHibernate에 : Person3_1_, Id1_ 같은 pets0_.Id, Id6_0_ 같은 pets0_.Id, pets0_.Name Name6_0_ 같은 FROM [동물] pets0_로 pets0_.Person_id를 선택 [email protected]; 당신이 할 수 있도록 필요한 @ P0 = 'cd123fc8-6163-42a5-aeeb-9bf801013ab2'는이 [애완 동물]에서 삭제
주 ... 그래서
는 손 NHibernate에 Person 객체 (에 이 예제)를 수정 된 콜렉션과 비교하여 삭제할 대상을 결정할 수 있어야합니다. Cascade.AllDeleteOrphan() 속성이 설정되어 있는지 확인하십시오.
대단히 감사합니다. 많은 작업이있었습니다! 불행히도, 내가 고민하고있는 비트는 두 번째 세션/트랜잭션 (즉, 내 POST)에있는 'Person'객체가 ModelBinder에 의해 생성 된 완전히 새로운 객체이며, 수정 된 필드가 거의없고 '자식 삭제'호출이 몇 개있었습니다. 내가 찾고있는 것은 새로운 객체를 가져 와서 변경된 객체를 검색하여 nh가 필요한 SQL을 처리 할 수있는 방법이라고 생각합니다. 어쩌면 그것은 단지 존재하지 않을 수도 있습니다. –
그 상황을 처리하는 경향은 모델 바인더로 만든 새 개체를 프레젠테이션 모델 개체로 처리하는 것입니다. 업데이트하고 해당 객체에 업데이트를 적용하려는 객체를 검색해야합니다 (또는 어떻게 든 "지속 된"클래스의 인스턴스를 생성해야합니다). 그런 다음 해당 객체를 Hibernate에 저장할 수 있습니다. 말이 돼? –
'수동'(즉, 속성 별, 루프 별 또는 하위 컬렉션 용)은 '검색된'객체의 속성을 '프레젠테이션 (즉 POST)'객체의 속성으로 덮어 씁니 까? 필요한 하위 삭제를 수동으로 계산 하시겠습니까? 내가 바라던 것보다 더 많은 일 (그리고 유지 보수!)을 보입니다. 모델 바인더로 귀찮게 여길 가치가없는 것처럼 보입니다. 실제로 필드 응답을 양식에서 한 번에 하나씩 처리해야하는 것처럼 보입니다. 그래도 도움을 주셔서 감사합니다. –