[NHibernate] Verwijderen item uit List<>

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Hark_k
  • Registratie: September 2002
  • Laatst online: 09:08
Hoi,

Ik heb twee entiteiten/objecten, Category en Subcategory. Deze hebben een 1:N relatie.
Het Category object heeft een property IList<Subcategory> Subcategories.

Ik heb in ASP.Net MVC een form gemaakt waarin ik een categorie en subcategorieën kan bewerken. Eenmaal op de server is de IList<Subcategory> Subcategories weer gevuld met de nieuwe subcategorieën. Het updaten en invoegen van nieuwe subcategorieen gaat correct, alleen het verwijderen niet.

Hoe gaat NHibernate 2.1.2 echter standaard om met verwijderde items? Stel ik heb de volgende situatie:

Categorie: Hoofdcategorie A (CategoryId 10)
Subcategory A 1 (SubcategoryId 25)
Subcategory A 2 (SubcategoryId 26)
Subcategory A 3 (SubcategoryId 27)

en na bewerken:
Categorie: Hoofdcategorie A (CategoryId 10)
Subcategory A 1 (SubcategoryId 25)
Subcategory A 3 (SubcategoryId 27)

In dit geval zou bij een SaveOrUpdate(Category); de subcategory met id 26 verwijderd moeten worden. Is dit iets wat je handmatig moet doen of zou NHibernate dit zelf moeten doen? Met de SaveOrUpdate worden wel eerst oude items weggegooid en daarna de nieuwe aangemaakt, maar kan er geen wijs uit worden waarom SubcategoryId 26 nog blijft bestaan.

Alvast bedankt.

Acties:
  • 0 Henk 'm!

  • Guldan
  • Registratie: Juli 2002
  • Laatst online: 12-09 23:23

Guldan

Thee-Nerd

Je kan in de nhibernate xml config bestanden aangeven wat er moet gebeuren indien iets verwijderd wordt. Dus dan doet nHibernate dit automatisch voor je.

You know, I used to think it was awful that life was so unfair. Then I thought, wouldn't it be much worse if life were fair, and all the terrible things that happen to us come because we actually deserve them?


Acties:
  • 0 Henk 'm!

  • Hark_k
  • Registratie: September 2002
  • Laatst online: 09:08
Guldan schreef op maandag 14 februari 2011 @ 11:48:
Je kan in de nhibernate xml config bestanden aangeven wat er moet gebeuren indien iets verwijderd wordt. Dus dan doet nHibernate dit automatisch voor je.
Dat is als een parent verwijderd wordt, wat er dan met de childs moet gebeuren. Dit kan middels het cascade attribuut in de mapping.

Kort samengevat wil ik dus als het ware m'n objectmodel 'syncen' met de database, en verwijderde objecten moeten ook uit de database verwijderd worden. Kan dit automatisch of moet ik zelf een lijst met verwijderde objecten bij gaan houden en ieder object middels een Delete() verwijderen?

Acties:
  • 0 Henk 'm!

  • Hark_k
  • Registratie: September 2002
  • Laatst online: 09:08
Niemand?

Acties:
  • 0 Henk 'm!

  • alwinuzz
  • Registratie: April 2008
  • Laatst online: 08:46
Ik gok dat je Subcategory een property/db kolom heeft die verwijst naar de 'parent' Category.
Je kan dan wel Category.Subcategories.Remove(subCat26) doen, maar subCat.ParentCategory is nog steeds ingesteld op Category10.
Bij de volgende Session staat die subcategory er dan doodleuk weer.

Daarom zie je vaak:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Category {

// read write
// gemapped met cascade=all-delete-orphan
private ISet<Subcategory> subCats;

// read only voor de buitenwereld
public IEnumerable<Subcategory> Subcategories {get {return subCats;}}

// collectie aanpassen in losse methods, zodat je subCat zelf gelijk kan wijzigen
public void AddSubCat(subCat){
subCats.Add(subCat);
subCat.ParentCategory = subCat;
}
public void RemoveSubCat(subCat){
subCats.Remove(subCat);
subCat.ParentCategory = null;
}

}


Uhm, zoals dit dus :)

Acties:
  • 0 Henk 'm!

  • Hark_k
  • Registratie: September 2002
  • Laatst online: 09:08
Dan zit je echter nog steeds met het verwijderen van de subcategorie middels NHibernate.

Ik heb inmiddels een werkende oplossing waarin dit wel meevalt. Aan de Subcategory heb ik een property Remove toegevoegd. In de View gebruik ik het volgende:

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="Subcategories">
    <% Int32 i = 0;
       foreach (Subcategory subcategory in Model.Category.Subcategories)
       { %>
            <div class="Subcategory" id="Subcategory-<%= i.ToString() %>" index="<% = i.ToString() %>">
                <%= Html.HiddenFor(x => x.Category.Subcategories[i].SubcategoryId) %> 
                <%= Html.HiddenFor(x => x.Category.Subcategories[i].Remove) %>                                         
                <%= Html.EditorFor(x => x.Category.Subcategories[i].Name) %> 

                <a href="#" onclick="DeleteSubcategory(<%= i.ToString() %>);" id="DeleteSubcategoryLink<%= i.ToString() %>">Remove</a>
                <a href="#" onclick="UndeleteSubcategory(<%= i.ToString() %>);" id="UndeleteSubcategoryLink<%= i.ToString() %>" style="display: none;">Undo removal</a>
            </div>
    <%  i++;
        } %>
</div>


Als je de model-binding correct wilt laten functioneren moet je zorgen dat de subcategories opvolgend blijven. In je HTML zie je dus dit:

HTML:
1
2
3
4
5
6
7
8
<div index="0" id="Subcategory-0" class="Subcategory">
    <input type="hidden" value="25" name="Category.Subcategories[0].SubcategoryId" id="NewCategory_Subcategories_0__SubcategoryId"> 
    <input type="hidden" value="False" name="Category.Subcategories[0].Remove" id="NewCategory_Subcategories_0__Remove">                                         
    <input type="text" value="Sub 1a" name="Category.Subcategories[0].Name" id="NewCategory_Subcategories_0__Name" class="text-box single-line"> 

    <a id="DeleteSubcategoryLink0" onclick="DeleteSubcategory(0);" href="#">Remove</a>
    <a style="display: none;" id="UndeleteSubcategoryLink0" onclick="UndeleteSubcategory(0);" href="#">Undo removal</a>
</div>


M.b.v. jQuery zet ik de Category.Subcategories[0].Remove op true en markeer ik hem als verwijderd middels wat style-wijzigingen. Nieuwe subcategorieen voeg ik opeenvolgend toe, met [1] in dit geval. In de controller krijg ik netjes een Category-object binnen met daarin een list Subcategories. Daar is het een kwestie van filteren op Remove = true en die objecten verwijderen. Kost wat uurtjes maar dan heb je ook wat ;)
Pagina: 1