05. april 2005 - 08:42Der er
41 kommentarer og 2 løsninger
Hjælp til metode
Hej Eksperter
Jeg er gået i stå i en opgave, den er nok let nok:
Jeg har tre klasser: DataHandler (til oprettelse af databasen, og indeholdende main), Ansat (med atributterne aId, aEfterNavn, aFornavn, aDato, aAfdId - svarende til kollonerne i databasen, id, fornavn, efternavn, dato, afdId) og det samme gør sig gældende med Afdeling (afId, afNavn, afBy henholdsvis id, navn, by). Ansat og Afdeling klasserne har "kun" get og set.
Jeg skal nu lave en public metode i min DataHandler klasse der ser således ud:
Ansat GetAnsat(aId)
Hvordan gør jeg det?
Når jeg skal teste det, skal det testes i en consol app. Her er det meningen at når man indtaster den ansattes id, at den pågældende ansatte returneres (fra databasen). Hvordan gør jeg det?
Virksomheder er på vej fra store sprogmodeller, der svarer på spørgsmål, til AI-agenter, der kan udføre opgaver på egen hånd. Det gør teknologien mere nyttig – og langt mere risikabel.
du laver en connection du laver en command med en select du laver en data reader med ExecuteReader du laver en Ansat med at agive data fra readeren som argumenter til constructor (eller med en tom constructor og så sætte properties en af gangen) du lukker diverse du returnerer Ansat objektet
public void GetAnsat(int aId) { OleDbCommand comm = new OleDbCommand("SELECT efternavn, fornavn, dato, afdid FROM tblAnsatte WHERE (id = "+ aId +")", this.conn);
bortset fra det første punkt med connection (jeg går ud fra at der er en intern connection i hans DataHandler-klasse man kan bruge), svarer din liste vist 100% overens med min kode - og nej, jeg havde ikke set dit indlæg :P
og hvorfor bør der ikke være det? hvis man har lavet en klasse der wrapper omkring de database-specifikke klasser vil det da skabe mindst overhead at have en connection som field, da dette object jo netop vil blive brugt i så og sige alle metoderne i klassen.
Eneste problem man kan løbe ind i er hvis man bruger samme DataHandler-object i flere tråde, men der bør man oprette en ny DataHandler til hver tråd.
en void metode der returnere en ansat? bare mig eller? :P
En helt anden ting... din Ansat klasse skal da vel ikke have et Afdelings ID? det du ender i der er at linke Objekter på ID'er... det går ikke, så den skal vel nærmere tage en Afdeling...
Så:
public class Ansat { private int aID; //Du bør også overveje om denne att er nødvendig... private string aEfterNavn; private string aFornavn; private string aDato; private Afdeling aAfd; ... }
public class Afdeling { private int afId; //Bør igen overveje denne att. private string afNavn; private string afBy; ... }
Og så ellers en klasse der holder styr på disse... Singleton fx...
dog kan jeg ikke se hvorfor at et klasse der mapper til en tabel i databasen ikke skal have et id-field. Det vil give en masse problemer hvis den ikke havde, for hvordan ville du da ellers kunne opdatere en ansat f.eks. ?
by the way, så er et field og en attribut ikke det samme. En private variabel der har hele klassen som scope kaldes for et field.
>>Cyberfessor Hvis jeg gør som du skriver, så har jeg ikke mulighed for at få Id, jeg har kun aId, når jeg skal a.Id...
så jeg har metoden: public Ansat GetAnsat(int aId)
Og her siger jeg efter så: Ansat a = new Ansat(7, "Hansen", "Hannah", system.DateTime.Now, 3);
Og så i min main skriver: console.write("Indtast ansattes id: "); aid=Console.ReadLine(); data.GetAnsat(7);
Men her kommer den ud og siger at den ansatte ikke findes, hvorfor? Og hvordan kan jeg undgå at hardkode GetAnsat(7) men rent faktisk hente den ansatte som brugeren taster id'et på?
public void GetAnsat(int aId) { OleDbCommand comm = new OleDbCommand("SELECT efternavn, fornavn, dato, afdid FROM tblAnsatte WHERE (id = "+ aId +")", this.conn);
ok, men nu når jeg i consolen indtaster et id på en ansat som eksisterer, sker der ikke noget - den skal udskrive den ansattes oplysninger i consolen, hvordan det? Den breaker fint når jeg indtaster et id, der ikke eksisterer...
Fordi .NET har indbygget connection pool. Hele ideen med en sådan er at man kun låner connection mens man har brug for den.
Hvis man holder på connection, så skalerer ens kode ikke, fordi man kan risikere at få flere DataHandler instanser end databasen understøtter connections. Og hvis man skriver sin DataHandler klasse til at håndtere det så har man reelt skrevet sin egen connection pool oven på .NET connection pool.
problemt er at hvis jeg gerne ville have aId med (der hvor jeg læser hvad man indtaster) så kan jeg ikke se at aId og id er det samme her, vel?
og hvis jeg skriver Ansat a = new Ansat (aId, reader.GetInt32(0), reader.GetString........ derudaf, hvor reader.GetInt32 refererer til id (og ikke aId), så har jeg for mange argumenter 6 (og der skal kun være 5).
okay, så kommer jeg til det problem jeg startede ud med..
jeg har: Ansat a = new Ansat(aId, reader.GetString(1), reader.GetString(2), reader.GetDateTime(3), reader.GetInt32(4));
Når man så taster et aId som eksisterer skriver den ikke den ansattes info ud på skærmen - hvorfor ikke? Jeg har gjort som cf sagde: string aid = Console.ReadLine(); data.GetAnsat(int.Parse(aid));
svar : 05/04-2005 09:42:12 ; cyberfessor _____________________________________________________________________________________ Tror der er en masse ting du har misforstået ud fra det jeg skriver...
Normalt vil man ikke rive ID'er med op fra databasen til Objekter (Burde man vide) Men i nogle tilfælde kan de være nødvendigt... Der vil det dog så være pænere at serialisere sit objekt. tag et kig på fx Object Identifier Patterns...
Men mapning fra Object Orientere til Relationel er et problem som er maget omdiskuteret, og der er utallige måder at løse dette på...
Men nu var det jo afID på Ansat jeg sagde der 100% skulle fjernes, resten af ID'erne sagde jeg så vidt muligt... afID skal helt klart erstattes af private Afdeling afd;
Husk på vi ikke skal linke på ID'er men Referencer...
Singleton patternet vil du kunne tage i brug for at holde styr på dine Ansate, så den ville fx holde en Collection og metoderne AddAnsat og GetAnsat... (Delete og Clear evt)... og samme metoder for Afdelinger om man så vil have en eller flere Singletons eller benytte en anden metode...
Ellers vil dine objecter ligge og flyde og dermed kan du ikke få fat i dem... (Man holder ikke referencer i Presentations lag) (de vil naturligvis kun ligge og flyde til GC komemer forbi)
det er rigtigt at afdID ikke har nogen steder hjemme, det bør være en reference til en Afdeling-instans.
Dog har jeg lidt svær ved at se din harme over ID i sit object. Alle de OR-mappers jeg kender til er netop afhængige af at den postens primære nøgle i databasen bliver gemt i objectet, da det ellers ikke er muligt at indentificere posten i databasen igen.
Omkring singleton pattern kommer det nok meget an på ens arkitektur i programmet. Det er rigtigt, at hvis man har brug for en unificeret tilgang til sine ansatte og afdelinger er Singleton ikke nogen dum idé. Men det er nu heller ikke nogen ulovlighed at lave en static metode i sin Ansatte-klasse der returnerer en AnsatteCollection, ala det her
public class Ansat { public static AnsatCollection GetAll() { //Hent alle fra databasen //Opret n-ansatte objecter og tilføj til en collection //returner collection'en } }
AnsatCollection coll = Ansat.GetAll();
foreach (Ansat a in coll) { a.Salary = 100000; }
På den måde er det også muligt at lave forskellige kriterier for hvilke ansatte man har lyst til at hente ud. Ved et singleton-pattern er man tvunget til at have ALLE ens ansatte liggende i en collection, da man ellers ikke har mulighed for at hente nogle helt specifikke ansatte ud.
Men, ja... guidelines og arkitektur kan man snakke om fra nu af og til dommedag.
Rent teknisk er en attribut i .Net et object man kan sætte som egenskab til klasser og metoder
Eks.
[Developer("cyberfessor", "21")] public class Me {
[Obsolete("Don't use Hej; use Bye instead", true)] <-- dette er en attribut public void Hej { } }
Nu var atribut begrebet i forbindelse med alle programmeringssprog...
i .NET ville jeg også nok kalde en Attribut for et Field, og vise den som en Property...
Min Harme over ID hænger sammen med at det hurgtigt leder til at man resikere at benytte ID'er som det der kæder ting sammen... hvilket vil være en fejl...
ID'er er noget vil har i den Relationelle verden mens at vi har referencer i den ObjectOrienterede verden... og at man skal passe på med ikke at kede de 2 vernener for meget sammen, og der er andre måder at løse det på... fx med:
System.Runtime.Serialization
Desuden kan du også sagtens definere i en Singleton af den skal lede i databasen efter en ansat hvis denne ikke findes i din collection, det er et spørgsmål om kode...
Dit tilfælde er et alternativ, men jeg bryder mig mere om at bruge en Singleton som et "Library" frem for at skulle hen og have en mase Statiske samlinger og metoder...
Man skal bare passe på med de begreber, da man nemt kan misforstå hinanden når at man ikke bruger samme "regelsæt".
Så du efter dit hoved burde vi skrotte alle databaser og serialisere alle vores objecter istedet? :) Jeg vil mene man kun bør bruge serialisering når man skal pakke ens object ind for at overføre det, f.eks. over http eller sockets. Man bør ikke bruge Serialisering til at gemme oplysninger for senere at hente det frem igen, med mindre det er noget meget applikationsspecifikt. Baner i et spil f.eks. I et lille program der skal koble sig op mod firmaets oracle-database og hente nogle oplysninger ud hører serialisering jo ingen steder hjemme.
Jeg ved ikke hvor du har fået ideen om at jeg mener man skulle skrotte databaser???
Det var jo netop til Mapningen fra vores Objekter -> Records -> Objekter...
Men til sidst vil jeg faktisk poientere at du faktisk ikke altid har brug for noget af alt dette... konkret har jeg faktisk i alle de projekter jeg har været med til ikke haft behov for at smide ID på klasser for at smide ID på...
selv om du måske har et hav af klasser i en model er det faktisk nogle gange nok at du har en fast "forbindelse" mellem måske 2 klasser, og disse data er måske enda vigtig information i klassen... typisk har vi haft brug for nogle ID'er externt til systemet som en bruge så kan taste ind... det er oplysninger som:
CPR, Ordrenr, Stregkode, Timestamps+stationsid osv... alle sammen egenskaber og derfor tiladte...
Endnu en muligned er flere PK'er...
Du må også godt definere din PK til at bestå af flere koloner i din db... så længe du opnår en helt unik kombination... kunne være et Telefon nummer kombineret med et navn fx... Et tidspunkt kombineret med en placering...
En hovedregel er bare at et ID i en klasse helst ikke skal være der for ID'ets skyld... der er så måske tilfælde hvor dette ikke er muligt... men derfor sagde jeg også så vidt muligt undgå... frem for at gå ned i en tabel i en database og sige at nå... men Bruger tabel har {id, navn, addresse, telefon} så skal min Bruger klasse sQ også have dette...
en fast "forbindelse" mellem måske 2 klasser --> Refrace...
en fast "forbindelse" mellem klasser og tabeller (records og objekter) i meget få (måske kun 2 fx) af dine klasser
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.