20. oktober 2004 - 21:50Der er
27 kommentarer og 1 løsning
Problemer med GetParentRow/GetParentRows
Hep !
Jeg håber der er en der kan hjælpe mig en smule. Mit problem består i at jeg skal have hentet nogle et ID nummer fra en "parent/master" tabel - via en "pointer-tabel". Tror heller lige at jeg visuelt må illustrere det:
Jeg har følgende 3 tabeller (course_hole er "pointer-tabellen", som jeg bruger i forbindelse med den "mange-til-mange" relation der imellem "Course" og "Hole"):
Course: ------- id <-- PK name ...
Course_Hole ------- id <-- PK course_id <-- FK hole_id <-- FK hole_no hole_handicap_index
Hole ------- id <-- PK par ...
Når jeg har fundet frem til ID nummeret på den Course_Hole-DataRow, der "peger" på den Hole-DataRow jeg vil finde, håbede jeg lidt på at jeg kunne gøre det med:
index_number = "ID på min "Course_Hole"-DataRow, hvis parent jeg vil finde.
Du må så indexere dig frem til den du er interesseret i (f.eks. parents[0]).
Du kan også løbe dem igennem : foreach(DataRow dr in oDataSet.Tables["course_holes"].Rows[index_number].GetParentRows("REL course_holes-holes",DataRowVersion.Original)) { // gør noget med rækken. }
(jeg går ud fra at det er DataRowVersion.Original du er interesset i, men hvis du skal have den "mest aktuelle værdi" kan du brug DataRowVersion.Current).
hmm... frygter lidt at det er i oprettelsen af mine relationer den er gal. For jeg har 3 forskellige "courses"/baner med hver 18 huller. Og ID'et som jeg får fat i via min relation er:
37 på alle de huller der på den første bane/course. 38 den alle 18 huller på bane 2 og 39 de sidste 18 huller, der er på den sidste og treje bane
Min app er opbygget i 3 lag - et presentation-, buisness- og et Data Access lag. Alle relationerne oprettes i business-laget:
Dvs. at jeg har ét overordnet dataset (oDataSet), som jeg så løbende tilføjer mine tabeller til.
BL Course: --------------------------- DACourse oDACourse = new DACourse(); oDataSet = oDACourse.getSelectedCourses(arrayOfClubs, oDataSet, out arrayOfCourses);
// (2) HENTER VORES COURSE_HOLE-OBJEKTER FOR DE PÅGÆLDENDE BANER: // Vi tilføjer en tabel til dataset'et med de pågældende baners "course_hole's": BLCourseHole oBLCourseHole = new BLCourseHole(); oDataSet = oBLCourseHole.getSelectedCourseHoles(arrayOfCourses, oDataSet);
//(3) OPRETTER RELATIONEN MELLEM DE TO TABELLER: // Opretter relationen (master-detail) imellem tabellerne: oDataRelation = new DataRelation("REL SELECTEDcourses-SELECTEDcourse_holes", oDataSet.Tables["SELECTEDcourses"].Columns["id"], oDataSet.Tables["SELECTEDcourse_holes"].Columns["course_id"]);
// (4) Tilføjer relationen til DataSet'et: oDataSet.Relations.Add(oDataRelation);
BL Course_Hole: --------------------------- // (1) HENTER VORES COURSE_HOLE-OBJEKTER FOR DE PÅGÆLDENDE BANER: DACourseHole oDACourseHole = new DACourseHole(); oDataSet = oDACourseHole.getSelectedCourseHoles(arrayOfCourses, oDataSet, out arrayOfCourseHoles);
// (2) HENTER VORES HOLE-OBJEKTER FOR DE PÅGÆLDENDE COURSE_HOLES: BLHole oBLHole = new BLHole(); oDataSet = oBLHole.getSelectedHoles(arrayOfCourseHoles, oDataSet);
// (3) OPRETTER RELATIONEN MELLEM DE TO TABELLER: // Opretter relationen (master-detail) imellem tabellerne g 'course' oDataRelation = new DataRelation("REL SELECTEDcourse_holes-SELECTEDholes", oDataSet.Tables["SELECTEDholes"].Columns["id"], oDataSet.Tables["SELECTEDcourse_holes"].Columns["hole_id"]); // (4) Tilføjer relationen til DataSet'et: oDataSet.Relations.Add(oDataRelation);
ahh... jeg gør det normalt på en lidt anden måde (ikke at det nødvendigvis er smartere).
Jeg plejer at definere de datasets jeg vil bruge ved specialiserede datasets, hvor jeg direkte i specialiseringen angiver tabeller, relationer (og navnene på samme).
f.eks. sådan her :
public SomeDataSet : DataSet { public const string RelationOne = "RelationOne"; public const string TableOne = "TableOne"; public const string TableTwo = "TableTwo";
public SomeDataSet() { this.Tables.Add(TableOne); this.Tables.Add(TableTwo);
this.Relations.Add(RelationOne ...); } }
Så kan jeg bruge det sådan her :
SomeDataSet ds = new SomeDataSet(); someAdapter.Fill(ds);
foreach(DataRow dr in ds.Tables[<tablename>].GetChildRows(SomeDataSet.RelationOne)) { // et eller andet. }
faktisk har jeg også ofte tabellerne i koden - således at jeg ville have en :
public class TableTwo : Table { ... diverse - hvad der nu synes hensigtsmæssigt f.eks. : public const string Id = "Id"; }
Resultatet er så, at jeg kan gøre sådan her :
foreach(DataRow dr in ds.Tables[TableOne.TableOneName].GetChildRows(SomeDataSet.RelationOne)) { int id = (int)dr[TableTwo.Id]; }
...
Det er ikke altid jeg gør sådan, men hvis jeg gør det ender jeg gerne med at være ret glad for det, selvom det giver lidt ekstra kode... Der bliver sådan en dejlig kompilerkontrollet adgang til tabellerne, og der er ikke det vanlige overhead ved typed datasets.
OK,...det vil sige at du mere eller mindre definere nye specialiserede DataSet's DataTable's etc. så de er skrædersygede til dit forretningslag ???
Dvs. at jeg eksempelvis ville lave et dataset til "Club" alá:
public DataSetClub : DataSet { public const string RelationOne = "REL club_cours"; public const string TableOne = "club"; public const string TableTwo = "course";
public SomeDataSet() { this.Tables.Add(TableOne); this.Tables.Add(TableTwo);
this.Relations.Add(RelationOne ...); } }
...og var det en DataTable, ville det så være det bl.a være kolonner etc jeg ville ligge i en "DataTableClub : DataTable" klasse...
Giver dig helt ret i at det virker meget godt at have det hele samlet - pt. er jeg nemlig MAX irreteret på mig selv over at jeg manuelt skal opbygge diverse DataTables til de forskellige klasser (tabeller), når jeg løbende skal bruge dem.. pisse irreterende !!!
Gid jeg havde endnu en måned til at lave applikationen,...så havde jeg 100% rettet hele koden til....
Men du kan ikke lige se at der er noget galt med relationerne, vel ?? Alle de steder i koden, hvor jeg kalder ned til en DA (Data Access)-klasse oprettes der ganske enkelt en ny tabel, der smides ind i det parameteroverførte oDataSet, og sender det opdaterede (med f.eks. en SELECT * FROM club-tabel) retur til metodekaldet:
DACourse oDACourse = new DACourse(); oDataSet = oDACourse.getSelectedCourses(arrayOfClubs, oDataSet, out arrayOfCourses);
Det er simpelthen for sort (og dog ikke alligevel - jeg skal jo passe på hvad jeg siger,...det er ris til egen røv) ;-) , at den kun skifter imellem 3 forskellige ID-numre - alt afhængigt af hvilken bane der er valgt... (og det ID den viser har INTET at gøre med primærnøglen i "Courses"-tabellen !! ???
Hehe... jeg kender godt fornemmelsen .... man kan nogle gange blive rigtig rigtig træt !
Men ja... noget i den stil... Jeg ville nok sørge for at lave en navngivning der gav lidt "genkendelsens glæde" med intellisense alá :
public DataSetClub : DataSet { public const string ClubCourseRelation = "REL club_cours"; public const string Club = "club"; public const string Cource = "course";
public SomeDataSet() { this.Tables.Add(ClubTable); this.Tables.Add(CourseTable);
this.Relations.Add(ClubCourseRelation ...); } }
Men jeg kan ikke umiddelbart se noget ballade i dine relationer, men det ville også kræve at jeg kunne se din tabeller - eller de selects/procedurer du bruger.
Jeg vil gerne hjælpe yderligere (i det omfang jeg kan), men det har været en lidt lang dag, så jeg vil dampe i seng.
Jeg er nok først ved et klaver igen relativt sent imorgen :o(
Håber du får det til at snurre på en eller anden måde !
snepnet,...jeg er desværre nød til at smutte - skal nå den sidste bus hjem. Men regner stærkt med at du har fisket problemet, når jeg logger på derhjemme om små tre kvarter ;-)
men hvis du er på vej til køjs, må vi jeg bare tage den op imorgen (hvis du har lyst)
Jeg fandt du hvad problemet var. Jeg har jo ét overordnet DataSet, hvortil jeg "importerede" data fra mine "Club", "Course", "Course_Hole" og "Hole" tabeller i databasen (altså til tilsvarende tabeller i DataSet'et).
Alle tabel-data er hentet via en seperat "SELECT * FROM <tabel>", og jeg lavede derefter relationer imellem tabellerne.
Jeg troede derfor at når en bruger havde valgt en given "Course", at jeg så kunne hente de pågældende, relaterede poster ud fra "Course_Hole" (og i sidste ende også, Hole) vha min relation: // index på den "Course/bane" der er valgt i min dropdown: index_number = ddCoursesOfClub.SelectedIndex;
// Henter ud fra ovenstående de relaterede "Course_Hole" rækker: DataRow[] child_rows; child_rows = oDataSet.Tables["course"].Rows[index_number].GetChildRows("<min relation imellem courseOGcourse_hole>");
...problemet var så bare, at jeg hvis jeg havde hentet mere end én Klubs data ned, ville index-nummeret i min dropdown, ikke svare til det index-nummer der jo ville figurerer i selve min DataTable - den indeholder jo "SELECT * FROM..."
Så lige nu prøver jeg at lave en manuel "master-detail" ved at jeg stadig har min "SELECT *..." tabeller, men så i stedet bruger min DataTable's Select()-metode...
For nu har jeg ledt i efter en måde at kalde GetChildRows() og GetParentRows() på vha af selve ID-nummeret på den rækker jeg ønsker at finde children eller parents til,...men jeg har ikke rigtig kunne finde noget endnu ??!! Ved du om det muligt ???
Har lige et/to/tre andre spørgsmål i forbindelse med din "specialiserede-løsning" med DataSet's og DataTables.
1) Hvis jeg ønsker at opretter en tabel svarende til min "Course" tabel i databasen, hvordan opretter jeg så det helt præcist mht. kolonner etc.. - er det noget alá:
public TableCourseHole() { this.columnCourse_id = new DataColumn("id", typeof(Int32)); this.columnId = new DataColumn("course_id", typeof(Int32)); this.columnHole_id = new DataColumn("hole_id", typeof(string)); this.columnHole_no = new DataColumn("hole_no", typeof(Int32)); this.columnHole_handicap_index = new DataColumn("hole_handicap_index", typeof(double)); } ...
2) Til din kommentar 20/10-2004 23:36:18 >> Vil det sige at du højest har én relation pr. DataSet eller...? For jeg kan ikke lige se hvordan fanden man så får styr på relationerne. (F.eks. hvis din TableTwo har en relation til en evt. TableThree og TableFour,..og de derudover re relateret til TableFive etc... er det ikke skruen uden ende ??
c = this.Columns.Add(SomeString, typeof(string)); c.AllowDBNull = false;
osv... Id og SomeString kunne så været at par af dine konstanter.
Og hvad det med relationerne angår... så har jeg de relationer der er nødvendige :o) (fedt svar ikke !)... Så længe man navgiver fornuftigt har jeg ikke været ude for det blev et problem (men det kan være jeg har misforstået dig ?).
mvh (jeg smider lige et svar hvis du på et tidspunkt vil lukke spm)
de relationer der er nødvendige... hehe :o) Tjooo,..det kunne jeg jo næsten gætte mig til - men jeg går så ud fra at du har ét DataSet pr. side - eller hvad ?
Har du eksempelvis aspx-siderne, houses.aspx og cars.aspx, hvor den henholdsvis vil liste huse og biler for brugeren (tænkt eksempel selvfølgelig),..så vil de have ét DataSet for hver enkel side - og her vil du så oprette de relationer der nødvendige i forbindelse med visningen af dataene på de enkelte sider.
anyway - du skal have 1000 tak fopr din tid,...og svarene ;o)
jeg kan ikke sådan helt præcist sige hvordan jeg ville gøre det i enhver situation.... jeg synes ofte der er flere sider der i vid udstrækning gør brug af de samme data, så der vil være datasets der danner grundlag for mange sider. der er også forhold omkring hvorvidt man vægter at have få datasets man "altid kan regne med", eller hvorvidt man vægter at have fuldstændig tilpassede minimums-dto'er af performancehensyn, eller måske endda fordi man ikke har tid til at programmare en masse gui, og derfor vælger at tilpasse datagrundlaget så gui-en viser det den skal - fordi det er det der er. der er rigtig mange forhold der spiller ind synes jeg.... nogle gange er det jo også bare nemmere/billigere at snuppe en eller anden O/R mapper, og så bare leve med de muligheder den giver, og så indordne sig lidt under det :o)
mvh
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.