Verwijderd schreef op zondag 07 januari 2007 @ 23:27:
[...]
Betreft nog de concurrency, mag ik dan aannemen dat noch datasets, noch ORM de situatie kunnen vermijden dat wanneer user A iets aan het veranderen is en user B hetzelfde verandert maar sneller klaar is dan A, dat nadien user A een conflict krijgt? Er is dus geen van de twee die eigenlijk op dit vlak beter is dan de andere, of ben ik verkeerd? Ik meen ergens gelezen te hebben dat bij datasets in geval van een conflict de rollback al eens durft misgaan, met inconsistente data in de db tot gevolg, of is dit een fabeltje? Het enige wat men kan doen is om ten gepasten tijde -afhankelijk van de situatie zoals je aanhaalt- de data zelf te updaten naar de db en opnieuw op te halen?
Er is geen oplossing voor. Zie:
http://weblogs.asp.net/fbouma/archive/2003/05/24/7499.aspx
Veel O/R mappers hebben 1 concurrency methodiek (optimistic), anderen laten je vrij of hebben een plugin-architectuur waarbij je je concurrency methodiek per context/entity kunt aanpassen (LLBLGen Pro)
MrBucket schreef op zondag 07 januari 2007 @ 21:25:
Hmm, volgens mij haal je een paar dingen door elkaar. ORM staat voor Object-To-Relational mapping, en dat is dan ook precies wat het doet: het vertaalt de records die je uit je relationele database haalt naar (meestal collecties van) objecten, en vice versa kan je middels een method call tegen een object zeggen dat hij zichzelf moet inserten / updaten / deleten in plaats van dat je dit moet regelen middels het uitvoeren van een SQL statement.
Beetje kort door de bocht, want wat jij omschrijft is EEN implementatie van een O/R mapper. ORM staat voor Object Role Modelling overigens (
http://www.orm.net) en wordt veelvuldig gebruikt om O/R mapper/mapping aan te duiden, maar dat is onjuist.
O/R mapping zorgt ervoor dat 2 verschillende paradigmas (OO vs Relational) in 1 applicatie kunnen worden gebruikt zonder dat je de een aan de ander hoeft aan te passen. Dus je hoeft niet je entity classes aan te passen aan de tables en vice versa.
Zie:
http://weblogs.asp.net/fbouma/archive/2004/10/09/240225.aspxEchter, als je een OR mapping toepast, zegt dit nog niets over in hoeverre de data in je applicatie overeenkomt met de data in je database. OR-mappers als NHibernate laten je (voor zover ik weet) vrij in de keuze of je wel of geen chaching, lazy loading en/of delayed writing gebruikt.
Dat is niet iets wat gerelateerd is aan een O/R mapper: alle data die jij leest uit een DB is vanaf dat moment 'Stale', m.a.w: je kunt wel net doen alsof de data in memory dezelfde is als de data in de db, maar dat hoeft niet het geval te zijn.
Lazy loading, prefetch paths etc. zijn bedoeld om data-load acties te optimaliseren.
Vanuit een performance perspectief is dit waarschijnlijk wel aan te raden (omdat je waarschijnlijk minder roundtrips naar de DB nodig hebt), maar je zult merken dat je donders goed in de gaten moet houden welke data wel, en welke data niet verouderd mag zijn. Als dit erg complex wordt, dan kan dat een argument zijn om deze performance-optimalisaties niet toe te passen, zodat je minder je hoofd hoeft te breken of je wel met (redelijk) actuele data werkt.
Alle data is per definitie 'verouderd'. Een 'beetje' verouderd is altijd nog 'verouderd', er is geen tussenweg. Overigens zijn roundtrips lang niet altijd de bottleneck.
Andersom is een DataSet ook niet inherent aan "problemen met verouderde data". Je kunt er nl. voor kiezen om een DataSet elke keer opnieuw in te lezen als je de betreffende data nodig hebt, en na elke wijziging op een DataSet deze meteen te laten doorvoeren op de database.
Dat helpt niets, dan nog werk je met stale data en dus loop je de kans op concurrency gerelateerde zaken.
De reden dat de DataSet vaak in 1 adem genoemd wordt met het risico op verouderde data, is (volgens mij) dat de DataSet gebaseerd is op de filosofie van "minimaliseer het aantal roundtrips naar de DB", en niet "houd de data in code zo consistent mogelijk met die in de DB". En dan is het risico op verouderde data meer aanwezig.
Welnee, de dataset is gewoon een untyped bak voor resultsets.
Ja en nee. Ja, het is beter om geen SQL in je business logic te gebruiken, en het is sowiezo een goed idee om stored procedures te gebruiken (de DB kan SP's doorgaans sneller uitvoeren dan losse SQL statements).
In het kader van onderhoudbaarheid is het inderdaad beter om geen SQL in de code te plaatsen, maar het is onzin dat sp's sneller uitgevoerd worden.
Dit kan je zowel met de combinatie DataSets + SPs als met een OR mapping bereiken, dus daar zit het verschil niet echt.
Zie mijn artikel hierboven over to O/R map or not to O/R map: het is wel degelijk een fundamenteel verschil of je datasets gebruikt of entity classes.
Stored procs icm een o/r mapper is lastig, want je mapt je entities dan op resultsets van procs ipv fysieke representaties van entity definities (tables/views).
[...]
Je hebt nu inmiddels denk ik wel door dat je vraag zou moeten zijn: "Gebruik ik wel of geen lazy loading en/of delayed writing?".

Wat meespeelt in deze beslissing is:
- Hoeveel conflicten met verouderde data denk je tegen te komen? (zoals je al aangaf)
Dit heeft echt weinig met lazyloading te maken, omdat alle data die uit de db wordt geladen stale is.
- In hoeverre heb je de performancewinst van lazy loading en delayed writing nodig?
Lazy loading is alleen in DIE situatie een performance winst wanneer je enkele gerelateerde entities nodig hebt van een grote set. Wanneer je veel gerelateerde entities nodig hebt is lazy loading traag, omdat je per gerelateerd entity een query uitvoert.
- Welke data denk je veilig te kunnen cachen zonder in de problemen te komen?
Dit kun je ook buiten een O/R mapper doen en is veelal aan te raden. Zoals bv het cachen van webcontrols in een web applicatie: het cachen van de control output is efficienter dan het cachen van de entities gebruikt in de webcontrol, want je moet dan toch elke keer weer de control renderen, plus dat cache management performance KOST ipv dat het performance oplevert. (Entities cachen is alleen efficient wanneer je single entity instances fetcht op basis van de PK)
--toevoeging:--
Het gebruik van de concepten "lazy loading" (data pas inlezen als je het echt nodig hebt) en "delayed writing" (wijzigingen opsparen en dan als een bulk-opdracht naar de DB versturen) is meestal geen kwestie van wel of niet gebruiken, het is een spectrum.
De extreemste vormen zijn:
- altijd lazy loading (m.a.w. nooit geen data cachen)
- nooit lazy loading (alles van tevoren uitlezen en naar de client toetrekken (!!))
Je hebt ook nog zoiets als prefetch paths/spans: je wilt alle customers uit Nederland + hun 10 laatste orders. Dan heb je 2 queries nodig: de customers en de orders. Met lazy loading heb je dan (# customers)+1 queries nodig.
Lazy loading is overigens ook geen 'cache', het is een manier om het inladen van gerelateerde data uit te stellen, want wellicht heb je het niet nodig.
- alles delayed writen (bij het afsluiten van de applicatie pas DB-updates doen)
- nooit delayed writen (bij het aanpassen van een enkel veld meteen een update doen).
Alles delayed wegschrijven lijkt me onmogelijk, tenzij weggeschreven data niet opnieuw gelezen hoeft te worden.
Het moge duidelijk zijn dat (heel misschien met uitzondering van het 1e punt) dit geen werkbare oplossingen zijn. Een praktische oplossing ligt dus ergens in het midden, maar waar... dat verschilt per applicatie.

Nauwelijks, mits er goed gefilterd wordt, kun je altijd toe met prefetch paths.
[
Voor 75% gewijzigd door
EfBe op 08-01-2007 12:48
]