[C#] Objectgeorienteerd te werk gaan met SQL als backend?

Pagina: 1
Acties:

  • Lethalis
  • Registratie: April 2002
  • Niet online
Even op de hypothetische toer gaan :)

Stel je hebt in SQL server 2 tabellen, de tabel 'Boek' en de tabel 'Auteur'. De tabel 'Boek' bevat gegevens over een boek, bijv ISBN, titel, aantal pagina's enzovoorts en de tabel 'Auteur' allerlei gegevens over een auteur.

Stel je schrijft code om deze gegevens te beheren, om dus boeken en auteurs toe te voegen, te verwijderen, te wijzigen enzovoorts. In procedurele top-down code zou je dan in C# met 1 enkele SQL connectie alles kunnen oplossen. Bij het toevoegen van een nieuwe boek en een nieuwe auteur zou je makkelijk onder elkaar code kunnen schrijven die met 1 enkele SQL connectie een record voor de auteur aanmaakt, en een record voor het boek. Abstract gezien:

1. Maak connectie object aan (SqlConnection)
2. Maak commando object aan (SqlCommand)
3. Voor SQL INSERT commando's uit voor resp. de auteur en het boek.


En klaar is kees.

Maar nu is deze code in zijn uiteindelijke vorm natuurlijk minder leesbaar en toegankelijk dan code die zou vertellen:

1. Maak instantie van Auteur klasse aan.
2. Ken de eigenschappen toe aan de public properties.
3. Voer de Insert method uit.
4 t/m 6. Doe hetzelfde met de Boek klasse.


In C#, betekent dit echter dat ik binnen elke klasse een eigen SQL connectie moet aanmaken, als ik deze niet via de constructor mee wil geven. Performance technisch ga ik er dus op achteruit, als ik de code echt abstract wil houden en geen connectie-object meegeef.

Nu is dus mijn vraag: hoe pak ik dit op een nette manier aan? Kom ik er niet omheen het SqlConnection object mee te geven, zodat ik in bijvoorbeeld de Insert method van de Auteur klasse en de Boek klasse dezelfde connectie wil gebruiken, net zoals bij de procedurele code. Of is er toch nog een andere manier zoiets dergelijks aan te pakken in C#?

Het liefst zou ik in de programmacode zelf zou abstract mogelijk werken met eigen klassen die dan weer de echte code bevatten, maar toch graag vermijden dat ik op een gegeven moment 1000 keer een SQL connectie aanmaak en sluit voor allerlei triviale dingen.

Ik hoop dat het verhaal duidelijk is en mensen hier hun eigen visie op kunnen geven :)

Bij voorbaat dank.

Ask yourself if you are happy and then you cease to be.


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 21-05 14:59

pjvandesande

GC.Collect(head);

Waarom wil je het niet als argument meegeven?

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 19:24

gorgi_19

Kruimeltjes zijn weer op :9

Het liefst zou ik in de programmacode zelf zou abstract mogelijk werken met eigen klassen die dan weer de echte code bevatten, maar toch graag vermijden dat ik op een gegeven moment 1000 keer een SQL connectie aanmaak en sluit voor allerlei triviale dingen.
Je kan speciale classes maken die een 'combinatie' vullen, of iig een aparte method schrijven. Sowieso valt de 'prijs' van het openen van een connectie mee als je een connectionpool gebruikt :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 23-05 16:52
Een connectie aanmaken en sluiten is helemaal niet erg, zeker niet als je connection pooling gebruikt.
Sterker zelfs, in systemen met meerdere gebruikers is het helemaal niet aangeraden om je connectie gedurende de gehele 'levensduur' vn je applicatie open te houden. Dat is totaal niet schaalbaar.

Ik zou het zo aanpakken:
Een class auteur, een class boek, een collection class auteurs en een collection class boeken.
De collection-class boeken kan dan een 'field' zijn van auteur, een auteur schrijft nl. 1 of meer boeken.
Dan kan je ook nog een class, of een aantal classes aanmaken met eventueel static methods die gewoon de database-afhandeling gaan verzorgen, en die methods roep je dan aan vanuit je auteur of boek class:

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
26
27
28
class Auteur
{
    private string _naam;
    ...
    private BoekenCollection _boeken;
    ....
     ....
    public void Save()
    {
         ....
         AuteurDAL.Insert ( _naam, .... );
    }
}

class AuteurDAL
{
    public static void InsertAuteur ( string naam ... .)
    {
          SqlConnection conn;
          SqlCommand cmd;
          ....
          conn.Open();
          ...
          cmd.ExecuteNonQuery();
          ...
          conn.Close();
    }
}

De code is louter ter illustratie natuurlijk.

https://fgheysels.github.io/


  • Lethalis
  • Registratie: April 2002
  • Niet online
gorgi_19 schreef op 02 september 2004 @ 22:07:
[...]
Sowieso valt de 'prijs' van het openen van een connectie mee als je een connectionpool gebruikt :)
Daar maak ik ook al ruimschoots gebruik van :)

Het werkt ook zoals het nu is, maar toch 'voelt' het niet netjes. Momenteel heb ik een basisklasse met daarin mijn SqlConnection object en een OpenSqlConnection() en CloseSqlConnection() method, waarvan alle klassen overerven en heel makkelijk hun eigen SqlConnection kunnen openen en sluiten.

Probleem is echter dat mijn applicatie deel uitmaakt van een groter systeem en dan ook nog eens voor elke request in een aparte thread wordt afgesplitst binnen welke ik werk. Als mijn stukje code dan bijvoorbeeld 10 SQL connecties gebruikt, van de 127 beschikbare binnen mijn connectiepool en er worden meer dan 10 threads tegelijkertijd van afgesplitst dan wordt het allemaal een beetje spannend :/

Ik zie mezelf dan ook genoodzaakt om binnenkort de connectie mee te geven in de constructor, maar vind het gewoon niet netjes. Daarom vroeg ik me af of er andere manieren zijn om zoiets toch netjes te implementeren en het schaalbaar te houden.

@questa: Omdat de SqlConnection op een ander abstractieniveau ligt, logisch gezien. Technisch gezien is het natuurlijk wel te doen.

@whoami: Waarom de statische methods? Dat gaat een beetje tegen het objectgeorienteerde in, of zie ik dat verkeerd? :+

Bedankt voor de reacties tot nu toe iig :)

Ask yourself if you are happy and then you cease to be.


  • whoami
  • Registratie: December 2000
  • Laatst online: 23-05 16:52
Lethalis schreef op 02 september 2004 @ 23:09:
[...]
Daar maak ik ook al ruimschoots gebruik van :)
Je kan enkel gebruik maken van connection pooling als je je connectie sluit wanneer je ze een tijdje niet meer nodig hebt, en wanneer je telkens opnieuw identiek dezelfde connectionstring gebruikt.
Het werkt ook zoals het nu is, maar toch 'voelt' het niet netjes. Momenteel heb ik een basisklasse met daarin mijn SqlConnection object en een OpenSqlConnection() en CloseSqlConnection() method, waarvan alle klassen overerven en heel makkelijk hun eigen SqlConnection kunnen openen en sluiten.
Je bedoeld dat je class Boek bv van die 'basis-connection' class inherit?
Dat zou ik niet doen. Je kan eventueel overwegen dat je class 'Boek' een object heeft van die Connectie-class, maar ik zou het zeker geen Connectie-class laten zijn.
Probleem is echter dat mijn applicatie deel uitmaakt van een groter systeem en dan ook nog eens voor elke request in een aparte thread wordt afgesplitst binnen welke ik werk. Als mijn stukje code dan bijvoorbeeld 10 SQL connecties gebruikt, van de 127 beschikbare binnen mijn connectiepool en er worden meer dan 10 threads tegelijkertijd van afgesplitst dan wordt het allemaal een beetje spannend :/
Waarom gebeurt dat altijd in een aparte thread, en hoe?
@whoami: Waarom de statische methods? Dat gaat een beetje tegen het objectgeorienteerde in, of zie ik dat verkeerd? :+
Je hoeft ze niet static te maken, je kan er instance-methods van maken mocht dat nodig zijn, maar een DAL zie ik meestal als een statische layer.
Ik heb het ook wel eens als non-static gemaakt, maar dat was dan omdat ik at runtime van Data Access Layer wou kunnen wisselen:
[rml][ Alg/.NET] Architectuur smart client - Part II concrete case[/rml]

https://fgheysels.github.io/


  • mindcrash
  • Registratie: April 2002
  • Laatst online: 22-11-2019

mindcrash

Rebellious Monkey

Objectgeorienteerd data benaderen in o.a. SQL Server met C#?

Dan zou ik je aanraden om zeker eens te kijken naar: Gentle.NET

Documentatie is redelijk schaars, maar technisch gezien is dit framework zeer goed opgezet en het is ook nog eens gratis (opensource!). Ik ben in ieder geval dusdanig onder de indruk dat ik dit stukje software vaker ga gebruiken in mijn .NET projecten in de nabije toekomst ;)

Meer info @ deze site.

"The people who are crazy enough to think they could change the world, are the ones who do." -- Steve Jobs (1955-2011) , Aaron Swartz (1986-2013)


  • EfBe
  • Registratie: Januari 2000
  • Niet online
Inderdaad, O/R mapping is wat je wilt. Niet gratis, wel erg goed (:)) : LLBLGen Pro: http://www.llblgen.com.

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


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 19:24

gorgi_19

Kruimeltjes zijn weer op :9

En dan hebben we, als het over O/R mapping gaat, ook nog bijvoorbeel Entity Broker en WilsonORMapper :) Hoewel iedereen enthousiast is over zijn eigen gebruikte c.q. gemaakte O/R mapper, zou ik iedereen willen vragen om niet over te gaan tot het noemen van allerlei O/R mappers, zodat er hier een opsomming gaat optreden.

Relevante (theorie)bespreking c.q. algemene toepassing past hier natuurlijk wel :)

[ Voor 30% gewijzigd door gorgi_19 op 03-09-2004 09:44 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • CyBoB
  • Registratie: Januari 2001
  • Laatst online: 24-12-2025

CyBoB

.::BURB::.

er is afaik ook een c# voor hibernate!! hibernate voor jave werkte erg goed, misschien moet je hier eens naar kijken!!

Verwijderd

Lethalis schreef op 02 september 2004 @ 23:09:
[...]
Daar maak ik ook al ruimschoots gebruik van :)

Het werkt ook zoals het nu is, maar toch 'voelt' het niet netjes. Momenteel heb ik een basisklasse met daarin mijn SqlConnection object en een OpenSqlConnection() en CloseSqlConnection() method, waarvan alle klassen overerven en heel makkelijk hun eigen SqlConnection kunnen openen en sluiten.

Probleem is echter dat mijn applicatie deel uitmaakt van een groter systeem en dan ook nog eens voor elke request in een aparte thread wordt afgesplitst binnen welke ik werk. Als mijn stukje code dan bijvoorbeeld 10 SQL connecties gebruikt, van de 127 beschikbare binnen mijn connectiepool en er worden meer dan 10 threads tegelijkertijd van afgesplitst dan wordt het allemaal een beetje spannend :/

Ik zie mezelf dan ook genoodzaakt om binnenkort de connectie mee te geven in de constructor, maar vind het gewoon niet netjes. Daarom vroeg ik me af of er andere manieren zijn om zoiets toch netjes te implementeren en het schaalbaar te houden.

@questa: Omdat de SqlConnection op een ander abstractieniveau ligt, logisch gezien. Technisch gezien is het natuurlijk wel te doen.

@whoami: Waarom de statische methods? Dat gaat een beetje tegen het objectgeorienteerde in, of zie ik dat verkeerd? :+

Bedankt voor de reacties tot nu toe iig :)
Je kunt het beter, als je het echt 'netjes' object georienteerd aan wil pakken, anders opzetten. Je domein objecten moet je zo weinig mogelijk vervuilen met bijv database code en zo. Je kunt de database code heb beste in een andere laag zetten, namelijk de datamapper laag (zoals whoami ook al aanraad). Ik raad je aan om het volgende boek eens te gaan lezen:
patterns of enterprise application architecture, schrijver : Martin Fowler.
Hierin staan allerlei designpatterns om dit soort dingen goed aan te pakken.
Later, als je wat meer ervaring heb met het schrijven van dit soort applicaties hebt, kun je inderdaad beter een O/R mapper gebruiken.
Je zegt ook dat jou programma in een groter systeem moet werken, misschien kun je eens kijken hoe de ontwerpers van dat systeem het aangepakt hebben.

Met betrekking tot de database connecties: in je datamapper laag kun je het beste elke datamapper van een base klasse laten overerven en hieraan geef je de connectie mee, zo kun je bijv alle Auteuren en Boeken met 1 connectie opslaan of inladen.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
CyBoB schreef op 03 september 2004 @ 14:54:
er is afaik ook een c# voor hibernate!! hibernate voor jave werkte erg goed, misschien moet je hier eens naar kijken!!
!! :)

Het lullige is alleen dat NHibernate nog in het pre-alpha stadium is, als je open source oplossingen wilt zijn er wel betere te krijgen op dit moment.

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


  • Lethalis
  • Registratie: April 2002
  • Niet online
O/R mappers :|

Klinkt heel interessant. Ik ga denk ik ook eens wat boeken erover nalezen.

Bedankt voor de reacties iig :) Ik vind het altijd leuk om nieuwe dingen te leren _/-\o_

Ask yourself if you are happy and then you cease to be.


  • pjvandesande
  • Registratie: Maart 2004
  • Laatst online: 21-05 14:59

pjvandesande

GC.Collect(head);

Download gewoon de demo is van LLBLGen Pro, kun je er zelf even mee spelen en bekijken of dit iets is wat je wilt.
Pagina: 1