Avatar billede hald. Nybegynder
20. oktober 2004 - 21:50 Der 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.

DataRow parent_row;

parent_row = oDataSet.Tables["course_holes"].Rows[index_number].GetParentRows("REL course_holes-holes",DataRowVersion.Original);
       

...men den fucker umådeligt meget med mig... er jeg forkort på den ?

/hald
Avatar billede snepnet Nybegynder
20. oktober 2004 - 21:58 #1
Nej slet ikke... men der er lige et par småting :

GetParentRows returnerer et array af rows, så du skal lave en :

DataRow[] parents =
oDataSet.Tables["course_holes"].Rows[index_number].GetParentRows("REL course_holes-holes",DataRowVersion.Original);

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.
}

Håber det var ok :o)

mvh
Avatar billede snepnet Nybegynder
20. oktober 2004 - 21:59 #2
(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).
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:05 #3
Hej Snepnet !
Jeg har prøvet med noget af det samme, men det vil sgu ikke som jeg vil. Jeg har f.eks. prøvet netop med et array af DataRows i stedet:

DataRow[] parent_rows;

parent_rows = oDataSet.Tables["SELECTEDcourse_holes"].Rows[index_number].GetParentRows("REL SELECTEDcourse_holes-SELECTEDholes",DataRowVersion.Original);

DataRow oDataRow;
foreach(DataRow row in parent_rows)
{
    oDataRow = oDataTable.NewRow();
    oDataRow.ItemArray = row.ItemArray;   
    oDataTable.Rows.Add(oDataRow);   
}



...og så har lavet en tabel til at gemme rækken,...men er det ikke lidt overkill??

DataTable oDataTable = new DataTable();

oDataTable.Columns.Add(new DataColumn("ID",    typeof(Int32)));
oDataTable.Columns.Add(new DataColumn("course_id",typeof(string)));
oDataTable.Columns.Add(new DataColumn("hole_id",typeof(string)));
oDataTable.Columns.Add(new DataColumn("hole_no",typeof(Int32)));
oDataTable.Columns.Add(new DataColumn("hole_handicap_index", typeof(double)));


...men selv om jeg kan se (i debuggeren) at den finde det ene hit jeg er interesseret i, kan jeg fandme ikke få fat i selve id-værdien.
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:12 #4
hvordan ligger jeg værdien af de forskellige kolonner ind i f.eks. et array... Har prøvet, men igen - den fucker lidt med mig.
Avatar billede snepnet Nybegynder
20. oktober 2004 - 22:14 #5
det var da træls.... har du prøvet den "direkte" :

int id = 0;

foreach(DataRow row in parent_rows)
{
  id = (int)row["id"]; // altså hvis kolonnen hedder id
}

hvis det er en string eller andet end en int, kan du også prøve med :
id = int.Parse(row["id"].ToString()); // altså hvis kolonnen hedder id

mvh
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:33 #6
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

...Crap !!!

relationerne
Avatar billede snepnet Nybegynder
20. oktober 2004 - 22:35 #7
må jeg se hvordan du opbygger dit dataset ?
(eller i hvert fald hvordan du indsætter relationerne)
mvh
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:36 #8
Snepnet,...hvordan ville du lave relationerne - hvis vi tager udgangspunkt i de tre ovenstående tabeller?

du får lige hvordan jeg selv har lavet dem... 2 sek
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:37 #9
2 mennesker én tanke ;-)
Avatar billede snepnet Nybegynder
20. oktober 2004 - 22:37 #10
:o)
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:46 #11
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);


BL Hole:
---------------------------
DAHole oDAHole = new DAHole();
oDataSet = oDAHole.getSelectedHoles(arrayOfCourseHoles, oDataSet);
Avatar billede hald. Nybegynder
20. oktober 2004 - 22:48 #12
Hvis du har et foreslag eller du kender normale standarder til at navngive relationer i .NET, må du (som du jo nok kan se) MEGET gerne sige til... ;-)
Avatar billede snepnet Nybegynder
20. oktober 2004 - 23:05 #13
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.

mvh
Avatar billede snepnet Nybegynder
20. oktober 2004 - 23:06 #14
Hov denne
public class TableTwo : Table

Skulle selvfølge lige have været
public class TableTwo : DataTable

(jeg har bare skrevet det herude, så der kan godt være flere kludderier)
Avatar billede hald. Nybegynder
20. oktober 2004 - 23:17 #15
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 !!!
Avatar billede hald. Nybegynder
20. oktober 2004 - 23:23 #16
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);

...Hmmm
Avatar billede hald. Nybegynder
20. oktober 2004 - 23:28 #17
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 !! ???


Jeg kyler snart den skærm ad helv..... til :-(
Avatar billede snepnet Nybegynder
20. oktober 2004 - 23:36 #18
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 !

mvh
Avatar billede hald. Nybegynder
20. oktober 2004 - 23:38 #19
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)

Stort colgate-smil
/Hald
Avatar billede hald. Nybegynder
20. oktober 2004 - 23:40 #20
hehe... yes sir - sov godt ;-)
Avatar billede snepnet Nybegynder
21. oktober 2004 - 08:30 #21
:o)
hej igen... jeg er heller ikke ved klaveret i dagtimerne idag, men bare skriv så kigger jeg når jeg er online igen.
vi skrives ved
mvh
Avatar billede hald. Nybegynder
22. oktober 2004 - 12:35 #22
Hej igen, Snepnet

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 ???
Avatar billede hald. Nybegynder
22. oktober 2004 - 12:48 #23
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 class TableCourseHole : DataTable
{
private DataColumn columnId;
private DataColumn columnCourse_id;
private DataColumn columnHole_id;
private DataColumn columnHole_no;
private DataColumn columnHole_handicap_index;

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 ??

3) ...det blev vist jkun ved det to ;-)
Avatar billede hald. Nybegynder
22. oktober 2004 - 13:34 #24
1) >> Så lige at jeg lige manglede at oprette det så ubetydelige DataTable-objekt ;-) men nu fungerer mine typed-tables i det mindste.
Avatar billede snepnet Nybegynder
22. oktober 2004 - 14:18 #25
hej igen :o)

mht. tabellen, så kunne du i kontruktøren lave sådan noget her :

DataColumn c = this.Columns.Add(Id, typeof(int));
c.AllowDBNull = false;
c.AutoIncrement = true;
c.AutoIncrementSeed = 0;
c.AutoIncrementStep = -1;
   
DataColumn[] pKeys = {c};
this.PrimaryKey = pKeys;       
       
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)
Avatar billede snepnet Nybegynder
22. oktober 2004 - 14:18 #26
(hov.... og her var svaret :o)
Avatar billede hald. Nybegynder
22. oktober 2004 - 14:34 #27
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)
Avatar billede snepnet Nybegynder
22. oktober 2004 - 16:56 #28
hej igen :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
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester

IT-JOB

Lægemiddelstyrelsen

Løsningsarkitekt

Banedanmark

Systemarkitekt

Forsvarsministeriets Materiel- og Indkøbsstyrelse

Sektionschef til Enterprise Arkitektur i Forsvaret på Østerbro

Netcompany A/S

Managing Architect