Försöker göra en enkelt kommentar-sida där varje kommentar-rubrik visas under varandra. Om någon svara på ett inlägg ska det svaret vara intabbat en bit. Svarar någon på svaret ska det tabbas in osv.. Ska se ut ungefär såhär:
Jag tror ni förstår. När man klickar på en rubrik ska antingen hela texten visas under rubriken eller i ett annat fönster. det spelar egentligen ingen roll, kan jag fixa. Men det jag undrar över är hur man får till den där "TAB"-strukturen. Någon som har kodexempel eller tips på hur man kan göra? Kan använda både xml och databas.
Så att du har en parentId som visar vilket inlägg som detta inlägg hör till.
Det man sedan gör är att man gör en rekursivfunktion som hämtar ut alla poster som har parentID = X.
private void GetAllPost(int ID){
//-- hämta alla poster som har parentID = ID.
SELECT * FROM [post] WHERE ParentID = ID
//-- Skapa en while loop så skriver ut poster
while(finns poster){
//-- skriv ut posten till sidan
...
//-- hämta denna postens ID och kalla på denna funktion
GetAllPost(Post.ID);
}
}
Där har du principen för hur det fungerar, hur du sedan gör med tabbar och utskrift beror helt på hur du tänkt ha det så det får du pilla med själv.
Om du tycker det är viktigt med prestanda så kan det dock vara bra att istället göra en rekursiv lagrad procedur som exekveras inom databashanteraren, för att undvika den overhead som du får av att köra multipla anrop till databasen från en rekursiv .NET metod.
Jag vet att detta går att lösa med MS SQL Server 7 eftersom jag en gång (för typ 5 år sedan) själv implementerade en sådan rekursiv procedur just för att skapa ett kommentarsträd, men det finns troligtvis många andra databashanterare som också stöder rekursiva procedurer/funktioner.
Proceduren ska alltså returnera ett enda resultatset som du sedan kan loopa igenom, och för att du ska veta hur mycket du ska indentera på varje rad så kan du se till att varje post som returneras från proceduren innehåller en siffra som anger hur många parents den har, så att du med hjälp av den siffran kan styra hur många kolumner/mellanslag/css-pixlar som den aktuella raden ska indenteras med.
Den returnerade siffran som anger "level" (indenteringsnivån), d.v.s. hur många parents du har, kan antingen vara ett artificiellt fält som beräknas dynamiskt till en variabel inom proceduren om du vill slippa redundant information i den fysiska databasen, men level kan också anges som ett extra fält i tabellen.
I exemplet ovan skulle alltså _1 , _2 och _5 ha level 1, medan _3 har level 2 och _4 har level 3.
Om du tycker det är viktigt med prestanda så kan det dock vara bra att istället göra en rekursiv lagrad procedur som exekveras inom databashanteraren, för att undvika den overhead som du får av att köra multipla anrop till databasen från en rekursiv .NET metod.
Visst får du en overhead av att du gör flera SQL-anrop, men om du använder dig av cursors i T-SQL för att plocka fram datan så får du en större prestandhit. Har dock för mig att jag sett något exempel utan cursors, men kommer inte på det nu.
Om man inte vill göra flera anrop mot databasen, så kan man hämta all data en gång och lagra i ett dataset och sedan göra förfrågningar mot det, då har du endast 1 anrop till databasen och resterande utfrågningar sker i .NET mot datasetet. Det är en lösning på problemet, det finns garanterat fler.
Prestandaförlusten för en cursor i t-sql behöver inte bli så jättestor, om det inte är några joinoperationer och relativt få poster som ska hämtas. Man kan räkna med att varje fetch i en t-sqlcursor motsvarar resurserna som en select-satts tar från maskinen. Oftast går det att lösa med en enda lite mer komplicerad sql-fråga istället för en cursor, har du kollat så du inte kan lösa det med en select-satts?
Om du tycker det är viktigt med prestanda så kan det dock vara bra att istället göra en rekursiv lagrad procedur som exekveras inom databashanteraren, för att undvika den overhead som du får av att köra multipla anrop till databasen från en rekursiv .NET metod.
Visst får du en overhead av att du gör flera SQL-anrop, men om du använder dig av cursors i T-SQL för att plocka fram datan så får du en större prestandhit.
Det var ett intressant påstående men kan det verkligen vara möjligt.... rätta mig om jag har fel men jag har i alla fall alltid trott att det går till så här ungefär när man kör ett databas anrop från c# eller vb.net :
man anropar en odbc eller oledb -klass/driver
denna driver i sin tur anropar på nåt sätt ett C-API
C-drivern i sin tur skickar ett anrop till databasen
databasen utför sql-satsen
databasen returnerar binär data över nätverket
C-drivern tar emot datan och omvandlar det till ett format som kan tolkas av C#
odbc/oledb-drivern returnerar slutligen datat till din egen C#-kod
Om alla dessa steg ska köras upprepade gånger inifrån en metod, kan då verkligen det gå snabbare än att köra alltihop på en gång i databasen och alltså endast köra ovanstående stegen en enda gång ?
Det är särskilt steg 5 ovan, nätverkskommunikationen som i alla fall jag tycker borde ge väldigt stora prestandaförluster ? Finns det några mätningar som stöder påståendet att en cursor skulle vara så mycket långsammare jämfört med ovanstående ?
(i så fall, varför finns egentligen cursors om de ska behöva ge så dålig prestanda ?)
En lite annan fråga förresten som jag kan passa på och ställa, något som jag har funderat över ibland , är om det blir nätverkstrafik för varje metodanrop då man loopar ett resultat så här: "while (myReader.Read()) {"
Blir det liksom nätverkstrafik varje gång man anropar något på ett reader-objekt eller skickas alltid allting på en gång så att man liksom loopar lokalt från internminnet, eller kanske en kombination på så sätt att alla rader skickas på en gång från databasen, men bara upp till en viss gräns kanske några hundra rader åt gången så att man kan köra 100 stycken myreader.read() och sedan när det tar slut på data från minnet så blir det ett nytt nätverksanrop för att hämta ytterligare 100 rader till osv ???
Min fråga är asså om det är nån som säkert vet vilken nätverkstrafik som kommer att inträffa för varje anrop på en datareader ?
Ytterligare en fråga är om databas-drivers är tillräckligt smarta för att hoppa över nätverkstrafiken om den känner av att man anropar en databas-server som ligger på samma maskin som den maskin där det aktuella c# - programmet körs på, eller om den liksom ändå alltid skickar data via tcp/ip -trafik i alla fall ??
(om svaret är att den känner av det, gäller det då bara om man använder "localhost" i connection stringen eller kan den också fatta att en fullständig domän - eller ip-adress tillhör samma maskin som man själv kör på så att den därför kan "gå direkt på databasen" utan en omväg över tcp/ip och nätverkskabeln)
För varje fetch som görs i en cursor drar det rätt kraftigt med prestanda, enligt en förläsare jag hade på en kurs drog det ungefär likvärdig prestanda som en select, för varje fetch då och i en hel loop kan det bli otroligt prestandasänkande om man har många records som ska fetchas.
Cursors är ett relativt gammlat påhitt och praxis ska enligt de flesta jag har surrar om frågan med att inte använda dem så långt det går att undvikas, man kan oftast lösa det med en snyggare sql-fråga. Använder man sig av cursors hindrar du även DBA:n från att öka DBn prestanda då han inte kan/bör gå in i logiken i dina stored procedures å ändra.
Did you know that every FETCH being executed has about the same performance of executing a SELECT? This means that if your cursor has 10,000 records, it will execute about 10,000 SELECTs! If you can do this in a couple of SELECT, UPDATE or DELETE, it will be much faster.