Archief - normalisatie vraag

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

M_N_M

Legacy Member
Hallo,

ik heb een vraagje omtrent normalisatie.

Ik zal (vereenvoudigd) uitleggen hoe mijn database eruit ziet.
Ik heb 3 beheerstabellen:
- tabel1 met het artikelbestand:
ID autoint (primary key en dus aanpasbaar)
Artikelnummer (unique key)
Omschrijving
<nog wat randinfo bv type label, grondstof of eindproduct, ...>

- tabel2 met mogelijke informatie die je aan een artikel kan hangen:
ID autoint (primary key en dus niet aanpasbaar)
Informatie (unique key)

Mogelijke waarden: magazijn, THT, type pallet, ...

- tabel3 waarbij men kan opgeven welke informatie er moet opgevraagd worden bij een aanmelding van een artikel:
ID autoinit (primary key en dus niet aanpasbaar)
ID_artikel
ID_info
<nog wat extra velden die niet van belang zijn bv "verplicht in te geven">

De unique key is hier de combinatie van artikel en info.
Met deze tabel definieer je dus dat je bij artikel <x> zowel info "THT" als "magazijn" moet opvragen.

Hierboven zijn de beheerstabellen en kwa normalisatie zit dat volgens mij wel goed (nergens dubbele info gebruikt en telkens gewerkt met ID).

Ik stel mij echter de vraag of ik bij mijn HISTORIEK tabellen ook moet werken met id's of daar met de effectieve waarden?
Wat bedoel ik met "historiek": als men effectief zegt, ik ga nu 100 stuks van artikel <x> maken, dan wordt dat gelogd in historiek met een unieke code (jaar+maand+volgnummer) met daarin de gelinkte informatie uit het beheer)

Bv:
historiek tabel 1 (artikel) bevat bijvoorbeeld zo'n record:
2010020001 artikel x omschrijving x <extra info zoals aanmeldtijdstip, persoon, ..>

historiek tabel 2 (info artikel) bevat bijvoorbeeld volgende records:
2010020001 magazijn test (uniek nummer, info, waarde)
2010020001 THT 01/01/2011 (uniek nummer, info, waarde)

Mijn vraag: zou ik het doen zoals hierboven of zou ik in de historiek tabellen ook id's wegschrijven?

Kwa normalisatie lijkt mij dat het beste maar ik stel mij dan toch de vraag : wat als men het beheer gaat aanpassen, dan gaat de historiek ineens mee wijzigen?! (bv men zegt "THT" is vanaf vandaag "pallettype"). Aangezien ik in mijn historiek werk met een "ID", zal het dus lijken of al mijn oude aanmeldingen onder "pallettype" aangemeld zijn ipv "THT" ?!

Ik zou natuurlijk kunnen afblokken dat men het beheer niet meer kan wijzigen van zodra er een aanmelding op gebeurt is maar dat lijkt mij ook niet wenselijk aangezien ik dan bv artikelnummers die ik niet meer wil aanmelden niet meer kan verwijderen..

Hoe doen jullie dit?

Hopelijk is het een beetje duidelijk uitgelegd en kunnen jullie mij raad geven!


Grtz,
M_N_M

Moto

Legacy Member
Hierboven zijn de beheerstabellen en kwa normalisatie zit dat volgens mij wel goed (nergens dubbele info gebruikt en telkens gewerkt met ID).
telkens gewerkt met ID?
is dat een normalisatie-regel?
Nuja in Table1 zou ik de ID wel laten staan, artikelnummers die uniek zijn als dat echt zonder twijfel zo is heb je geen ID veld nodig, maar ja in de praktijk blijken ze dan opeens toch niet zo uniek te zijn :)

table3, voor het koppel tabelleke hebt ge eigenlijk geen ID nodig.

Mijn vraag: zou ik het doen zoals hierboven of zou ik in de historiek tabellen ook id's wegschrijven?
Denk dat die tabellen wel gebruikt worden in de app, stel dat ge de historiek van een artikel wilt opvragen, dan hebt ge wel een apart veld met de ArtikelID nodig, of voor reporting

wat als men het beheer gaat aanpassen, dan gaat de historiek ineens mee wijzigen?! (bv men zegt "THT" is vanaf vandaag "pallettype"). Aangezien ik in mijn historiek werk met een "ID", zal het dus lijken of al mijn oude aanmeldingen onder "pallettype" aangemeld zijn ipv "THT" ?!
De gebruiker duidelijk maken dat als men de omschrijving van de informatie wijzigt dat dat het gevolg zal zijn.
Tis dus eerder als ene palettype invult en der dingen mee doet dat ge het achteraf kunt rechttrekken, als ze de betekenis volledig veranderen is dat wel hun probleem

Ik zou natuurlijk kunnen afblokken dat men het beheer niet meer kan wijzigen van zodra er een aanmelding op gebeurt is maar dat lijkt mij ook niet wenselijk aangezien ik dan bv artikelnummers die ik niet meer wil aanmelden niet meer kan verwijderen..
Wijzigen + verwijderen moeten beide kunnen
voor verwijderen kijken als het al gebruikt is
nee : Hard-Delete
Ja : Soft-Delete
Soft-Delete is gewoon status-veldje of deleted-flag toevoegen die ge dan bv gebruikt bij ophalen van uw data, voor rapportering + historiek alles ophalen,
voor nieuwe dingen te doen met de huidige artikels, alleen actieve ophalen

Nog iets om over na te denken qua deleten van date :)

M_N_M

Legacy Member
Moto zei:
telkens gewerkt met ID?
is dat een normalisatie-regel?
Nuja in Table1 zou ik de ID wel laten staan, artikelnummers die uniek zijn als dat echt zonder twijfel zo is heb je geen ID veld nodig, maar ja in de praktijk blijken ze dan opeens toch niet zo uniek te zijn :)

table3, voor het koppel tabelleke hebt ge eigenlijk geen ID nodig.
Voor elke tabel een ID is nodig omdat ik werk in C#.NET met het entity framework om tbl'en te benaderen en dat laat niet toe dat je een primary key aanpast. Voor die reden dus ook overal toegevoegd (en ook in tabel 3) omdat je ander eens een foutief ingegeven link (bv artikel <x> met info "magazijn") nooit meer kan wijzigen (tenzij deleten en opnieuw toevoegen)

Op zich is dat misschien wel een goede denkwijze om mijn historiek niet naar de kl*te te krijgen?

Langs de andere kant (denkende aan de grote historiektabellen) is een update doorsturen op één int-veld wel veel sneller dan een gecombineerde key van chars.

Moto zei:
De gebruiker duidelijk maken dat als men de omschrijving van de informatie wijzigt dat dat het gevolg zal zijn.
Tis dus eerder als ene palettype invult en der dingen mee doet dat ge het achteraf kunt rechttrekken, als ze de betekenis volledig veranderen is dat wel hun probleem
idd da's hun probleem maar wij hebben nu reeds apps waar in historiek nooit id's gebruikt worden, daar hebben we dat probleem dus niet .. (historiek is en blijft altijd ongewijzigd, eender wat de gebruiker uitsteekt in het beheer (wat mij logisch lijkt)

Zeker in geval van facturen lijkt het mij ontoelaatbaar dat je bv bij een heraanmaak van een factuur van een paar jaar terug totaal andere artikelomschrijvingen te zien zou krijgen dan de originele factuur (moest men in het beheer de omschrijving aangepast hebben); niet?

Moto zei:
Wijzigen + verwijderen moeten beide kunnen
voor verwijderen kijken als het al gebruikt is
nee : Hard-Delete
Ja : Soft-Delete

Soft-Delete is gewoon status-veldje of deleted-flag toevoegen die ge dan bv gebruikt bij ophalen van uw data, voor rapportering + historiek alles ophalen,
voor nieuwe dingen te doen met de huidige artikels, alleen actieve ophalen

Nog iets om over na te denken qua deleten van date :)
hmz, deleted flag voorzien in elke tabel zou idd wel handig zijn, ik bekijk de link ook eens.


Alvast bedankt!

Moto

Legacy Member
Voor elke tabel een ID is nodig omdat ik werk in C#.NET met het entity framework om tbl'en te benaderen en dat laat niet toe dat je een primary key aanpast.
Allez veel succes met EF, snap nooit waarom sommigen een crappy beta-frameworkske gebruiken, maarja...

omdat je ander eens een foutief ingegeven link (bv artikel <x> met info "magazijn") nooit meer kan wijzigen (tenzij deleten en opnieuw toevoegen)
Ken uw functional specs niet, zie hier niet echt direkt het probleem

Langs de andere kant (denkende aan de grote historiektabellen) is een update doorsturen op één int-veld wel veel sneller dan een gecombineerde key van chars.
Euhm, gaat het hier over performance naar de DB? kijk, ge gebruikt EF, denk niet dat in de huidige versie al bv een batch-insert zit, als ge echt deftige performance wilt gooit ge al best EF deruit, tis niet dat ge daar veel develop-tijd mee gaat besparen zowiezo

Zeker in geval van facturen lijkt het mij ontoelaatbaar dat je bv bij een heraanmaak van een factuur van een paar jaar terug totaal andere artikelomschrijvingen te zien zou krijgen dan de originele factuur (moest men in het beheer de omschrijving aangepast hebben); niet?
Ahja natuurlijk, als een requirement is om de orginele factuur terug te zien moet ge daar rekening mee houden met uw DB-design, mijn link gaat daar eigenlijk ook over.
Altijd rekening houden met requirements, dus ook hoe uw data best stockeren om het er effecient terug uit te halen, + ook nog rekening houden met eventuele toekomstige requirements, rapportering, ....
Beetje pragmatisch zijn in die dingen heeft bij mij altijd voorrang op "het in acht houden van alle normalisatie-regelkes"

M_N_M

Legacy Member
is het entity framework dan zo vertragend? LINQ TO SQL werd ons afgeraden aangezien ze hier niet meer verder in ontwikkelen.. (+ voordeel van EF is dat je makkelijk kan switchen naar een andere backend DB, bij linq to sql is dat zowiezo een sql server)

Datasets zijn idd het snelste maar heeft het nog andere voordelen? Voor elke query heb je dan toch een andere dataset nodig en in een grote applicatie gaat dat toch leiden tot enorm veel datasets?

Btw: voor de ontwikkeling van onze basisklasse hebben we idd al ferm zitten zwoegen met dat EF (oa dynamische opbouw van een query met dynamische velden/tabellen was niet simpel!)

Nog verdere problemen (waar we voorlopig nog niet aan uit zijn): sortering op datagrids lukt default niet (met datasets gaat dat standaard)

Moto

Legacy Member
Linq to Sql Server zou ik nu ook niet direkt meer aanraden,
EF is nog beta, dat moet ge al beseffen, ge maakt een applicatie op een framework dat nog (lang) niet af is.
Vertragend, dit is al grappig -> What happens behind the scenes: NHibernate, Linq to SQL, Entity Framework scenario analysis

Het grootste probleem qua EF performance is Batch inserts/updates
Stel dat ge een faktuur hebt met 8 order lijnen, dus 9 records
Als ge dat zelf doet zonder ORM of bv met NHibernate hoeft ge daarvoor maar 1 keer naar de DB te gaan, met EF moet ge 9 keer naar de DB.
Ander zeer groot probleem zijn de N+1 Selects bij relational mapping

Datasets zijn idd het snelste maar heeft het nog andere voordelen? Voor elke query heb je dan toch een andere dataset nodig en in een grote applicatie gaat dat toch leiden tot enorm veel datasets?
Voordeel is dat als ge alles zelf doet later niet voor verrassingen gaat staan, anyway ik gebruik ook een ORM ze, maar enkel om datasets naar objecten te mappen en objecten terug naar params van een stored procedure te mappen, niks relationeel mapping, allemaal 1op1 en nooit een probleem.
Veel extra datasets/views heb ik niet nodig, en als ik 1 nodig heb, maak ik snel ene.
Het grote voordeel is 1 Leaky abstraction minder, (artikel over leaky abstrations)
Sql is ook een leaky abstraction heh, moogt gij wel indexen zetten, uiteindelijk moet ge u execution plan bekijken om te zien wat er echt gebeurd, om dan op een leaky abstraction nog een andere leaky laag (dus ORM) te plamuren is meestal vragen om problemen, zeker in grote systemen.

Btw: voor de ontwikkeling van onze basisklasse hebben we idd al ferm zitten zwoegen met dat EF (oa dynamische opbouw van een query met dynamische velden/tabellen was niet simpel!)
Bv zoekscherm op meerdere tabellen met optionele velden
Mja met 101 mappen is dat 1 Stored Procedure + 1 aparte view/dataset/poco en klaar,
bij slechte performance kunt ge direkt die SP op de DB executen, naar het execution plan kijken en aanpassen (indexje ofzo) waar nodig.

Bij ORM's is het meestal aan de hand van ingevulde velden entities joinen, en dan gaat hem zelf wat SQL samen stellen, als ge dan performance problemen hebt is het log files uitpluizen, op de DB uittesten, N+1 selects oplossen, andere velden dan eens invullen, log files bekijken, op DB uittesten, N+1 Sel......
ge weet wel wat ik bedoel :)

Nog verdere problemen (waar we voorlopig nog niet aan uit zijn): sortering op datagrids lukt default niet (met datasets gaat dat standaard)
Heb dat nog vorige week op het werk snel snel gemaakt, zal morgen is wa code posten

M_N_M

Legacy Member
Hallo,

even een update. Aangezien ons nieuw project nog niet zo ver zat, hebben we het volledig omgegooid en zijn we gestopt met het (crappy) EF, te veel problemen mee..

We werken nu met ADO.NET in combinatie met datasets, hierop kan je bepaalde standaardzaken wel uitvoeren die via het EF niet standaard gingen (sortering via klik op header, filter zetten op een datagrid, wijzigingen detecteren, opbouw van een dynamische query is vééééééél makkelijker (gewoon eigenlijk je sql maken in een string) ...)

Transacties zullen we dus zelf moeten regelen maar dat is nu niet zo moeilijk.

Ik zit wel nog steeds in twijfel met mijn historiek tabellen, ik ben eerder geneigd om daar de huidige situatie ("foto" van hoe het op dat moment er uit zag) van mijn beheer op te slaan (dus niet enkel de "id" maar wel de volledige artikelnummer, artikelomschrijving, info naam, verplicht status van info naam, ...)

Dit zal natuurlijk mijn tabellen wel wat groter maken maar dan staat beheer los van historiek wat ik toch liever heb. (dan mogen ze prutsen zo veel ze willen en komt de historiek niet in de knoei)

Wat betreft de auto id's overal toevoegen => ga hier nog eens een schema van maken en die enkel toevoegen waar echt nuttig (nu dat EF niet meer gebruikt is, is dat alweer een reden minder om die overal te gaan toevoegen :p)

Alvast bedankt voor de (goede) raad!
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan