Avatar billede mikkelk Nybegynder
01. december 2005 - 22:26 Der er 21 kommentarer og
1 løsning

Objekter og databaser

Hej Alle

Jeg er ret ny indenfor objektorienteret programmering og ASP.NET og sidder lige nu og tumler med nogle tanker om hvordan man laver de ting jeg tidligere har lavet i ASP om til objektorienteret .NET...
Og her gik jeg så i stå ved hele forbindelsen mellem objekterne og databasen.
Hvis jeg f.eks. har en portal, hvor jeg har nogle brugere, så ville jeg umiddelbart mene at det var smart at have en bruger-klasse? Men hvordan skal denne klasse så designes når den skal forbindes med en database?
Man kunne jo selvfølgelig i constructoren hente alle data om brugeren i databasen og så sætte nogle attributter til at indeholde disse data og så arbejde videre derfra, men det virker temmeligt voldsomt at skulle hente alle data ud, for f.eks. blot at ændre en attribut? Hvordan håndterer man sådanne ting smart?
Avatar billede snepnet Nybegynder
01. december 2005 - 22:41 #1
well... det er jo unægteligt et område der har trukket en del omtale i tidens løb :o)
som udgangspunkt er det du skriver en helt normal måde at gøre det på.
umiddelbart synes jeg det virker endnu mere vildt at håndtere opdatering af properties på en person enkeltvist.

desuden .... i din objektmodel (og for den sags skyld i domænet) vil din person være en helhed som det ville være uhendsigtsmæssigt at stå med en delmængde af (selvom du har ret i, at der self. godt kunne være noget effektivt i blot at sende den del man har ondt i til lægen... istedet for at skulle troppe op med alt hvad man har :o)

en smart løsning.... jeg synes at en or-mapper er en enkelt måde at fikse det på - f.eks. denne (der er mange):
http://sourceforge.net/projects/gopf

mvh
Avatar billede mikkelk Nybegynder
01. december 2005 - 22:52 #2
Hvis man så står og blot skal vise personens navn - så skal den hente alle properties for den person, for blot f.eks. at printe navnet. Og hver eneste gang man skal gøre dette skal alle data hentes ud af databasen - er det virkelig måden man gør det på?
Avatar billede mikkelk Nybegynder
01. december 2005 - 22:53 #3
Og - kan det lade sig gøre at få en kort forklaring på hvad en or-mapper er?
Avatar billede arne_v Ekspert
01. december 2005 - 23:26 #4
under normale omstændigheder er data til et objekt så små at databasen læser dem
fra disk i en enkelt read og typisk også vil kunne levere dem til et andet
system over nettet (hvis app og db er på forskellige systemer) i en enkelt
pakke

og så er der ingen performance forskel på et komplet objekt og en barberet
objekt

der er undtagelser - hvis du har en attached CLOB/BLOB i MB størrelse så
kan det nok godt betale sig at holde den seperat

der er også den lille pointe hvis vi har en 1:stort M relation, hvor du kan
få en liste med mange små objekter

de gode O/R mappere understøtter imidlertid lazy loading så den slags
først hentes når de skal bruges
Avatar billede arne_v Ekspert
01. december 2005 - 23:27 #5
O/R mapper = software som mapper mellen en objekt model (klasser) og relationalle
database tabeller
Avatar billede burningice Nybegynder
02. december 2005 - 13:38 #6
kan anbefale wilson ORMapper hvis man ikke har rodet med det før. Den er meget nem at gå til, og er non-intrusive ved din kode, dvs. at dine klasser skal ikke nedarve fra noget bestemt da det hele styres fra en xml-mapping fil.
Avatar billede mikkelk Nybegynder
02. december 2005 - 15:28 #7
Ok, det lyder jo som en god ide at bruge en ORMapper...
Men for bare lige at få det på plads, hvis nu man ikke vælger at bruge sådan en.

Hvis vi nu forestiller os at vi har følgende struktur:

    Forlag - Ansatte
      |
    Forfatter
      |
      Bog

Hvis man nu f.eks. skal have fat i et forfatter objekt - ville man så hver gang hente alle data ind i forfatter-objektet, samt populere hele rækken af bog-objekter? Et forlagsobjekt ville jo så resultere i at man skal læse stort set hele databasen over i objekter?
Avatar billede mikkelk Nybegynder
02. december 2005 - 15:41 #8
Hmm... man ville vel nærmere lave en metode i klassen forfatter der returnerer en liste over bøger, right? Så man kun henter boglisten, hvis den er nødvendig...

Så et lidt nyt spm.(håber det er ok)
Hvis man deler op i flere lag, data access, Business logic og presentation:
Ville man så i dataaccess lave en klasse for hver tilsvarende klasse i businesslogic - der har til opgave at hente data og sende det videre til business og tilsvarende gemme det igen.
Eller ville man f.eks. lave én skrive-klasse og en læse-klasse, og så have en metode for hver business logic-klasse der skal hente data?
Hvis i evt. kunne komme med links til nogle beskrivelser af hvordan man håndterer sådan en situation...
Avatar billede burningice Nybegynder
02. december 2005 - 16:13 #9
nej.. altså.. du har en Forfatter-klasse der deri indeholder en Bøger-property som returnerer en liste af Bog-objecter.

De fleste OR-mappere understøtter LazyLoad (inkl. Wilson ORMapper), der betyder, at selvom du opretter en instans af en forfatter, så vil alle bøgerne fysisk først blive hentet fra db når du forespørger på dinForfatter-Bøger propertien.

Ang. konkret implementation foretrækker jeg følgende:

Alle klasser der repræsenterer data fra database implementerer et Interface, ie. IDataObject. Dette interface indeholder en Property og to metoder:

int ID {
  get;
}

void Persist()
void Delete()

Din konkrete Persist vil så se sådan her ud:

if (this.ID == 0) {
  ObjectSpace.StartTracking(this, InitialState.Inserted);
} else {
  OjbectSpace.PersistData(this)
}

Når du så vil oprette et ny forfatter object er det bare at skrive

Forfatter f = new Forfatter();
f.Navn = "hej";
f.Køn = "Mand";
f.Persist();

Du kan så have en RetreiveByName-metode der ser sådan her ud:

static Forfatter RetrieveByName(string name) {
  OPathQuery qry = new OPathQuery(typeof(Forfatter), "Navn= ?");
  return (Forfatter)ObjectSpace.GetObject(qry, name);
}

Så hvis du vil ændre navnet på en bestemt forfatter kan du:

Forfatter f = Forfatter.RetrieveByName("Jens");
f.Navn = "Mads";
f.Persist();

Omkring dine lag vil følgende nok være en passende beskrivelse

UI. ASPX/ASCX
Business. Dine data-klasser (Forfatter, Bog, Forlag m.m.)
Data. ORMapperen. I mit eksempel; ObjectSpace som er navnet på Wilson ORMapper.
Avatar billede mikkelk Nybegynder
02. december 2005 - 16:39 #10
Ja, ok... men jeg spurgte jo netop til, hvad nu hvis man vælger ikke at benytte en ORMapper...
Avatar billede burningice Nybegynder
02. december 2005 - 16:51 #11
det samme... dog skal du selv skrive en masse sql i dine Persist(), Delete() og Retrieve-metoder.
Avatar billede mikkelk Nybegynder
02. december 2005 - 16:56 #12
Du vil altså i såfald placere sql i en Persist-metode i det objekt der er tale om - hvilket vel strider mod opdelingen i Business og data?
Avatar billede burningice Nybegynder
02. december 2005 - 17:34 #13
hvordan strider det mod opdelingen?

Du kan evt. lave en DataManager-klasse som internt indeholder en IConnection og nogle standard metoder til at snakke med databasen. Så bliver din Persist-metode til noget i denne retning

public void Persist() {
  DataManager dm = DataManager.Current;
  // evt. brug parametre
  dm.ExecuteCommand("UPDATE tblForfattere SET navn = '"+ this.Navn +"' WHERE id = "+ this.ID +");
}

En anden mulighed er at benytte attributer i dine businessobjecter og så, via reflection, bruge en datamanager-klasse til at opdatere værdierne:

public void Persist() {
  DataManager dm = DataManager.Current;
  dm.Persist(this);
}

men så er vi ovre i ORMapping igen, og så kan du lige så godt benytte en allerede lavet ORMapper.
Avatar billede burningice Nybegynder
02. december 2005 - 17:35 #14
evt. fjerne Persist fra dit BO-object og kalde dm.Persist fra dit UI-lag, men det er heller ikke pænt.
Avatar billede mikkelk Nybegynder
02. december 2005 - 17:47 #15
Nu handler det her ikke om at lave et konkret projekt der nødvendigvis skal munde ud i et superprodukt, men om at lære at skrive et ordentligt system - og det tror jeg på at man gør ved at lave mest muligt af det selv - og ikke benytte alt for mange færdige produkter der klarer det sure arbejde for en :-)
Derfor vil jeg egentlig gerne skrive koden uden en ORMapper til at starte med, selvom dette måske ikke er det smarteste - og så måske skrive skidtet om, så jeg benytter en ORMapper.
Derfor alle de dumme spørgsmål - det er altså ikke et forsøg på for en værd pris at komme uden om en ORMapper.
Avatar billede burningice Nybegynder
02. december 2005 - 20:47 #16
tja. det er selvfølgelig rigtig nok. Men så kan du også sige, at så ikke skrive i IL istedet for at benytte en compiler der klarer det sure arbejde for dig.

:)

Selvfølgelig et ekstremt tilfælde. Men nu hvor der også er kommet en OR Mapper med i .Net 2.0 frameworket vil jeg tro at det bliver mere og mere udbredt, og måden man gør det på. MS's 100% satstning på DataSettet som basis for al tilgang med databasen du'r bare ikke når man har et stort objektdomæne.

Så er der også de religionskrige der kører på om man bør bruge OR mappers (ORM) i det hele taget, og det er vel en smagssag på højde med SPROC (Stored Procedures) og D-SQL (Dynamisk SQL). Personligt foretrækker jeg D-SQL fremfor SPROC, samt ORM fremfor at skrive de trivielle persistens-procedurer.

Men den overordnede opbygning af dine BO'er bør indeholde en Persist og en Delete metode, som så internt gør de ting der skal til for at slette eller gemme state'n af dit object. Det kan være med en ORM eller kald direkte til ADO.Net eller en mellemliggende DataManager du selv laver der evt. har noget caching indbygget.

En sidste mulighed er at bruge en Object database istedet for Relationel database, det giver dog problemer når andre systemer skal hente data fra din database.
Avatar billede mikkelk Nybegynder
03. december 2005 - 12:18 #17
Nå ja, men nu er det C# og ASP.NET jeg gerne vil lære og ikke IL :-)

Anyway, har siddet og kigget lidt på denne: http://www.c-sharpcorner.com//Tutorials/Building3TierAppPA.asp
Her benytter de jo så direkte et data-objekt og et business-objekt for hver eneste objekt - er det en tåbelig måde at gøre tingene på?
Avatar billede mikkelk Nybegynder
03. december 2005 - 12:33 #18
Og forresten - DSQL? Har aldrig benyttet det? Hvor kan jeg læse lidt om hvad det er?
Avatar billede burningice Nybegynder
03. december 2005 - 20:49 #19
DSQL er egentlig bare når du skriver f.eks. sådan her i din kode:

string qry = "SELECT * FROM tblForfattere";
IDataReader = dinCmd.ExecuteReader(qry);

Alternativet er at bruge SPROC hvor alt SQL'en er defineret inde i databasen, og fra koden kalder du så bare nogle funktioner, de såkaldte Stored Procedures.
Avatar billede mikkelk Nybegynder
05. december 2005 - 17:08 #21
Mange tak for de mange gode kommentarer! Jeg har helt sikkert fået en langt bedre forståelse for hvordan man sammenkobler sin applikation med en database. Så er det bare igang med at øve sig :-)
Smid et svar alle jer der vil ha' point!
Avatar billede burningice Nybegynder
05. december 2005 - 20:09 #22
:)
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