[Alg|.NET] Design van een generiek DbHelper object

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

  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Enkele dagen geleden was ik eens met Application roles in SQL Server aan het spelen. Dit werkt allemaal fijn, maar het probleem is dat je de application role iedere keer moet activeren als je de connectie opent.
Nu is het zo dat je -wil je een zo schaalbaar mogelijke applicatie- , je het best je connectie kunt sluiten van zodra je die niet meer nodig hebt. Op die manier kan je ook connection-pooling gebruiken.
Nu heb ik geen zin om iedere keer als ik een SqlConnection.Open() command doe, ook die application - role handmatig actief te gaan zetten. (Zie ook hier)
Daarom heb ik beslist om maar eens een DbHelper object te gaan ontwikkelen.

Nu, ik wil het ook direct goed aanpakken, en ik wil dat DbHelper object in al mijn projecten kunnen gebruiken. Ook die projecten dus die niet met Sql Server werken, maar met bv. Oracle.
Ook als ik in een project plots besluit om een andere DB te gaan gebruiken, wil ik daartoe in staat zijn, zonder dat ik het project hoef te recompilen.
Om zoiets te kunnen verwezenlijken, bestaat het Abstract factory pattern.

Een schema'tje van wat ik totnutoe heb ontwikkeld vind je hieronder:

Afbeeldingslocatie: http://users.pandora.be/fgzone/dbhelper.jpg

Door deze constructie kan ik dus at-runtime laten bepalen welk type IDbHelper object ik nu nodig heb.
Ik kan ook eenvoudig een nieuw DbHelper object bijmaken voor bv. Oracle databases door de Oracle ADO.NET classes te gaan gebruiken.
Ieder type DbHelper heeft op die manier dus z'n eigen implementatie voor die methods. Zo kan ik in de OpenConnection method van SqlDbHelper bv een application-role gaan activeren mocht dat nodig zijn.

Nu, zit ik nog met het volgende 'ei'.
Waar ga ik best m'n Factory-object gaan creeëren? Ik had zelf gedacht om dat in de presentatie-laag te doen. Vanuit die laag kan ik nl. eenvoudig aan een configuratie-file waarin staat welk type DBMS de applicatie gebruikt.
Bv:
code:
1
2
3
4
5
6
7
8
9
string type = ConfigurationSettings.AppSettings["typeDB"];
if( type == "sqlserver" )
{
    myDbFactory = new SqlFactory ();
}
else
{
    myDbFactory = new OleDbFactory ();
}


Dan had ik gedacht om m'n Factory-object simpelweg door te geven aan m'n DAL classes. In die DAL classes creeërt dat factory object dan het juiste DbHelper object en klaar is kees.

Nu, dat zal allemaal wel mooi werken enzo, maar het wringt ergens een beetje vind ik.
Als ik die factory in m'n presentatie-laag reeds creeër, meng ik dan m'n DAL code al niet te veel met m'n presentatie-code?
Ja en Nee, dat Factory object heeft nog niet echt iets met de datalaag te maken. Aan de andere kant is het op die manier wel mogelijk om in m'n presentatie-laag een Database object aan te maken.
Als ik het goed heb, kan ik ook de constructor(s) van de betreffende DbHelper objecten internal maken, zodat die enkel kunnen aangeroepen worden via de Factory-objecten.

Ik weet ook wel dat 'het design het project niet mag worden', maar ik had toch eens graag jullie opmerkingen, kritieken, etc.... gehoord. Wat wringt er? Wat zit er niet goed, wat kan er beter, ....

https://fgheysels.github.io/


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Al naar het nieuwe DAAB object gekeken? http://www.gotdotnet.com/...52-402b-9b7c-aaeb21d1f431

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


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Nee, dat had ik nog niet gezien.

https://fgheysels.github.io/


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15-02 11:20
Ik snap iets niet aan je ontwerp geloof ik.

Nomaal gesproken is een factory toch een object dat aan de hand van een context ( het type database ) bepaalde objecten teruggeeft ?

Waarom heb je dan voor elk type db een aparte factory, die naast de createHelper() ook nog properties heeft die ( naar mijn idee ) in het DBHelper object thuishoren ? ( Die connectionstring bv )

Dusseuh zoiets:

Java:
1
DBHelper dh = DBHelperFactory.getInstance().createDBHelper();


De createDBHelper method zou dan zelf bepalen welk type DBHelper object er nodig is.

[ Voor 25% gewijzigd door farlane op 12-08-2003 08:29 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Die connectionstring hoort idd thuis in m'n DbHelper object.
Bij het creeëren van een DbHelper object ga ik die connectionstring dan als parameter doorgeven aan de DbHelper constructor.
Om dit makkelijk te kunnen verwezenlijken, zorg ik er voor dat m'n factory die gegevens al bezit. Bij het creeëren van m'n factory ga ik dan éénmalig de connectie-string enzo gaan ophalen uit de config-file.

https://fgheysels.github.io/


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15-02 11:20
Is het dan niet handiger om die Factory een algemeen 'settings' object ( bijvoorbeeld een map< string, string > in c++ typen ) te laten maken die wordt gevuld met settings uit je configuratie, en die mee te geven aan de constructor van je DBHelper object ?

Op die manier vermijd je dat je bij iedere andere database ook een nieuwe factory moet maken. Je hebt dan alleen de variaties in je DBHelper objecten zitten.

just my 2 cts

[ Voor 9% gewijzigd door farlane op 12-08-2003 10:08 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Het is idd een mogelijkheid om één Factory object te maken die dan gaat gaan bepalen welke helper er moet gecreeërd worden.
Echter, als ik iedere keer dat ik een DbHelper object nodig heb, moet gaan controleren welk type ik nu weer nodig heb, lijkt me dat niet zo efficient.
Als ik met meerdere factories werk, dan hoef ik slechts 1x na te gaan welk type DB ik gebruik, en dan maak ik een factory voor dat type.

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

*kick* :)

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 21:12
Instantiatie van de DBHelper hoort iig niet thuis in de presentatie laag. Je zou een registry kunnen introduceren in de DAL waar je de instantie van de juiste dbhelper in onderbrengt.

  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Ik heb ook geen DbHelper object in m'n datalaag, enkel een factory-object dat ik dan doorgeef aan m'n datalaag.

Ik moet trouwens dat Decorator pattern nog eens bekijken van Alarmnummer

https://fgheysels.github.io/


  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 21:12
Je hebt enkel een factory-object in je datalaag wat je doorgeeft aan je datalaag?

ps: Ik snap trouwens niet waarom je die application blocks van ms niet gebruikt. Die zijn goed uit te breiden. Daarnaast zou je gewoon een referentie design kunnen nemen. Er zijn al zoveel mensen die hier mee bezig zijn geweest.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

whoami schreef op 15 August 2003 @ 10:06:
Ik heb ook geen DbHelper object in m'n datalaag, enkel een factory-object dat ik dan doorgeef aan m'n datalaag.

Ik moet trouwens dat Decorator pattern nog eens bekijken van Alarmnummer
Het voordeel is dat je dan geen nieuwe interfaces introduceerd waar de rest van het systeem mee in aanraking komt (lees: last van krijgt want je krijg onnodige afhankelijkheden naar jouw systeem). Ik zou dus gewoon een decorator maken om extra functionaliteit toe te voegen (kijk ook ff naar de proxy), hierdoor kan het systeem gebruik maken van de oude interfaces terwijl je toch stiekum jouw functionaliteit eraan toegevoegd hebt.

[ Voor 20% gewijzigd door Alarmnummer op 15-08-2003 10:24 ]


  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15-02 11:20
whoami schreef op 15 augustus 2003 @ 10:06:
Ik moet trouwens dat Decorator pattern nog eens bekijken van Alarmnummer
Ik zie nog ff niet hoe je hier een decorator in zou moeten passen. Je probleem had toch te maken met het instantieren van het factory object ?
Waar zou je die decorator dan voor willen gebruiken ?

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Hij wil bestaande interfaces onderbrengen in een nieuwe class hierarchie (de DbHelper). Hij wil verder geen nieuwe methodes aanbieden (zo ver ik heb begrepen) dus een nieuwe class hierarchie is daarvoor niet nodig. Verder voldoet de Sql2000 en de Oracle implementaties aan een reeds bestaande interface, dit is nog een reden om niet een nieuwe class hierarchie te introduceren.

Hij kan hier perfect gebruik maken van het decorator design pattern om de oracle en sql2000 objecten te versieren met zijn eigen extra`s. Het voordeel is dat je in de rest van het systeem totaal neits meer ziet van whoami zijn extra`s.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

En heb je er al iets leuks van gemaakt? :)

  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Ik heb m'n GoF boek nog niet van de plank gehaald om dat decorator-pattern te bekijken als je dat bedoelt. :+
Ik heb het momenteel een beetje drukjes, maar dat komt nog wel. ;)

Echter, ik denk niet dat een decorator hier van toepassing kan zijn, aangezien m'n dbHelper verschillende classes encapsuleert. (Die dbHelper bevat bv. een Connection object, een DataCommand object, ... )

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik ben verder niet thuis in de .NET architectuur om een goed antwoord daarop te geven. Maar ik zag die nieuwe class hierarchie en daarbij moest ik meteen denken: is dat nou nodig? Ik probeer het ontwerp zo simpel mogelijk te houden en wijzigingen zo weinig mogelijk het systeem te laten indringen. Decorators kan je hierbij ideaal inzetten.

En ik vond dit eerlijk gezegd wel een goeie uitspraak:
Technical skill is mastery of complexity while creativity is mastery of simplicity
E.C. Zeeman

Verwijderd

Je abstract factory DBHelper mag nooit in je presentatie laag zitten.
Alleen je DAL mag weten dat er een database gebruikt wordt.
Je kan het factory pattern gebruiken om je DBHelper te creeren in je DAL.
Dat lijkt me hier makkelijker dan het abstract factory pattern.
Je factory method kan dan aan de hand van informatie uit de System.Configuration.AppSettingsReader en wat runtime type informatie
de juiste DBHelper klasse instantieren.

Decorators lijken me hier overdreven. Er wordt geen widged set ofzo gedesigned...

[ Voor 9% gewijzigd door Verwijderd op 19-08-2003 09:49 ]


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Verwijderd schreef op 19 August 2003 @ 09:47:
Decorators lijken me hier overdreven. Er wordt geen widged set ofzo gedesigned...
Ik wist niet dat je hem alleen mocht gebruiken voor widget sets ;)

En ik denk dat je of mijn antwoorden niet goed heb doorgelezen, of niet hebt begrepen, of het de decorator design pattern niet helemaal goed hebt begrepen.

  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Verwijderd schreef op 19 August 2003 @ 09:47:
Je abstract factory DBHelper mag nooit in je presentatie laag zitten.
Alleen je DAL mag weten dat er een database gebruikt wordt.
Je kan het factory pattern gebruiken om je DBHelper te creeren in je DAL.
Dat lijkt me hier makkelijker dan het abstract factory pattern.
Je factory method kan dan aan de hand van informatie uit de System.Configuration.AppSettingsReader en wat runtime type informatie
de juiste DBHelper klasse instantieren.
Dat dacht ik idd ook, echter, ik vond het een beetje onzinnig om iedere keer dat ik een DAL method aanriep, ik een nieuwe factory te gaan creeëren.
Daarom heb ik een Factory object aangemaakt in m'n presentatie-laag, en die bewaar ik in een Application Variable. Die geef ik dan door aan m'n DAL.

Design-technisch gezien zou het natuurlijk mooier zijn om die Factory in m'n DAL ofzo aan te maken, echter, qua performance zou dat toch zeker een nadeel zijn.
Don't let the design become the project

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Voor ieder argument is er altijd een goed tegen argument:
A broken window.

One broken window, left unrepaired for any substantial length of time, instills in the inhabitants of the building a sense of abandonment—a sense that the powers that be don't care about the building. So another window gets broken. People start littering. Graffiti appears. Serious structural damage begins. In a relatively short space of time, the building becomes damaged beyond the owner's desire to fix it, and the sense of abandonment becomes reality.
The Pragmatic Programmer: From Journeyman to Master

:P

[ Voor 12% gewijzigd door Alarmnummer op 19-08-2003 10:05 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
Hmmm.... Da's een beetje overdreven. ;)

In mijn geval kan ik gewoon die factory ergens anders creeëren. Als ik die DAL gebruik, dan weet ik gewoon zeker dat ik een DB-gebruik, waarom heb je anders DAL code?
Als ik in m'n config-file bepaalde settings niet heb, dan maak ik geen gebruik van een DB, en ga ik ook die factory niet gaan creeëren.

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 14-02 12:34

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 August 2003 @ 10:11:
Hmmm.... Da's een beetje overdreven. ;)

In mijn geval kan ik gewoon die factory ergens anders creeëren. Als ik die DAL gebruik, dan weet ik gewoon zeker dat ik een DB-gebruik, waarom heb je anders DAL code?
Als ik in m'n config-file bepaalde settings niet heb, dan maak ik geen gebruik van een DB, en ga ik ook die factory niet gaan creeëren.
Je dal kan toch ook je web.config uitlezen?
Daarnaast: Waarom heb je gekozen voor een application variabele en niet voor bijvoorbeeld System.Web.Caching?

[ Voor 12% gewijzigd door gorgi_19 op 19-08-2003 10:15 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
gorgi_19 schreef op 19 August 2003 @ 10:14:
[...]

Je dal kan toch ook je web.config uitlezen?
Idd.
Maar dan zou ik iedere keer dat ik een DAL method aanroep, die config moeten gaan checken, nagaan welk factory object ik moet creeëren, die factory creeëren, die factory een dbHelper laten creeëren.
Niet echt performant als je het mij vraagt. Ik geef nu gewoon een factory object door aan m'n DAL object (in de constructor bv).
Dat DAL object gebruikt dan die factory om een dbHelper object te creeëren.
Daarnaast: Waarom heb je gekozen voor een application variabele en niet voor bijvoorbeeld System.Web.Caching?
Hmmm, dat zou ik nog kunnen doen.

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 14-02 12:34

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 19 August 2003 @ 10:20:
[...]

Idd.
Maar dan zou ik iedere keer dat ik een DAL method aanroep, die config moeten gaan checken, nagaan welk factory object ik moet creeëren, die factory creeëren, die factory een dbHelper laten creeëren.
Niet echt performant als je het mij vraagt. Ik geef nu gewoon een factory object door aan m'n DAL object (in de constructor bv).
Dat DAL object gebruikt dan die factory om een dbHelper object te creeëren.
Je hoeft in dat geval ook niet je web.config te checken. Je controleert gewoon of in je cache al het object staat of dat deze nothing / null is. Is deze null, dan moet die aangemaakt worden, anders hoeft deze niet aangemaakt te worden.

Sowieso vraag ik me af of het echt heel veel trager is om de boel in je web.config te zetten. Volgens mij, maar dat weet ik dus niet zeker, worden alle application variabelen bij het wijzigen van je web.config al 'gekopieerd' en hoeft het bestand dus niet steeds aangesproken te worden.

code:
1
2
3
4
If Cache("HelperType") Is Nothing
    Cache("HelperType") = new object
End if
Return CType(Cache("HelperType"), IDataBaseHelper)

[ Voor 8% gewijzigd door gorgi_19 op 19-08-2003 10:24 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:19
gorgi_19 schreef op 19 August 2003 @ 10:23:
[...]

Je hoeft in dat geval ook niet je web.config te checken. Je controleert gewoon of in je cache al het object staat of dat deze nothing / null is. Is deze null, dan moet die aangemaakt worden, anders hoeft deze niet aangemaakt te worden.
Ik kan toch niet vanuit m'n DAL (aparte DLL) aan mijn Cache?
En als dit toch zou kunnen, dan zou het een slecht design zijn om vanuit m'n DAL mijn presentatie-laag te gaan benaderen. Op die manier zou ik nl. m'n DAL vastkoppelen met m'n presentatie-laag. Dan zit je vast.
Sowieso vraag ik me af of het echt heel veel trager is om de boel in je web.config te zetten. Volgens mij, maar dat weet ik dus niet zeker, worden alle application variabelen bij het wijzigen van je web.config al 'gekopieerd' en hoeft het bestand dus niet steeds aangesproken te worden.
Dat is waar, en het checken van m'n config-file is dan ook niet het grootste probleem. Het creeëren van een factory object, iedere keer ik een DAL method aanroep is de grootste bottleneck.
Bv: in UpdateContact(), DeleteContact, InsertContact(), etc... zou ik iedere keer een factory moeten maken.

https://fgheysels.github.io/


Verwijderd

Van de cache kan je een singleton maken, of zit je niet steeds in hetzelfde AppDomain.

Alarmnummer, ik had het best gelezen en ik ken het decorator pattern en .net ook.
Mijn mening is dat het decorator pattern er niet geschikt voor is.
Pagina: 1