complex database <-> classes probleem

Pagina: 1
Acties:
  • 106 views sinds 30-01-2008
  • Reageer

  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
Beste mensen,

Al een tijdje heb ik een probleem waar ik niet uit kom.
Dit betreft het ontwerpen van een methode om data uit een database op te slaan in classes, de data in de classes aan te passen en vervolgens weer op te slaan.

zie het zo:

ik heb een tabel (laten ze zeggen persoon) met wat velden (id (PK), naam, bsn nummer etc.)

nu kan ik een class maken die dezelfde velden heeft (eventueel laten genereren adhv de tabel), en deze middels een query vullen.

dan heb je een 1op1 van de tabel als class. Een record is dan een instantie van die class, en wanneer je
Persoon p = new Persoon(1) doet krijg je bijvoorbeeld een nieuwe instantie van het eerste record uit die tabel.

p.Save() slaat het record dan weer op.

tot zover is er niks aan de hand.


echter, stel nou dat ik twee tabellen heb, 'persoon' (zie hierboven) en bijvoorbeeld 'order' (id, persoonid, totaalbedrag, etc.)

Nu wil ik een lijst hebben met alle orders, en de naam van de persoon erbij.
Geen probleem zou je zeggen, dat wordt zoiets:
[sql]
SELECT `o`.*, `p`.naam`
FROM `order` AS `o`
INNER JOIN `persoon` AS `p` ON `o`.`persoonid` = `p`.`id`
[/]

echter.. in welke klasse ga je dat resultaat opslaan?
je hebt er geen klasse voor...


Nu zijn er een aantal dingen waar ik aan dacht, maar geen enkel idee lijkt compleet te werken.

oplossing 1

je maakt twee instanties van de twee klasses die je hebt (persoon en order) met daarin de waardes die je opgevraagd hebt.
echter, je hebt dan geen idee meer welke persoon er bij welke order hoort, en dus zul je ze moeten koppelen.
laten we zeggen de simpelste methode om dat te doen, is een tweedimentionale collectie van wat voor soort dan ook.
dus :
code:
1
2
3
4
[0][0] -> order1
[0][1] -> persoon1
[1][0] -> order2
[1][1] -> persoon2

echter, waar ga je die collectie opslaan, en hoe ga je ervoor zorgen dat de data die je hebt ook weer terug opgeslagen kan worden?
stel dat ik de naam van een persoon verander, en ik wil mijn persoon instantie opslaan, dan weet ik niet welk ID (de pk) mijn persoon heeft.

Enige manier om dit lekker te laten werken is dus van alle tabellen (ook in joins) altijd alle velden opvragen (of in ieder geval altijd de PK) en een inteligent systeem te maken dat aan de hand van een query weet welke velden er uit welke tabel komen.
dus dat je weet dat de eerste velden (tot de tweede 'id' kolom die je tegenkomt) bij de eerste tabel horen, vanaf de tweede id kolom tot de 3de bij de tweede tabel etc.

echter heb ik dan nog steeds geen idee hoe ik op een nette manier mijn koppeling tussen instanties van de klasses moet bewaren. (dus welke persoon aan welke order zit)

oplossing 2

Stel nou dat ik in plaats van allemaal 1op1 klasses te maken van tabellen gewoon zeg dat ik 1 klasse heb die in staat is om data uit allerlei tabellen op te slaan.

ik zou dan geen klasses hoeven genereren (of overtypen) en heb dus geen 1op1 relatie met een tabel.

Ik zou dan het hierboven beschreven probleem kunnen oplossen door een instantie te maken van die klasse (laten we hem 'QueryResult' noemen) en deze instantie de result te geven van een query.
ik zie de klasse dat een beetje zo voor me:

QueryResult
- record[]
- nrOfRows
- Original Query
- Execution time
- etc.

waarbij 'record' weer een collectie is van een andere class is die er ongeveer zo uit ziet:

Record
- tablename
- columnname
- value

Op deze manier kan je dus onze mooie join uitvoeren, en het resultaat in die objecten stoppen.
Echter ook hier zit weer een probleem aan dat ik niet helemaal kan oplossen.

Ten eerste heb je een slimme methode nodig om de tablename en de columnname op te vragen.
Bij een select * heb je namelijk aan de hand van je query geen enkel idee welke kolommen je opvraagd.
Echter, elk DBMS (dat je wilt gebruiken tenminste) retourneerd wel op de een of andere manier de opgevraagde kolommen.

Wanneer je dan data wijzigd in je klasse is het dus goed te doen om in je .Save() een methode te maken die adhv de tablename en columnname een update query uitvoert.

Echter, wat als je een nieuwe instantie wilt maken van een bepaald object, laten we zeggen 'persoon'
Ik kan in de tablename wel 'persoon' invullen, maar zou dit dan al uit me hoofd doen. Er is geen controlle of die 'persoon' tabel eigenlijk wel bestaat. Ditzelfde geld voor de kolommen. En de value's die je er in duwt kunnen van een compleet andere datatype zijn...

Natuurlijk valt dit met een aantal queries wel te controlleren, maar wanneer je dan veel nieuwe objecten aanmaakt blijf je queries schieten op de DB.


Verder is het zo dat je geen eigen methodes die specifiek voor die klasse zijn kunt toevoegen aan de klasse.
Stel dat ik een methode heb om uit te rekenen of een bepaalde persoon wel ouder is dan een bepaalde leeftijd, dan zou ik dit normaal in de Persoon klasse doen.
dus
code:
1
if (Persoon.CheckAge(16)) { /* do stuff */ }

Alleen heb ik geen Persoon klasse....
Erg lastig dus.




Weet een van jullie misschien een manier om te zorgen dat ik op een fatsoenlijke manier toch dit soort dingen kan doen?
Is er misschien een standaard oplossing voor?
hebben jullie zelf oplossingen?
oplossingen voor de problemen in mijn oplossingen? (:?)

deel het :)

This message was sent on 100% recyclable electrons.


  • Janoz
  • Registratie: Oktober 2000
  • Nu online

Janoz

Moderator Devschuur®

!litemod

Als er een persoon bij een order hoort kun je in de class order toch gewoon een referentie naar die persoon opnemen? Desnoods doe je dit twee kanten op. Bij een 1:N relatie betekent dat dat er in order een property persoon zit en in persoon zit een lijst met orders. In je data access layer kun je vervolgens deze structuur opbouwen. Wel zorgen dat je van 1 persoon maar 1 object hebt. Dat is simpel te doen door bij het uitlezen alle personen in een hashmap op te slaan (met id als key). Je hoeft dan alleen een nieuw persoon object uit je resultset te halen wanneer deze nog niet in de hashmap zit.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Oplossingen voor de 'object / relational mismatch' zijn er; er zijn diverse O/R mappers (al dan niet gratis) op de markt. ((N)Hibernate, Wilson OR mapper, LLBLGen, etc....)

https://fgheysels.github.io/


  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
whoami schreef op donderdag 03 mei 2007 @ 10:02:
Oplossingen voor de 'object / relational mismatch' zijn er; er zijn diverse O/R mappers (al dan niet gratis) op de markt. ((N)Hibernate, Wilson OR mapper, LLBLGen, etc....)
ik heb van Hibernate idd wel eens iets gehoord, maar het idee is een beetje om het zelf te ontwikkelen (of iig te ontwerpen)

Het is niet zo dat ik nu een structuur nodig heb om iets op te bouwen, ik ben gewoon benieuwd naar hoe dit probleem opgelost wordt.

Ik zal eens kijken of er van de systemen die jij noemt een soort van 'how it's done' documentatie is, want om in de sourcecode te loeren lijkt me wel enorm veel werk (zal geen paar regels zijn)
Janoz schreef op donderdag 03 mei 2007 @ 09:47:
Als er een persoon bij een order hoort kun je in de class order toch gewoon een referentie naar die persoon opnemen? Desnoods doe je dit twee kanten op. Bij een 1:N relatie betekent dat dat er in order een property persoon zit en in persoon zit een lijst met orders. In je data access layer kun je vervolgens deze structuur opbouwen. Wel zorgen dat je van 1 persoon maar 1 object hebt. Dat is simpel te doen door bij het uitlezen alle personen in een hashmap op te slaan (met id als key). Je hoeft dan alleen een nieuw persoon object uit je resultset te halen wanneer deze nog niet in de hashmap zit.
dat is idd een goed idee.

het nadeel is dus wel dat je dan niet een echte join uitvoert, maar dat je wel 'alle' kolommen van de bepaalde tabel opvraagd (wat opzich natuurlijk geen probleem is)

dus het zou dan zoiets worden:
Ik wil een lijst hebben van orders en personen, dan vraag ik van orders alles op, zie dat er een 'persoon_id' in zit (al dan niet door een database relatie of stukje naamgeving van kolommen), en haal dan (doordat die key er in zit) het bijbehorende record op van persoon.

op die manier is het wel nog steeds een 1op1 relatie, en kan ik beide records terug schijven in de DB.

Echter, een echte join is het niet. Wat je eigenlijk doet is gewoon per record van de order tabel de bijbehoorende persoon opzoeken (indien niet al in de hashmap)

Verder is het natuurlijk zo dat een persoon ook weer een kolom 'vader' en een kolom 'moeder' heeft, die weer verwijzen naar een ander record in persoon.

Deze wil je (meestal) niet hebben, en je zult dus ergens als zoekargument mee moeten geven hoe 'diep' je wilt querien, of het zelfs zo verzinnen dat je pas je query uitvoert als je de data opvraagd

dat laatste stel ik me zo voor:
stel je vraagt alle orders op. En op het moment dat je zegt
String naam = Order.Persoon.Naam
en 'Persoon' is nog null dat je dan pas de query gaat uitvoeren die Persoon vult.

Op deze manier kan je dus wel dynamisch bij je childs (order.persoon.vader.vader.moeder.naam ;)) maar voer je pas de query uit op het moment dat je de data echt nodig heb.


zoiets bedoelde je janoz?
(heb het een beetje uitgewerkt)

This message was sent on 100% recyclable electrons.


  • Janoz
  • Registratie: Oktober 2000
  • Nu online

Janoz

Moderator Devschuur®

!litemod

Je kunt het ook gelijk met de join doen. Als je toch weet dat je alle gegevens nodig hebt dan haal je doe op. Je hebt alleen een beetje extra logica nodig om je objecten juist te vullen. Die logica heb ik in mijn vorige post wel beschreven. In elke row zitten de persoonsgegevens ook al. Je moet alleen kijken of je bij het uitlezen van die resultset dat persoon al eens aangemaakt hebt. Als dat neit het geval is kun je de persoon gewoon aanmaken mbv de huidige row (dus niet met een nieuwe query)

Bij O/R mappers wordt trouwens vaak wel losse queries uitgevoerd. Ook hebben deze vaak een vorm van lazy objecten die pas uit de database gehaald worden wanneer ze nodig zijn. Het is iig redelijk complexe materie waar trouwens wel een heleboel over te vinden is.

[ Voor 55% gewijzigd door Janoz op 03-05-2007 11:06 ]

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
Ik weet nu tenminste hoe het heet (O/R mappers) dus zoeken zal nu wel een stuk beter gaan :)

edit:
een paar boeiende dingen:
http://en.wikipedia.org/wiki/Object-relational_mapping
http://dotnetjunkies.com/...D5-9C12-DE37E5984B5B.dcik
http://www.theserverside.net/news/thread.tss?thread_id=29071

[ Voor 57% gewijzigd door BasieP op 03-05-2007 11:39 ]

This message was sent on 100% recyclable electrons.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Nou, ik wil je niet ontmoedigen maar het bouwen van een goede O/R mapper kernel die een beetje werkt en veel features heeft waar je wat aan hebt daar ben je wel 1 a 2 jaar full time mee bezig. Je kunt na een half jaar flink doorprogrammeren wel een heel eind zijn hoor, maar veel features kosten gewoon een hoop tijd, bv recursive graph persistence, fk-pk syncing, prefetching ... om maar te zwijgen over de query taal die je gaat gebruiken.

HET document over o/r mapping is overigens dat van scott ambler
http://www.agiledata.org/essays/mappingObjects.html

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • Cavalera125
  • Registratie: December 2003
  • Laatst online: 26-11 07:25
Hoe snel is Hibernate eigenlijk in het ophalen van data, of eigenlijk het mappen van opgehaalde data naar objecten? Is het bruikbaar voor systemen waarbij response tijd zeer kritisch is, waar bijvoorbeeld 10ms een wereld van verschil is? Zorgt reflectie hierbij veer relevante vertraging?

  • stp_4
  • Registratie: Maart 2003
  • Laatst online: 29-11 18:01
Cavalera125 schreef op woensdag 09 mei 2007 @ 15:11:
Hoe snel is Hibernate eigenlijk in het ophalen van data, of eigenlijk het mappen van opgehaalde data naar objecten? Is het bruikbaar voor systemen waarbij response tijd zeer kritisch is, waar bijvoorbeeld 10ms een wereld van verschil is? Zorgt reflectie hierbij veer relevante vertraging?
In het bedrijf waar ik werk hebben we de verdere ontwikkeling van een applicatie m.b.v. NHibernate stopgezet omdat het veel te traag bleek te zijn in sommige situaties. Ook bleek het leggen van wat complexere relaties niet altijd even makkelijk en sommige features (van hibernate) waren in NHibernate nog niet geheel geimplementeerd (is alweer 2 jaar geleden dus kan veranderd zijn).

stp - PSN ID: stp_4


  • Standeman
  • Registratie: November 2000
  • Laatst online: 20:13

Standeman

Prutser 1e klasse

Cavalera125 schreef op woensdag 09 mei 2007 @ 15:11:
Hoe snel is Hibernate eigenlijk in het ophalen van data, of eigenlijk het mappen van opgehaalde data naar objecten? Is het bruikbaar voor systemen waarbij response tijd zeer kritisch is, waar bijvoorbeeld 10ms een wereld van verschil is? Zorgt reflectie hierbij veer relevante vertraging?
Reflectie is in principe duur proces en hibernate genereert natuurlijk enige overhead. Je kan een hoop tweaken en tunen, maar als 10ms een wereld van verschil is die je de kop kan kosten, zal ik een beetje gaan kijken naar andere oplossingen. Bijvoorbeeld naar een oplossing op maat in C, aangezien je daar meer in de hand hebt qua memory allocation.
Maar goed, ik ben dan ook niet echt een performance expert.

The ships hung in the sky in much the same way that bricks don’t.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Cavalera125 schreef op woensdag 09 mei 2007 @ 15:11:
Hoe snel is Hibernate eigenlijk in het ophalen van data, of eigenlijk het mappen van opgehaalde data naar objecten? Is het bruikbaar voor systemen waarbij response tijd zeer kritisch is, waar bijvoorbeeld 10ms een wereld van verschil is? Zorgt reflectie hierbij veer relevante vertraging?
Als 10ms al teveel is dan moet de weg van commando naar data naar result zo kort mogelijk zijn, dus je commando EN je data EN je result verlaten nooit dezelfde machine, dus alle code en alle data zit in de database engine. Dit omdat het transporteren van data van/naar een client altijd tijd kost en relatief veel tijd, alhoewel tegenwoordig de low-level libraries van clients wel redelijk goed zijn, maar je houdt altijd netwerk latency op die manier. Het hangt wel van de hoeveelheid data af natuurlijk. Als je veel data moet processen en het is tijdkritisch, dan is het wellicht zaak om de afstand tussen process logic en data zo kort mogelijk te houden. Een O/R mapper kan dan nog steeds wel helpen (bv de o/r mapper code in sqlserver draaiend) maar de winst die je haalt op development gebied verlies je weer aan die paar ms die je verliest aan performance. Wanneer performance KEY is, dan bevind je je hoedan ook op een glijdende schaal: er is geen limiet aan wat je nog kunt veranderen om meer performance eruit te persen. O/R mappers over het algemeen proberen via veel truuks en voorwerk ervoor te zorgen dat data zo snel mogelijk gefetched wordt, maar je bevind je altijd buiten de RDBMS dus de latency van de roundtrip verlies je altijd.

Verder gebruikt geen enkele goede O/R mapper reflectie icm property descriptors on fields/collections etc te zetten/getten, men doet 1 van de volgende 3 dingen:
1) men genereert code vooraf, en deze code is zo opgezet dat set/get acties op velden erg snel is
2) men genereert at runtime een zg. 'dyn. proxy' class, dit is een subclass van je feitelijke entity en deze class bevat code die ervoor zorgt dat het setten/getten van fields erg snel is, vooral omdat veel libraries die dit gebruiken eisen dat de properties virtual zijn.
3) men manipuleert de IL/bytecode post-compile time (of pre-startup) en voegt zo code toe aan de class die het setten/getten van fields erg snel maakt.

Ook kun je met wat IL gegenereert at runtime erg snel properties zetten. Via propertydescriptors is erg traag inderdaad, dat moet je ook niet doen (maar het vergt wel veel complexe code om het goed snel te krijgen)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • BasieP
  • Registratie: Oktober 2000
  • Laatst online: 19-10 08:18
EfBe schreef op zondag 06 mei 2007 @ 11:23:
Nou, ik wil je niet ontmoedigen maar het bouwen van een goede O/R mapper kernel die een beetje werkt en veel features heeft waar je wat aan hebt daar ben je wel 1 a 2 jaar full time mee bezig. Je kunt na een half jaar flink doorprogrammeren wel een heel eind zijn hoor, maar veel features kosten gewoon een hoop tijd, bv recursive graph persistence, fk-pk syncing, prefetching ... om maar te zwijgen over de query taal die je gaat gebruiken.
ik heb niet de intentie om zelf een O/R kernel te schrijven, ik wilde er gewoon iets meer van weten.

Verder wordt er op mijn werk gewerkt met een eigen geschreven tool, waar ik hier en daar al een aantal bugs ben tegengekomen.
Ik heb hierbij ook gemerkt dat niet alles opgelost kan worden zoals je graag wilt.
stp_4 schreef op woensdag 09 mei 2007 @ 15:21:
[...]


In het bedrijf waar ik werk hebben we de verdere ontwikkeling van een applicatie m.b.v. NHibernate stopgezet omdat het veel te traag bleek te zijn in sommige situaties. Ook bleek het leggen van wat complexere relaties niet altijd even makkelijk en sommige features (van hibernate) waren in NHibernate nog niet geheel geimplementeerd (is alweer 2 jaar geleden dus kan veranderd zijn).
probleem is dat je een keuze hebt tussen twee methodes met nadelen:

of je werkt met O/R mapping systeem (algemeen opgezet, en dus met veel functies)
of je werkt met een eigen pakket, waar waarschijnlijk meer onderhoud/ontwikkeling tijd in zit, waarbij je kan optimaliseren voor snelheid.

het bedrijf waar ik bij werk heeft gekozen voor het O/R mapping verhaal, alleen hebben dit zelf (deels foutief) geimplementeerd, waardoor de resultaten erg tegenvallen.
Echter in hun geval is het blijven gebruiken van die methode beter dan custom build zut, omdat er op zo'n snelheid ontwikkeld wordt dat het 'alles zelf doen' gewoon niet meer kan.

Verder verlies je met 'alles zelf doen' natuurlijk al heel gauw je lagen systeem (je bouwt queries, en voert checks uit op plaatsen waar je dit niet wilt)

This message was sent on 100% recyclable electrons.


  • Cavalera125
  • Registratie: December 2003
  • Laatst online: 26-11 07:25
BasieP schreef op woensdag 09 mei 2007 @ 19:30:
Verder verlies je met 'alles zelf doen' natuurlijk al heel gauw je lagen systeem (je bouwt queries, en voert checks uit op plaatsen waar je dit niet wilt)
Volgens mij kun je evengoed nog wel een duidelijke scheiding hebben tussen je DAL en businesslogic. De DAL is dan wel breder, je zult waarschijnlijk per object een objectmanager krijgen die zorgt voor de persistence. Wanneer je entities nauwelijks veranderen, toenemen of afnemen lijkt me dat opzich geen probleem. Pas als je vaak nieuwe entities krijgt, of oude moet wijzigen zal dit veel extra werk met zich meebrengen.
EfBe schreef op woensdag 09 mei 2007 @ 19:19:
Verder gebruikt geen enkele goede O/R mapper reflectie icm property descriptors on fields/collections etc te zetten/getten, men doet 1 van de volgende 3 dingen:
1) men genereert code vooraf, en deze code is zo opgezet dat set/get acties op velden erg snel is
2) men genereert at runtime een zg. 'dyn. proxy' class, dit is een subclass van je feitelijke entity en deze class bevat code die ervoor zorgt dat het setten/getten van fields erg snel is, vooral omdat veel libraries die dit gebruiken eisen dat de properties virtual zijn.
3) men manipuleert de IL/bytecode post-compile time (of pre-startup) en voegt zo code toe aan de class die het setten/getten van fields erg snel maakt.
Als ik het goed heb is dit het prototype pattern, toch? Hoe doet een O/R mapper dit? Geneert hij de eerste keer dat een object opgehaald wordt middels reflectie het object en wordt dit bij volgende requests gecloned?

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Cavalera125 schreef op woensdag 09 mei 2007 @ 22:10:
[...]
Als ik het goed heb is dit het prototype pattern, toch? Hoe doet een O/R mapper dit? Geneert hij de eerste keer dat een object opgehaald wordt middels reflectie het object en wordt dit bij volgende requests gecloned?
Volgens mij is het het dynamic proxy pattern maar die pattern namen ontschieten me nogal eens dus het kan best het prototype pattern zijn, al lijkt me een naam als 'prototype pattern' voor dit mechanisme wel wat raar.

Je roept in feite een factory aan. Die factory aanroep krijgt een type mee en die factory maakt dan een subclass van het type dat je hebt aangegeven en geeft een instance van die subclass terug. Dit cachet de factory natuurlijk zodat je de volgende keer gewoon weer een instance krijgt van die subclass. Dit wordt door ge-emitte bytecode/IL gedaan zodat je niet met trage code als Activator.CreateInstance() zit :)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Ik lees net deze post en ik had een ongeveer vergelijkbaar probleem. Ik heb het als volgt opgelost:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ZoekMe {
var $student;
function ZoekOrder() {  
        $query = sprintf("SELECT en de rest van je query );
        $result = mysql_query($query);
        while ($row = mysql_fetch_assoc($result)) {
            $order[]=$row['ordergegevens'];
            }
        mysql_free_result($result);
        $this->aantal=count($studentorders);  //je weet nu hoeveel orders er van een student zijn gevonden
        $this->studentorder=$order; // de orders worden een array
        }
}

$query = sprintf("SELECT studentnaam FROM studenten");
    $Studs = $conn->SelectLimit($query) or die($conn->ErrorMsg());
    $Studenten = $Studs->GetArray();
$teller = count($Studenten); // het totale aantal gevonden studenten

for ($i2=0;$i2<$teller;$i2++) { we gaan nu alle studentnamen invoeren in de query van class ZoekOrder
$$studentnaam=$Studenten[$i2][0];
${'studentnr'.$i2} = new ZoekOrder;
${'orderaantal'.$i2} = ${'studentnr'.$i2}->aantal; // je hebt nu het aantal orders
${'order'.$i2} = ${'studentnr'.$i2}->studentorder;
}

Nu hebben we 3 zaken gevonden:
een variabele gebonden aan de studentnaam; $$studentnaam
een array met alle orders van student met id x : $orderx
een variable $orderx waarin het aantal orders van de student staat.

Door te spelen met x kun je de verschillende arrays doorlopen en omdat ze in het geheugen staan gaan de bewerkingen snel.


De vraag is alleen: Was het een goede oplossing?

[ Voor 4% gewijzigd door Verwijderd op 05-06-2007 17:08 ]


  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 30-11 15:10

Creepy

Tactical Espionage Splatterer

Het feit dat je met {} en $$ aan het werken bent zou al behoorlijke alarmbellen moeten laten rinkelen. Dat alleen al maakt het voor mij geen goede oplossing. Er zullen vast wel voorbeelden zijn waarom variabele variabelen handig kunnen zijn, maar dit is er naar mijn idee geen voorbeeld van.

Daarnaast mis ik het totale idee maar dat zou wel eens kunnen liggen aan mijn gebrekkige kennis van OO in PHP waar je nu zo te zien ook wat rare fratsen mee uithaalt of nogal wat weglaat (als in: je hebt een methode ZoekOrder die je blijkbaar als constructor wilt gebruiken (new ZoekOrder) :? )
Daarnaast lijkt altijd 1 query per student me nu ook niet zo handig.

Zo te zien ga je de array's aleen als cache gebruiken? Een O/R mapping (of een O/R mapper) houdt meer in dan dat alleen.

Edit: om maar te zwijgen wat er gebeurd als er studenten zijn met dezelfde naam ;)

[ Voor 13% gewijzigd door Creepy op 06-06-2007 11:24 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Verwijderd

D'r mist idd nog al wat, maar dat komt omdat mijn originele code flink groter is en ik heb gepoogd alleen de essentiele dingen hier neer te zetten.

Het idee is om elke student (in plaats van zijn naam zou je zijn unieke ID kunnen) een array aan orders te genereren en die kun je dus gebruiken voor verdere bewerkingen.

Het klopt dat de variabele variabelen discutabel zijn, maar dat is ook waarom ik mijn "oplossing" poste. Ben er nog steeds niet uit hoe ik het anders kan oplossen.

  • Boss
  • Registratie: September 1999
  • Laatst online: 16:27

Boss

+1 Overgewaardeerd

Ik weet niet in welke taal je bezig bent, maar ik heb een vergelijkbaar model gemaakt in Delphi. Daar kan je gewoon objecten in een TObjectList plaatsen. In dat geval heeft een TPersoon een property TOrders, dat een afgeleide is van TObjectList (nouja, geen afgeleide dan... een composite met een TObjectList).

Dat werkt prima. Ieder object heeft een ID, en zo kan ik bij het inlezen/wegschrijven weer de database-koppeling leggen tussen de objecten.

The process of preparing programs for a digital computer is especially attractive, not only because it can be economically and scientifically rewarding, but also because it is an aesthetic experience much like composing poetry or music.


  • labee
  • Registratie: November 2002
  • Laatst online: 10-09-2022
Kijk eens naar LINQ

Hier is een WebCast te vinden (skip de eerste 4 minuten) die uit te doeken doet wat je allemaal met LINQ kan. LINQ to SQL is het onderdeel dat je nodig hebt.

http://msevents.microsoft...1032334431&CountryCode=US

LINQ zit in .NET Framework 3.5 die in Visual Studio 2008 (Orcas) zit.
Visual Studio 2008 en framework 3.5 zijn beide nog in de Beta fase dus hou daar nog even rekening mee maar LINQ bied wel DE oplossing die je nodig hebt.

http://www.labee.nl


  • EfBe
  • Registratie: Januari 2000
  • Niet online
labee schreef op zaterdag 16 juni 2007 @ 01:36:
Kijk eens naar LINQ

Hier is een WebCast te vinden (skip de eerste 4 minuten) die uit te doeken doet wat je allemaal met LINQ kan. LINQ to SQL is het onderdeel dat je nodig hebt.

http://msevents.microsoft...1032334431&CountryCode=US

LINQ zit in .NET Framework 3.5 die in Visual Studio 2008 (Orcas) zit.
Visual Studio 2008 en framework 3.5 zijn beide nog in de Beta fase dus hou daar nog even rekening mee maar LINQ bied wel DE oplossing die je nodig hebt.
Iedere O/R mapper biedt de oplossing. Het is echt niet zo dat nu Linq er is er ineens iets mogelijk is wat daarvoor niet door iemand voormogelijk werd gehouden... ookal wil MS je anders doen geloven. Linq is gewoon een DSL die ze gemerged hebben met C# en VB.NET en dat op een niet al te beste manier, maar goed, beter dan niks (qua taal constructie). Over linq to sql.... laat ik me daar niet over uit laten ;)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Verwijderd

Ik merk in deze thread dat er al gelijk veel te veel naar de data laag geleund wordt. Een veel voorkomende ontwerp fout die programmeurs maken is beginnen met je data model... Dit kan een vak appart zijn, maar het ontwerpen van je bussines laag is ook een vak appart!

Je bussines laag ontwerp je a.d.h.v. use-cases. Welke gegevens wil je gebruiker zien op het scherm? welke relaties moeten zichtbaar zijn en op welke manier gaat hij hier mee om. Aan de hand van DIE use-cases bouw je je bussines objecten.

Daarna ga je kijken hoe je je goed genormaliseerde data kan 'mappen' naar je bussines objecten. En uiteraard gaat het dan voorkomen dat je joins moet leggen, of meerdere inserts/updates moet uitvoeren voor één save actie.

Rockford Lhotka (http://www.lhotka.net/) heeft een aantal boeken over het CSLA framework, waarin in de eerste paar hoofdstukken dit principe ook wordt uitgelegd. Zeer interresant om eens te lezen.

Het heeft mij in ieder geval geholpen om niet meer in de hokjes van relationele data te denken, maar meer naar de kant van de gebruiker te leunen tijdens het ontwerpen van een goede bussines laag (met de nadruk op use-cases / UI schermen en user interactie/flow diagrammen).
Pagina: 1