Toon posts:

[.NET/C#/SQLServer] Data-tier generator released

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

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb mn data-tier generator gereleased vandaag. De tool, LLBLGen, genereert aan de hand van een gegeven SQLServer 7 of SQLServer 2000 database per table een C# class en bijbehorende insert/update/selectPK/selectall/selectFK/delete stored procedures. De code generation is tweakable, dus als je iets niet zindt in de gegenereerde code dan kun je dmv opties het generatieproces sturen. De classes zijn meteen te compileren in een assembly die kan worden gebruikt als data-access layer voor de gegeven database. Alle gegenereerde code is gemodelleerd aan de hand van handgeschreven productiecode en eventueel van veelvuldig commentaar te voorzien (tweakable) zodat de code uitbreidbaar is wanneer je meer features wilt toevoegen aan de classes of de stored procedures.

Uiteraard is LLBLGen gratis en open source (BSD license).

Directe download links:
Source: http://www.sd.nl/pages/files/LLBLGen_Src_1.0.04182002.zip
Executable: http://www.sd.nl/pages/files/LLBLGen_Exe_1.0.04182002.zip
Meer info: http://www.sd.nl/software/

Het is mn C# leerproject geweest en ik hoop dat veel C# / .NET developers hier er wat aan hebben, het scheelt namelijk nogal wat tijd: zelf met de hand die data-tier intikken of genereren :)

Acties:
  • 0 Henk 'm!

  • Yannick
  • Registratie: December 2000
  • Laatst online: 26-03-2024

Yannick

Bub MC

Ziet er erg vet uit! GA het binnenkort eens proberen.

Tot nu toe gebruikte ik altijd deze (zonder stored procs helaas):
http://yzcsharp.yyyz.net/

Acties:
  • 0 Henk 'm!

Verwijderd

Lijkt me cool! Ik zal er binnenkort eens naar gaan kijken, want het zou wel ideaal zijn :).

Otis: is you Frans Bouma :? Die naam staat er namelijk vernoemd...

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op woensdag 24 april 2002 14:27 schreef KoenM het volgende:
Lijkt me cool! Ik zal er binnenkort eens naar gaan kijken, want het zou wel ideaal zijn :).
:)
Ja als je al een aantal van die dingen met de hand hebt lopen kloppen dan weet je hoeveel tijd je er aan kwijt bent... (en hoe saaaaaaai het is. :))
Otis: is you Frans Bouma :? Die naam staat er namelijk vernoemd...
Correct :)

Acties:
  • 0 Henk 'm!

Verwijderd

Op woensdag 24 april 2002 14:36 schreef Otis het volgende:
Ja als je al een aantal van die dingen met de hand hebt lopen kloppen dan weet je hoeveel tijd je er aan kwijt bent... (en hoe saaaaaaai het is. :))
:X, ik durfde het niet te zeggen, maar je hebt helemaal gelijk. Laatst maakte ik bug tracken uit voor saai en ongeschoold werk, en daar was niet iedereen het mee eens, om het subtiel uit te drukken :)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Al enig feedback beschikbaar, mannen? :) Vooral blob retrieval heb ik niet goed kunnen testen, als iemand een database met blobs heeft en de generated code daarop los wil laten: graag! :)

Acties:
  • 0 Henk 'm!

Verwijderd

bij het bedrijf waar ik werk hadden ze een soortgelijke tool gebouwd (GenerationX), wat wel cool was eraan was dat er en xml-bestand werd opgebouwd met alle info en dat aan de hand van xslt templates de code werd gegenereerd. Als de code uitgebreid/veranderd moest worden was het dus gewoon een kwestie van templates aanpassen...

Acties:
  • 0 Henk 'm!

Verwijderd

Op donderdag 25 april 2002 10:20 schreef Otis het volgende:
Al enig feedback beschikbaar, mannen? :) Vooral blob retrieval heb ik niet goed kunnen testen, als iemand een database met blobs heeft en de generated code daarop los wil laten: graag! :)
Ik heb nu helaas geen tijd, maar ik kan haast niet wachten tot komend weekend, dan zal ik dit tooltje eens flink laten stressen >:). Ben heel benieuwd :).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 10:28 schreef KoekenBoes het volgende:
bij het bedrijf waar ik werk hadden ze een soortgelijke tool gebouwd (GenerationX), wat wel cool was eraan was dat er en xml-bestand werd opgebouwd met alle info en dat aan de hand van xslt templates de code werd gegenereerd. Als de code uitgebreid/veranderd moest worden was het dus gewoon een kwestie van templates aanpassen...
Heb ik ook aan zitten denken in 1e instantie, alleen is het schrijven van XSL(T) templates die C# code genereren niet 1 2 3 gedaan, omdat codegeneratie een vrij straightforward gebeuren is en IMHO alleen via een omweg te mappen is op patternmatching mechanismes zoals XSL(T). Petje af dat gelukt is daar bij jou.:) Het is voor VB.net en andere talen wellicht wel leuk dat er ook in hun taal code wordt gegenereerd, je kunt die dan in je eigen taal aanpassen, alhoewel dat niet echt hoeft, je kunt de C# classes weer als baseclass gebruiken voor nieuwe classes in bv VB.net, waar je extra code in stopt die je handmatig toevoegd.

Template based is uiteraard wel beter. Zeker met bv xslt, die je ook weer kunt genereren voordat je code gaat genereren. Maar simpel lijkt het me zeker niet.

Acties:
  • 0 Henk 'm!

Verwijderd

zo ongewikkeld was het niet hoor. Je moet er alleen voor zorgen dat je xml structuur voldoende informatie bevat.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
ff wat opmerkingen... ik heb hem getest op een database met zo'n kleine 250 tabellen en het werkt perfect ALLEEN:

Een optie om clsarp_ArtPars.cs naar Arp_ArtPars.cs te noemen...dat cls voor de klasse naam is natuurlijk neit de bedoeling in VS.NET volgende style guide van Mic doen we dat middels MyClass.cs ipv clsMyClass.cs

Verder erg erg erg welkom tooltje, maar die optie zou wel heel fijn zijn. Ik duik in het weekend de code, wellicht dat ik nog iets bruikbaars voor je heb als wederdienst.

trouwens volgens de C# guidelines:

param : strMyParam
private: _myPrivate
static protected: s_myProtected
property: MyProperty

class: MyClass

ga zo maar door, pas geleden trouwens een goed topic over geweest wat nu precies de style van MS is voor C#... Het is echt aan te raden consistent met de rest van het FrameWork te blijven

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 11:34 schreef paulgielens het volgende:
ff wat opmerkingen... ik heb hem getest op een database met zo'n kleine 250 tabellen en het werkt perfect ALLEEN:

Een optie om clsarp_ArtPars.cs naar Arp_ArtPars.cs te noemen...dat cls voor de klasse naam is natuurlijk neit de bedoeling in VS.NET volgende style guide van Mic doen we dat middels MyClass.cs ipv clsMyClass.cs
Noted. Ik zal hiervoor een optie maken. Je kunt dit in de code makkelijk wijzigen, op regel 248 van clsTable.cs.
Verder erg erg erg welkom tooltje, maar die optie zou wel heel fijn zijn. Ik duik in het weekend de code, wellicht dat ik nog iets bruikbaars voor je heb als wederdienst.
Mooi! :) Zoals je wellicht aan de code ziet, gebruik ik een eigen coding style, maar het is vooral bij code generation noodzaak dat de handel die gegenereerd wordt beantwoord aan de codingstyle van de gebruiker, en in het kader van de C# generatie is er nog veel ruimte voor tuning parameters.
trouwens volgens de C# guidelines:
param : strMyParam
private: _myPrivate
static protected: s_myProtected
property: MyProperty

class: MyClass

ga zo maar door, pas geleden trouwens een goed topic over geweest wat nu precies de style van MS is voor C#... Het is echt aan te raden consistent met de rest van het FrameWork te blijven
Mja, daarover zijn de meningen verdeeld. Ik heb de page van KoenM gelezen net en er zitten wel leuke dingen in, maar niet die me echt aanspreken, (MS vind ik ook niet echt consistent, maar het is meer een kwestie van smaak denk ik). De prefixes zijn echter table based, dus verschillende tables aanmaken voor verschillende codingstyles is makkelijk inpasbaar en ga ik zeker toevoegen. Met de hand kun je nu de prefix tables onder in clsLLBLGenerator.cs al aanpassen, maar het is wellicht niet helemaal toereikend.

Bedankt voor de feedback! Ik was me niet bewust van de noodzaak die de MS' voorgeschreven codingstyle voor veel mensen is, dus voor de generator is dat toch wel een must-have feature.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
ik heb hem links en rechts al aangepast en ben aan het stress testen met een nog grotere DB... ik post tegen het eind van de middag nog wat nuttige opmerkingen

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Ok Otis... ik heb de tool ondertussen flink vertimmert. Wij gebruiken bv een eigen BugTracker welke ik dus in de parser ingebouwd heb. "cls" eruit gesloopt, ik wil dus geen vb achtige zaken. Natuurlijk ook even die enum verbouwt. Verder moet ik zegggen dat dat progje rete stabiel is, petje af. Wij hebben toch geen misselijke backend dacht ik zo dus ik was behoorlijk onder de indruk van de snelheid/stabiliteit. Links en recht heb ik ook wat veranderd aan de style zodat deze conform de style guide is van MS zijn FrameWork style.

Zou je mij eens uit kunnen leggen wat precies de reden is van een DataTable als return van de data? Gewoon ff de argumenten niet dat er iets mis mee is natuurlijk.

Ik denk dat als je dit tooltje enorm flexibel gaat maken, wellicht middels code templates voor syle guide's...de mogelijkheid je eigen connectie methode te definieren aangezien ik bv niet middels een config file de conm string wens op te halen... je een commerciel aantrekkelijk product in handen hebt. Ik zou er iig wel een paar centen voor over hebben mocht je support etc kunnen leveren.

Ik werk in het weekend nog wat wellicht dat ik een wat interface aanpassingkjes maak etc, moet je maar zien wat je er mee doet. Morgen ga ik ff de code testen door de dataaccess layer te stress testen (de gegenereerde dus).

mooi werk, jammer dat niet meer mensen het nut van de tool inzien. (gezien de posts)

Acties:
  • 0 Henk 'm!

  • Nexopheus
  • Registratie: Juni 2001
  • Laatst online: 20-08-2024
Op donderdag 25 april 2002 19:18 schreef paulgielens het volgende:
1 ... je een commerciel aantrekkelijk product in handen hebt. Ik zou er iig wel een paar centen voor over hebben mocht je support etc kunnen leveren.

2mooi werk, jammer dat niet meer mensen het nut van de tool inzien. (gezien de posts)
ad 1)
NEEEE! niet commercieel maken, ik wil er nog graag wat van leren !!

ad 2)
Erg nuttige tool indeed, heb nog geen tijd gehad om alles goed te testen (SQL Server doet een beetje vreemd!)

Wat niet kan is nog nooit gebeurd


Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Dan toch maar even posten: Ik zie er wel degelijk het nut van in :) .

Ik heb er ondertussen een aantal Java-database projectjes op zitten en voor elk project heb ik opnieuw deze stuff geschreven (met wel veel generieke super-classes).

Ik heb wel door de jaren heen steeds mijn ontwerpen en implementaties verbeterd en dat zorgde er (ivm een te puristische instelling) vaak voor dat ik oude projecten ook weer ging aanpassen als ik er weer eens mee aan de slag moet.

Ondertussen speelde ik dus ook met de gedachte om deze stuff volledig te gaan generen omdat je toch niet alles met generieke abstracties kunt oplossen. Dit zorgt er dus voor dat als je het design van de code die de generator uitspuigt verbeterd gelijk overal deze aanpassingen zijn doorgevoerd en dat is dus precies wat ik nodig heb :) .

Helaas is het er nog steeds niet van gekomen, maar ik begin er nu steeds harder over te denken om het alsnog te gaan doen. Stratego is hier namelijk een uitmuntende taal voor, zeker nu er Stratego uitgebreid is met concrete-syntax mogelijkheden voor de talen waar je transformaties op uit voert. Dit betekent dat je de transformaties gewoon kunt beschrijven in de taal waarop je werkt (C# of Java bijv) maar dat op de achtergrond abstract syntax trees gebruikt worden.

Een generator schrijven is met deze concrete syntax en een goede pretty-printer werkelijk een fluitje van een cent (relatief dan natuurlijk ;) ). De lastigste beslissing is wat je configureerbaar maakt en hoe...

Hulde dus voor dit projectje! :) (heb nog niet naar de code gekeken)...

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 19:18 schreef paulgielens het volgende:
Ok Otis... ik heb de tool ondertussen flink vertimmert. Wij gebruiken bv een eigen BugTracker welke ik dus in de parser ingebouwd heb. "cls" eruit gesloopt, ik wil dus geen vb achtige zaken. Natuurlijk ook even die enum verbouwt.
heh :)
Verder moet ik zegggen dat dat progje rete stabiel is, petje af. Wij hebben toch geen misselijke backend dacht ik zo dus ik was behoorlijk onder de indruk van de snelheid/stabiliteit.
Stabiliteitsproblemen kom je met testen snel tegen (en oh, wat heb ik die vaak gezien ;) vandaar ook mn eigen exception viewer die erin zit, dan schiet het nog een beetje op :)), snelheidsproblemen heb ik niet gehad, behalve op MSDE, daar is de query gigatraag door de beperking van max 5 concurrent transactions. Ik heb zoveel mogelijk redundant code vermeden (dus bv 1 keer bepalen welke params je hebt en daarmee alle routines mee maken).
Links en recht heb ik ook wat veranderd aan de style zodat deze conform de style guide is van MS zijn FrameWork style.
Ja die output moet veel flexibeler merk ik nu. De T-SQL lijkt me wel vrij duidelijk, maar de C# code wil je toch uitbreiden met andere code vaak... ga'k zeker inbouwen!
Zou je mij eens uit kunnen leggen wat precies de reden is van een DataTable als return van de data? Gewoon ff de argumenten niet dat er iets mis mee is natuurlijk.
Je bedoelt als return van de selects? De PK select zou in de properties kunnen returnen, maar bij meerdere rows lukt dat niet. Je kunt dan kiezen uit DataReader, DataSet of DataTable. Ik heb niet gekozen voor een DataReader, omdat de connection dan open blijft en je geen black box data-access layer kunt maken, je geeft een open data-reader object terug, naar de caller, wat ik niet fraai vind, immers het is een datatransfer over een tier-grens. DataSet vond ik te log voor dit, omdat de resultset bestaat uit 1 set rows. Vandaar DataTable.
Ik denk dat als je dit tooltje enorm flexibel gaat maken, wellicht middels code templates voor syle guide's...de mogelijkheid je eigen connectie methode te definieren aangezien ik bv niet middels een config file de conm string wens op te halen... je een commerciel aantrekkelijk product in handen hebt. Ik zou er iig wel een paar centen voor over hebben mocht je support etc kunnen leveren.
Valt tegen hoor: om iets commercieel op de markt te zetten is het bouwen van een tool 1 ding, maar de rest die er bij komt kijken: documentatie, flexibiliteit in de features, functionaliteit die veel mensen aanspreekt maar jezelf waarschijnlijk niet etc. En het allermoeilijkst bij een tool/systeem: een developer overtuigen dat de tool hem veel werk bespaart en veel tijd scheelt tov de methode die hij/zij nu gebruikt. Is een lange weg. :) (dat merken we aan ons CMS CESys, mooi systeem, gemaakt voor de verkoop, maar overtuig mensen maar eens dat ze die tool moeten kopen. :))
Ik werk in het weekend nog wat wellicht dat ik een wat interface aanpassingkjes maak etc, moet je maar zien wat je er mee doet. Morgen ga ik ff de code testen door de dataaccess layer te stress testen (de gegenereerde dus).
Klinkt goed! Ik heb de aanwijzigen die je tot nu toe hebt geopperd al in een todo lijst gezet, daar ga ik volgende week aan werken, tezamen met de Delete Triggers voor foreign keys.
mooi werk, jammer dat niet meer mensen het nut van de tool inzien. (gezien de posts)
Dank :) Ach, valt wel mee. Veel mensen zitten niet met tiers te werken maar werken met data-adapters direct achter een form, *shiver* , of vinden het gewoon fijn om alles met de hand in te kloppen (aaaarg!:) ). In de afgelopen 2 jaar heb ik iets van 85.000 regels code aan data-access layer spul geprogrammeerd met de hand (VB6 - T-SQL) en op een gegeven moment dan wil je gewoon niet nog zo'n layer maken. :)

Acties:
  • 0 Henk 'm!

Verwijderd

ik zat net ff dit tooltje te testen, maar volgens mij gaat er wat fout ;(. Alle fields en properties ontbreken... Enig idee waardoor dit komt? Aan de rechten kan het niet liggen, aangezien ik als sa aanlog... Verder heb ik gewoon SQL Server 2000 Standard...
Jammer, want het ziet er zo cool uit! Alleen de naming van de classes en variabelen is niet helemaal mijn stijl, dus als dat ook nog flexibel gemaakt kan worden (zoals paulgielens al voorstelt), ben ik helemaal blij :).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 19:30 schreef mbravenboer het volgende:
Dan toch maar even posten: Ik zie er wel degelijk het nut van in :) .
Iedereen die meerdere data-tiers heeft gebakken met de hand, kent dat nare gevoel als je het af hebt en terugkijkt en je beseft... dit lijkt wel heel erg op die data-tier van dat project, alleen andere parametes. :))
Helaas is het er nog steeds niet van gekomen, maar ik begin er nu steeds harder over te denken om het alsnog te gaan doen. Stratego is hier namelijk een uitmuntende taal voor, zeker nu er Stratego uitgebreid is met concrete-syntax mogelijkheden voor de talen waar je transformaties op uit voert. Dit betekent dat je de transformaties gewoon kunt beschrijven in de taal waarop je werkt (C# of Java bijv) maar dat op de achtergrond abstract syntax trees gebruikt worden.
Klinkt interessant!
Een generator schrijven is met deze concrete syntax en een goede pretty-printer werkelijk een fluitje van een cent (relatief dan natuurlijk ;) ). De lastigste beslissing is wat je configureerbaar maakt en hoe...
Je verzandt snel in if-then-else crapcode. Maar als je het een beetje aanpakt als een normale code emitter dan valt het nog wel mee. :)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 20:44 schreef KoenM het volgende:
ik zat net ff dit tooltje te testen, maar volgens mij gaat er wat fout ;(. Alle fields en properties ontbreken... Enig idee waardoor dit komt? Aan de rechten kan het niet liggen, aangezien ik als sa aanlog... Verder heb ik gewoon SQL Server 2000 Standard...
Fields in de stored procedures?

Open eens Query Analyzer en kies de database in kwestie en run de volgende query: (vul op de 2e regel even de naam van de table in)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
DECLARE @sTableName varchar(250)
SET @sTableName='mytable'

SELECT INFORMATION_SCHEMA.COLUMNS.*,
(
    SELECT COLUMNPROPERTY(OBJECT_ID(@sTableName), INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME, 'IsComputed')
) AS IsComputed,
(
    SELECT COL_LENGTH(@sTableName, INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME)
) AS ColumnLength,
(
    SELECT COLUMNPROPERTY(OBJECT_ID(@sTableName), INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME, 'IsIdentity')
) AS IsIdentity,
(
    SELECT COLUMNPROPERTY(OBJECT_ID(@sTableName), INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME, 'IsRowGuidCol')
) AS IsRowGuidColumn,
(
    ISNULL( 
    (
        SELECT   CASE INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE
                    WHEN 'PRIMARY KEY' THEN 1
                END
        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE INNER JOIN 
            INFORMATION_SCHEMA.TABLE_CONSTRAINTS ON 
            INFORMATION_SCHEMA.KEY_COLUMN_USAGE.CONSTRAINT_NAME=
            INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_NAME
        WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME = @sTableName
            AND INFORMATION_SCHEMA.KEY_COLUMN_USAGE.COLUMN_NAME = 
            INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME
            AND INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'PRIMARY KEY'
    ), 0)
) AS IsPrimaryKey,
(
    ISNULL( 
    (   
        SELECT   CASE INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE
                    WHEN 'FOREIGN KEY' THEN 1
                END
        FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE INNER JOIN 
            INFORMATION_SCHEMA.TABLE_CONSTRAINTS ON 
            INFORMATION_SCHEMA.KEY_COLUMN_USAGE.CONSTRAINT_NAME=
            INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_NAME
        WHERE INFORMATION_SCHEMA.KEY_COLUMN_USAGE.TABLE_NAME = @sTableName
            AND INFORMATION_SCHEMA.KEY_COLUMN_USAGE.COLUMN_NAME = 
            INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME
            AND INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY'
    ), 0)
) AS IsForeignKey
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @sTableName

Krijg je een rijtje records? Of een error?

Acties:
  • 0 Henk 'm!

Verwijderd

nop ;(. Krijg helemaal niks terug... kan dit komen omdat m'n SQL Server een beetje brak is? Het lijkt wel alsof hij niet altijd even goed opstart... de tabellen worden wel goed opgehaald, ik zal ff kijken waar dit statement fout gaat...

Edit: Vreemd, ook als ik alleen 'SELECT * FROM INFORMATION_SCHEMA.COLUMNS' doe krijg ik niks terug... ik gok dat er op m'n server iets goed fout is :'(.

Edit2: Nog een klein puntje: als je vergeet een database naam invult zou het prettig zijn om een waarschuwing te krijgen, lijkt me :).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 20:56 schreef KoenM het volgende:
nop ;(. Krijg helemaal niks terug... kan dit komen omdat m'n SQL Server een beetje brak is? Het lijkt wel alsof hij niet altijd even goed opstart... de tabellen worden wel goed opgehaald, ik zal ff kijken waar dit statement fout gaat...
Edit: Vreemd, ook als ik alleen 'SELECT * FROM INFORMATION_SCHEMA.COLUMNS' doe krijg ik niks terug... ik gok dat er op m'n server iets goed fout is :'(.
whoops, dan is er idd wat mis, ook op de 'master' database? (ik krijg hier wel gewoon records terug).
Edit2: Nog een klein puntje: als je vergeet een database naam invult zou het prettig zijn om een waarschuwing te krijgen, lijkt me :).
Daar zit een validating event handler op... Ik stop die alleen wanneer het scherm wordt geclosed, want als je 'cancel' klikt, dan wil je niet een melding krijgen dat je de catalognaam nog moet invullen. Noted in the todo list:)

Acties:
  • 0 Henk 'm!

Verwijderd

Op donderdag 25 april 2002 21:05 schreef Otis het volgende:
whoops, dan is er idd wat mis, ook op de 'master' database? (ik krijg hier wel gewoon records terug).
Yep, op al m'n databases krijg ik niks terug... Volgens mij is m'n database server naar de klote, want als ik op properties klik krijg ik: 'could not find stored procedure xp_instance_regread'.

Na goed, ik zal eerst deze problemen oplossen, voordat ik dit topic nog meer vervuil, want dit heeft dus niks met je mooie tooltje te maken...

Acties:
  • 0 Henk 'm!

  • mbravenboer
  • Registratie: Januari 2000
  • Laatst online: 07-10-2022
Otis: Klinkt interessant!
Zeker, dat is het ook :) . Voor kleine transformaties maakt abstracte of concrete syntax niet zoveel uit (abstract syntax trees in herschrijvingen zijn dan vaak vrij klein), maar voor echte code-generatie is het werkelijk een zegen...

Je kunt dan op een buitengewoon fraaie manier echte abstract syntax trees opbouwen (je bent dus geen stringetjes aan het plakken) terwijl je toch in een hele compacte (en uiteraard bekende) concrete syntax werkt...

Extreem voorbeeld: de Stratego compiler was altijd al geschreven in Stratego (compilerend naar C), maar maakte dus gebruik van abstracte syntax trees voor Stratego en C. Nu kan gewoon gebruik gemaakt worden van de concrete syntax van Stratego en C, wat de code veel duidelijker en compacter maakt.

Wel heb je nu dus concrete Stratego syntax in een Stratego programma 8-) .

Blog, Stratego/XT: Program Transformation, SDF: Syntax Definition, Nix: Software Deployment


Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
De tool werkt 100% ik heb hem tegen 5 verschillende SQL 7 servers aangetest met alleen andere db's. Allen 700 tabellen +. Heb net snel nog even een copy getrokken tegen onze test sql 2000 server en die werkt ook zonder problemen.

Het ligt dus 100% zeker aan de sql server, zeker niet aan de tool.


Ja nu vat ik hem waarom je een DataTable gekozen hebt... vrij logisch zelfs. Ik heb tot nu toe alleen maar datasets gebouwt...

data (LLBL stored proc)
----
dataaccess (LLBL dataaccess layer)
----
systemframework (BugTracking, Profiling, Logging)
----
common (data->datasets, specifieke methodes voor business + registry shit)
----
businessrules
businessfacade
----
presentation - webservices
______________ presentation


Zo ziet de app er ongeveer uit, is een process besturingssysteem wat bovenop een FrameWork hangt geschreven in Java.

Hier gaat jouw gegenereerde code dus dienst in doen. Dat de mensen die n-tier oplossingen even weten dat een dergelijke tool een dag weer goed kan maken.


Otis: http://www.exocortex.org/3dengine/

Hier zit een foldertje diagnostics in met een BugTracking systeem en een Profiler om code segmenten door te meten kwa executie tijd... erg tof om over een n-tier applicatie je batches te traces. De implementatie van die klassen zijn middels linked listen en hashmaps geregeld. Tevens vind je enkele andere leuke code fragmenten in deze app. Laat je oog er eens op vallen/zeer leerzaam en nuttig om in je app te verweven.

VERGETEN: Heb jij er wel rekening mee gehouden dat het zeer waarschijnlijk is het component bevattende de LLBL classen binnen MTS draaien? Iig de update en insert methodes horen transactioneel te zijn "toch". Uhm heb jij hier al aan gedacht of een invulling aan gegeven? Dit zou dus betekenen dat alle classen van serviced component moeten erven. en transaction.required moeten voeren.

Acties:
  • 0 Henk 'm!

  • brammetje
  • Registratie: Oktober 2000
  • Laatst online: 12-01 11:31
Otis: je hebt het wel eens aangekondigd en toen was ik al nieuwsgierig.. Ik heb op het moment weinig tijd om er naar te kijken, maar ga het zeker gebruiken..

tnx!

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
mmm bij mij loopt dat SQL script niet...

ik krijg syntax problemen op de regels:
SELECT @iErrorCode=@@ERROR
in dat script

Enig idee wat waar hoe?

Ook als ik error code uitvink gaan alle Stored Procedures in de knoop...

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 26 april 2002 09:28 schreef paulgielens het volgende:
mmm bij mij loopt dat SQL script niet...
ik krijg syntax problemen op de regels:
SELECT @iErrorCode=@@ERROR
in dat script
Enig idee wat waar hoe?
Raar, hier lopen alle gegenereerde T-SQL scripts naar behoren.

De enige known issue die ik gezien heb is dat hij wel een WHERE statement genereert maar geen clause erachter bij tables zonder Primary Key, maar imho komt dat nooit voor. Welke error krijg je? is @iErrorCode int OUTPUT ook gegenereerd in de header van de stored proc?

Ik test hier nog ff een paar t-sql scripts

edit:

Werkt hier ok. Mail me anders ff een stored proc die fout gaat. (frans at sd dot nl)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 25 april 2002 21:45 schreef paulgielens het volgende:
Otis: http://www.exocortex.org/3dengine/
Hier zit een foldertje diagnostics in met een BugTracking systeem en een Profiler om code segmenten door te meten kwa executie tijd... erg tof om over een n-tier applicatie je batches te traces. De implementatie van die klassen zijn middels linked listen en hashmaps geregeld. Tevens vind je enkele andere leuke code fragmenten in deze app. Laat je oog er eens op vallen/zeer leerzaam en nuttig om in je app te verweven.
Ik zal der induiken! :)
VERGETEN: Heb jij er wel rekening mee gehouden dat het zeer waarschijnlijk is het component bevattende de LLBL classen binnen MTS draaien? Iig de update en insert methodes horen transactioneel te zijn "toch". Uhm heb jij hier al aan gedacht of een invulling aan gegeven? Dit zou dus betekenen dat alle classen van serviced component moeten erven. en transaction.required moeten voeren.
Kijk, dit zijn dingen die je snel vergeet als je het niet bouwt voor een commerciele release :).

De update/insert/delete statements in de stored procs zijn transactions op zich (elk T=SQL statement is een transaction). Gaat een insert fout, dan is de insert niet geslaagd. Echter, is de C# class inderdaad een onderdeel van een transaction (en de stored proc dus ook), dan zou de class wel moeten omvallen. Alle classes erven van de baseclass, die zou dan transaction aware moeten worden. Ik heb dit in .NET/C# nog niet bij de hand gehad, moet je verder nog iets doen in de class zelf? (een contect abort aanroepen?). Die code kan dan mooi in de base class weggewerkt worden. Noted :)

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
om in 1`record op te halen uit een tabel via een prim key waarde zeg 10. Hoe doe je da?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 26 april 2002 13:14 schreef paulgielens het volgende:
om in 1`record op te halen uit een tabel via een prim key waarde zeg 10. Hoe doe je da?
SELECT * FROM Table WHERE PKFIELD1=10

Maar ik heb het vermoeden dat je dit niet wilde vragen :)

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Ik instantier de gegenereerde klasse MyTable nu will ik een

Mytable.Select() aanroepen om 1 record op te halen... ik neem aan dat ik dan eerst de property moet zetten ofzo?

Hoe ziet de implementatie achter die DataAccess van jouw eruit/

[b]EDIT:[\b]
gvd: Geen prim keys op me db. Ik heb bij het importeren van de data naar mjin test DB vergeten copy all objects, dus inclusief all prim keys etc. Dus ik zou ook nog een optie inbouwen dat zodra er geen prim key op een tabel gedefinieerd is de Select() opdracht niet mee geparsed word in de code bestanden.

-> zo krijg je natuurlijk wel gebruikers gerichte feedback ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 26 april 2002 13:54 schreef paulgielens het volgende:
[b]EDIT:[\b]
gvd: Geen prim keys op me db. Ik heb bij het importeren van de data naar mjin test DB vergeten copy all objects, dus inclusief all prim keys etc. Dus ik zou ook nog een optie inbouwen dat zodra er geen prim key op een tabel gedefinieerd is de Select() opdracht niet mee geparsed word in de code bestanden.
Was al geplanned deze optie, want ik kreeg hem ook 1 keer op een database, bleek dat ik 1 table vergeten was van een PK te voorzien. :)
-> zo krijg je natuurlijk wel gebruikers gerichte feedback ;)
hehe :)

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
ff wat aanpassingen

Alle sproc klassen even voorzien van een disposer, het wordt een grote rommel als je dat niet doet namelijk. En ff Enterprise services meenemen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using System.EnterpriseServices;

: IDisposable

        /// <summary>
        /// Dispose of this StoredProcedure.
        /// </summary>

        public void Dispose()
        {
            if ( command != null )
            {
                SqlConnection connection = command.Connection;
                Debug.Assert( connection != null );
                command.Dispose();
                command = null;
                connection.Dispose();
            }
        }

Naar alle waarschijnlijkheid bouwt de gebruiker een wrapper binnen de DataAccess assemblie, zodat alle klassen transactioneel moeten zijn:
code:
1
2
3
4
5
using System.EnterpriseServices;

    [ Transaction( TransactionOption.Required ) ]
    [ ComVisible( true ) ]
: ServicedComponent

In het geval van de klassen per tabel moet je even in de try catch blokken:
code:
1
2
3
4
5
6
7
try{
ContextUtil.SetComplete();
}
catch{
ContextUtil.SetAbort();
throw excp; // fout naar business gooien
}

En vergeet ff niet alle klassen binnen de DataAccess als Transaction.Supported aan te duiden. Nu kun je naar hartelust in de Business Logica zaken transactioneel bundelen zonder dat de zaak breekt, doordat de Data-tier generator op dit moment nog geen transactionele aplpicaties ondersteund.

Otis: wellicht dat je er iets aan hebt, mocht ik ergens een denkfoutje maken hoor ik het graag, anders heb ik me eigen app ook verneukt ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Een dispose hoeft op zich niet, want de GC ruimt de boel zelf op, althans dat is wat ik er van begrepen heb. Wellicht dat icm COM+ er wel een dispose method bij moet.

Ik heb de gui nu sterk uitgebreid, met tabs zodat er veel meer ruimte is voor opties :). De C# generator moet COM+ services meegenereren indien aangeklikt, dus Transaction support, JIT en object pooling (de rest is niet interessant).

Ben nu de docs voor COM+ serviced components aan het doornemen, want heb met .net daar geen ervaring mee. Alle mogelijke opties meegenereren is geen doen, maar volgens mij ook niet nodig. De baseclass maak ik, indien COM+ serviced component features zijn geenabled, derived van serviced component, dan zijn alle table classes ook meteen daar vanaf geleid.

De committing/aborting van transactions heb ik wonderwel nog niet gezien, behalve de autocommit attribute.

Zodra er code uitrolt uit deze beta, dan mail ik je een testversie, ik heb hier geen COM+/transaction code klaarstaan om te testen. (maar dat kan nog wel een week of 2 duren denk ik, max)

edit:

Ok, die CotextUtil class is degene die ik moet hebben. Blijkt toch allemaal ong. hetzelfde te zijn als MTS development in VB6 :)

Acties:
  • 0 Henk 'm!

  • Yannick
  • Registratie: December 2000
  • Laatst online: 26-03-2024

Yannick

Bub MC

Geweldige tool! Ik heb echter een paar probleempjes:
- Heb de Prefix Variables (HC) optie uitgezet, maar krijg dan bij het compileren van de .cs files de melding:
"the name 'm_ErrorCode' does not exist in the class or namespace 'Yannick.DA.clsMyTable'" voor alle tabellen. Als ik naar de source kijk blijkt ook dat m_ErrorCode en m_iErrorCode door elkaar worden gebruikt.
- Ik krijg een aantal foutmeldingen bij het uitvoeren van het gegenereerde sql script:
code:
1
2
3
4
5
Server: Msg 156, Level 15, State 1, Procedure da_contact_SelectAll, Line 15
Incorrect syntax near the keyword 'SELECT'.
Server: Msg 2717, Level 16, State 2, Procedure da_Guestbook_Insert, Line 0
The size (8000) given to the parameter '@sMessage' exceeds the maximum allowed (4000).
Parameter '@sMessage' has an invalid data type

De fout near 'SELECT' slaat op de regel:
code:
1
SELECT @iErrorCode=@@ERROR

en komt meerdere malen voor
De tweede fout betreft een tabel met een nvarchar(4000) veld (slecht db design van mij?).

En nog wat vraagjes over design:
- ik heb altijd geleerd om een class variabele niet direct te gebruiken maar middels set en get aan te spreken (vraag me niet waarom). Heb je hier een reden ervoor om dat niet te doen? Zoiets dus:
code:
1
2
3
4
5
public string naam
{ 
   get  {return m_naam; }
   set  {m_naam=value; }
}

- Zou het niet handig zijn om bij het setten van de parameters voor de insert() methode eerste een check te doen of de waarde niet null is? Op die manier zou je de database kunnen vullen met een DBNull.Value waarde ipv dat hij een foutmelding geeft.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Ik probeer het je:

Serviced components draaien zoals je weet binnen MTS, en aangezien de CLR hier geen garbage collection over uit kan voeren moet je ofwel kun je het beste je eigen dispose methods invullen. Dit doe ik bv om het volgende. Indien je grote applicaties hebt met veel db benaderingen dan heb je weleens dat MTS onnoemelijk veel objecten aan gaat makenje kunt dit mooi zien in je MTS snap-in explorer. Door de Dispose/Activate zelf in te vullen weet je zeker dat jij je rommel te allen tijde netjes opruimt, zodat je die vreemde bugs kunt omzeilen die wij bv regelmatig tegenkomen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
        /// <summary>
        /// Deactivates this object at the end of a transaction.
        /// </summary>

        override protected void Deactivate()
        {
            if ( connection != null )
            {
                connection.Dispose();
                connection = null;
            }
        }


code:
1
2
3
4
5
6
7
8
9
10
11
        public void Dispose()
        {
            if ( command != null )
            {
                SqlConnection connection = command.Connection;
                Debug.Assert( connection != null );
                command.Dispose();
                command = null;
                connection.Dispose();
            }
        }

Klassen die transactioneel moeten verlopen krijgen het attribuut:
code:
1
[ Transaction( TransactionOption.Requered ) ]

Alle instanties van objecten binnen zon transactie klasse dienen transactie supported te zijn middels het attribuut:
code:
1
[ Transaction( TransactionOption.Supported ) ]

Nu kun je voor de void methods gewoon het attribuut:
code:
1
[AutoComplete]

Hierbij worden ContextUtil.SetComplete en Abort automatisch aangeroepen.

Voor de methodes vaak functies dus die een return waarde teruggeven gebruik je try-catch blokken, waardoor je autocomplete niet meer kunt gebruiken. Hierbij moet je expliciet Abort aanroepen indien je bv de catch induikt. Zoiets zou er zo uit kunnen zien:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        public status MyDatabaseTransaction (  )
        {
            try 
            {
                MyStatus status;

                // transactie #1
                status = BrokerStatus.pending;
                // acties

                ContextUtil.SetComplete();
                MyStatus.ready;
                return MyStatus;
            }
            catch
            {
                ContextUtil.SetAbort();
                throw;
            }
        }

Bovenstaand voorbeeld maakt gebruik van een enum welke de status van de transactie bijhoud. Dit is heel handig want dan kun je in je business logica veel eenvoudiger die final-state machine fixen aangezien je objecten acties uit kunt laten voeren relatief aan de status. Ik zou bv niet kunnen schrijven in de db, want een ander object is ergens onafhankelijk de db leeg aan het halen. Ik zet mijn actie om te schrijven even in een queue en start zodra het andere object klaar is. (deadlock opgelost). Ook voor debugging is dit erg makkelijk aangezien je nu transacties kunt tracen. Die status is een voorgedefinieerde enum.

Verder kan ik maar 1 tip geven, bestudeer het voorbeeld van Fitch & Mathers aangezien deze enorm kan helpen bij het hoe en waarom.

Let op de business logica kan ook transactioneel zijn om bv zaken te bundelendit staat echter los van jouw tool.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Op vrijdag 03 mei 2002 02:28 schreef Yannick het volgende:
Geweldige tool! Ik heb echter een paar probleempjes:
- Heb de Prefix Variables (HC) optie uitgezet, maar krijg dan bij het compileren van de .cs files de melding:
"the name 'm_ErrorCode' does not exist in the class or namespace 'Yannick.DA.clsMyTable'" voor alle tabellen. Als ik naar de source kijk blijkt ook dat m_ErrorCode en m_iErrorCode door elkaar worden gebruikt.
- Ik krijg een aantal foutmeldingen bij het uitvoeren van het gegenereerde sql script:
code:
1
2
3
4
5
Server: Msg 156, Level 15, State 1, Procedure da_contact_SelectAll, Line 15
Incorrect syntax near the keyword 'SELECT'.
Server: Msg 2717, Level 16, State 2, Procedure da_Guestbook_Insert, Line 0
The size (8000) given to the parameter '@sMessage' exceeds the maximum allowed (4000).
Parameter '@sMessage' has an invalid data type

De fout near 'SELECT' slaat op de regel:
code:
1
SELECT @iErrorCode=@@ERROR

en komt meerdere malen voor
De tweede fout betreft een tabel met een nvarchar(4000) veld (slecht db design van mij?).

En nog wat vraagjes over design:
- ik heb altijd geleerd om een class variabele niet direct te gebruiken maar middels set en get aan te spreken (vraag me niet waarom). Heb je hier een reden ervoor om dat niet te doen? Zoiets dus:
code:
1
2
3
4
5
public string naam
{ 
   get  {return m_naam; }
   set  {m_naam=value; }
}

- Zou het niet handig zijn om bij het setten van de parameters voor de insert() methode eerste een check te doen of de waarde niet null is? Op die manier zou je de database kunnen vullen met een DBNull.Value waarde ipv dat hij een foutmelding geeft.
Zorg dat je op alle tabellen een prim key hebt!

Error codes, klopt hebik ook alleen ik gebruik die verder niet aangezien alles al duidelijk te tracen is middels de try catch op een hoger nivo

Bv bij die connectiestring wordt een protected member direct aangeboden ipv een property. Is trouwens de beste manier aangezien de connectie string niet buiten het DA object mag komen en een propertie dus zinloos zou zijn. Is perfect zoals het is op het moment. Voor de klasse vars heb je helemaal gelijk verder.

Persoonlijk vind ik die m_ stijl van coden maar niks. Vooral omdat MS een complete eigen stijl heeft zodat je nooit conflicten krijgt in het .NET gebeuren. Het is dan ook sterk aan te raden om de guideliness te gebruiken zoals deze "hier" ergens te vinden zijn.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 03 mei 2002 02:28 schreef Yannick het volgende:
Geweldige tool! Ik heb echter een paar probleempjes:
- Heb de Prefix Variables (HC) optie uitgezet, maar krijg dan bij het compileren van de .cs files de melding:
"the name 'm_ErrorCode' does not exist in the class or namespace 'Yannick.DA.clsMyTable'" voor alle tabellen. Als ik naar de source kijk blijkt ook dat m_ErrorCode en m_iErrorCode door elkaar worden gebruikt.
Dit lijkt me een serieuze bug, noted. :)
- Ik krijg een aantal foutmeldingen bij het uitvoeren van het gegenereerde sql script:
code:
1
2
3
4
5
Server: Msg 156, Level 15, State 1, Procedure da_contact_SelectAll, Line 15
Incorrect syntax near the keyword 'SELECT'.
Server: Msg 2717, Level 16, State 2, Procedure da_Guestbook_Insert, Line 0
The size (8000) given to the parameter '@sMessage' exceeds the maximum allowed (4000).
Parameter '@sMessage' has an invalid data type

De fout near 'SELECT' slaat op de regel:
code:
1
SELECT @iErrorCode=@@ERROR

en komt meerdere malen voor
De tweede fout betreft een tabel met een nvarchar(4000) veld (slecht db design van mij?).
hij gaat dus verkeerd om met nvarchar fields, ok bug, noted. De size staat op 8000, maar omdat het nvarchar is, is de eigenlijke size maar 4000 (1 char is 2 bytes). Dit is een bug in llblgen.

Die select error is volgens mij dezelfde die Paul ook heeft gehad en die komt door dat er geen keys op de table zijn gedefinieerd.
En nog wat vraagjes over design:
- ik heb altijd geleerd om een class variabele niet direct te gebruiken maar middels set en get aan te spreken (vraag me niet waarom). Heb je hier een reden ervoor om dat niet te doen? Zoiets dus:
code:
1
2
3
4
5
public string naam
{ 
   get  {return m_naam; }
   set  {m_naam=value; }
}
? :) ik weet niet waar je op doelt, je bedoelt dat er geen public members in de classes mogen zitten? Dat is toch ook niet zo?
- Zou het niet handig zijn om bij het setten van de parameters voor de insert() methode eerste een check te doen of de waarde niet null is? Op die manier zou je de database kunnen vullen met een DBNull.Value waarde ipv dat hij een foutmelding geeft.
Dus support voor NULL values in feite? Op zich goed punt, wanneer je verschil wilt maken tussen de default value '0' bijvoorbeeld voor een int en NULL in een nullable field. Ik zal deze optie toevoegen. :)

Bedankt voor deze feedback! Ik hoop a.s.a.p. een nieuwe versie klaar te hebben met meer opties en uiteraard bugfixes.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 03 mei 2002 09:12 schreef paulgielens het volgende:
[..]
Error codes, klopt hebik ook alleen ik gebruik die verder niet aangezien alles al duidelijk te tracen is middels de try catch op een hoger nivo
Ze zijn voor sommige kleine routines overbodig, maar de gegenereerde code is bedoeld als basis voor uitgebreidere inserts bv. Je kunt bv je insert routine van 1 table uitbreiden met een insert in ook een andere table dat afhangt van een bepaalde toestand in de database. Error reporting is dan wel van belang.
Bv bij die connectiestring wordt een protected member direct aangeboden ipv een property. Is trouwens de beste manier aangezien de connectie string niet buiten het DA object mag komen en een propertie dus zinloos zou zijn. Is perfect zoals het is op het moment. Voor de klasse vars heb je helemaal gelijk verder.
Wat ik heb geprobeerd is de base class internal te maken, maar dat gaat niet, aangezien die errorcode property er in zit. Je kunt nu in theorie een instance maken van de baseclass en dus een public member hebben. Het kan natuurlijk via een property maar daarom is protected nu zo leuk :)

Die klassevars waar jij op doelt begrijp ik niet, ze zijn standaard private en hebben allen een property get/set pair.
Persoonlijk vind ik die m_ stijl van coden maar niks. Vooral omdat MS een complete eigen stijl heeft zodat je nooit conflicten krijgt in het .NET gebeuren. Het is dan ook sterk aan te raden om de guideliness te gebruiken zoals deze "hier" ergens te vinden zijn.
caMel style komt in de volgende versie, compleet met _memberVar en MyClass spul :) MS maakt er in de docs wel een potje van hoor, gister zag ik nog staan CMyClass :) Maar ik begrijp wat je bedoelt.

Dit is overigens wel hetgeen het moeilijk maakt een tool echt commercieel te releasen: hoe hard je ook nadenkt over features, zodra je het mensen laat gebruiken blijkt dat je lang alle features die er in hadden moeten zitten niet hebt geimplementeerd :)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 03 mei 2002 09:05 schreef paulgielens het volgende:
Serviced components draaien zoals je weet binnen MTS, en aangezien de CLR hier geen garbage collection over uit kan voeren moet je ofwel kun je het beste je eigen dispose methods invullen. Dit doe ik bv om het volgende. Indien je grote applicaties hebt met veel db benaderingen dan heb je weleens dat MTS onnoemelijk veel objecten aan gaat makenje kunt dit mooi zien in je MTS snap-in explorer. Door de Dispose/Activate zelf in te vullen weet je zeker dat jij je rommel te allen tijde netjes opruimt, zodat je die vreemde bugs kunt omzeilen die wij bv regelmatig tegenkomen.
Ok helder. Dat de CLR geen garbage collection doet van de MTS objects lijkt me een reden genoeg om ze idd zelf te implementeren. Is ook niet zo'n punt.
Alle instanties van objecten binnen zon transactie klasse dienen transactie supported te zijn middels het attribuut:
code:
1
[ Transaction( TransactionOption.Supported ) ]
Hier heb ik een vraag over, want de docs zeggen hier niets over: moet ik nu, wanneer ik een SqlCommand object aanmaak dit attribuut erboven zetten? (Iets zegt me van wel, want in VB/VC++ moest je je objects middels de MTS/COM+ context creeeren)
[code en status]
Bovenstaand voorbeeld maakt gebruik van een enum welke de status van de transactie bijhoud. Dit is heel handig want dan kun je in je business logica veel eenvoudiger die final-state machine fixen aangezien je objecten acties uit kunt laten voeren relatief aan de status. Ik zou bv niet kunnen schrijven in de db, want een ander object is ergens onafhankelijk de db leeg aan het halen. Ik zet mijn actie om te schrijven even in een queue en start zodra het andere object klaar is. (deadlock opgelost). Ook voor debugging is dit erg makkelijk aangezien je nu transacties kunt tracen. Die status is een voorgedefinieerde enum.
Een component moet dus ook queueable zijn? Vziw wacht de connection op de lock die SQLserver legt, dus hoef je dat niet te doen, maar het kan handig zijn wellicht. Ik begreep alleen dat queueing support voor MSMQ gold, statefull objects en niet echt het doel van de classes die gegenereerd worden. Die transaction status is ook uit te lezen uit de ContextUtil instance, maar wellicht is die niet toereikend genoeg. Klopt dit? Of zeg je: die status is veel beter?
Verder kan ik maar 1 tip geven, bestudeer het voorbeeld van Fitch & Mathers aangezien deze enorm kan helpen bij het hoe en waarom.
Okidoki, ik zal hem installeren en uitpluizen :)
Let op de business logica kan ook transactioneel zijn om bv zaken te bundelendit staat echter los van jouw tool.
Ja snap ik, transaction support moet alle mogelijkheden beslaan. BYOT support sla ik echter over, MS beveelt dit ook niet aan, maar ik neem aan dat je dat niet bedoelt :)

Verder ga ik Load Balancing, Object pooling en JIT features toevoegen (dit zijn attributes die mee worden gegenereerd). Je kunt nu ook de tables kiezen en de fields kiezen die moeten worden geexclude. Zo kun je bv 1 table opnieuw doen, zonder alle classes opnieuw te genereren.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Load Ballancing: heb je daar documentatie van, ergens? Wil ik graag ook iets meer over weten.

Supported: staat inderdaad nergens in de documentatie, maar dit is goed uit de Fitch & Mathers case te halen alsmede de MTS goeroe's hier mij vertelt hebben dat dit momenteel ook al in VB6 gebruikt wordt. Het is namelijk zo dat Supported alleen omvat, het kunnen draaien binnen MTS. Indien je een instantie van een object (Y) aanmaakt en zijn owner Required zet object (X) dan moet natuurlijk die instantie (Y) ook in MTS meegenomen kunnen worden... want zijn vader gaat tenslotten transactioneel verlopen.

wat een verhaal zeg ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 03 mei 2002 10:07 schreef paulgielens het volgende:
Load Ballancing: heb je daar documentatie van, ergens? Wil ik graag ook iets meer over weten.
In Win2k Beta 2 zat Component Load Balancing, ingebakken in de SCM. Dit is verwijderd 'op aanraden van veel customer feedback' (maar boze tongen beweren dat het niet werkte en MS het niet werkend kreeg op tijd). Je kunt 'application center 2000' kopen van MS, waar de component load balancing in zit. ALs je dat installeert op je WIn2k server heb je load balancing support en kun je middels COM+ dus load balancen tussen objects. Voor de marketing poop over Application Center 2000: http://www.microsoft.com/applicationcenter/techinfo/productdoc/default.asp
Supported: staat inderdaad nergens in de documentatie, maar dit is goed uit de Fitch & Mathers case te halen alsmede de MTS goeroe's hier mij vertelt hebben dat dit momenteel ook al in VB6 gebruikt wordt. Het is namelijk zo dat Supported alleen omvat, het kunnen draaien binnen MTS. Indien je een instantie van een object (Y) aanmaakt en zijn owner Required zet object (X) dan moet natuurlijk die instantie (Y) ook in MTS meegenomen kunnen worden... want zijn vader gaat tenslotten transactioneel verlopen.
Ja, wat je in VB/VC++ deed was een method gebruiken van de Context instance en daarmee nieuwe COM objects instantiaten, zodat DIE meedraaiden in de huidige transaction. Creeer je gewoon met new of met CreateInstance een object dan draait die niet mee in de MTS/COM+ transaction. Dus die attribute zal dat wel vervangen, ContextUtil heeft in ieder geval geen method om objects te creeren in de huidige context. Maar ik kan me ook zo voorstellen dat ze het zo hebben geimplementeerd dat iedere objectinstance automatisch in de huidige transaction draait.

Ik krijg zo'n gevoel dat MS het allemaal ook nog niet weet, transactions in de CLR, gezien de zeer spaarzame documentatie hierover.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
this eigenlijk heel duidelijk, zie in Fitch and Mathers de Account class maar eens. Daar maken ze:

AccountAdd requered

en Account supported, dit zou je in vb6 in 1 account class gooien die transactioneel binnen MTS draait... in .NET moet je gewoon alle insert/updates requered houden en de select etc supported zodat eventuele transacties op een hoger nivo alsnog de objecten mee kunnen nemen als supported (op zijn minst)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op vrijdag 03 mei 2002 13:14 schreef paulgielens het volgende:
this eigenlijk heel duidelijk, zie in Fitch and Mathers de Account class maar eens. Daar maken ze:
AccountAdd requered
Ja klopt, ik raakte even in de war met het feit dat de Transaction attribute bij bv:
code:
1
2
3
4
5
6
7
private void foo()
{
    // ... some code in a method
    [Transaction( TransactionOption.Supported )]
    MyObjectClass myObject = new MyObjectClass();
    // ... do something with myObject;
}

maar Transaction attribute heeft class scope, dus dat is nu duidelijk. De code in FMStocks 7 is ook duidelijk: alle objects die je aanmaakt in de transactional aware class draaien mee in de transaction. Vandaar dat er geen info over is :D
en Account supported, dit zou je in vb6 in 1 account class gooien die transactioneel binnen MTS draait... in .NET moet je gewoon alle insert/updates requered houden en de select etc supported zodat eventuele transacties op een hoger nivo alsnog de objecten mee kunnen nemen als supported (op zijn minst)
Iemand die de generator bedient moet kunnen aangeven of de complete layer uberhaupt transaction aware is, en zo ja op wat voor niveau, en daaraan worden de objects aangepast. selects hoeven niet in een nieuwe transaction te draaien, maar als je hebt aangegeven dat de layer transactions MOET ondersteunen, moeten selects 'required' hebben en geen supported. (maar dat is kniesoren werk ;) ). Overigens kun je binnen een class niet onderscheid maken tussen methods die transaction 'supported' zijn en die transaction 'required' zijn: je geeft dat nl. aan per class. (althans, dat is wat ik er van begreep)

Ik bedacht me ook nog dat sommige mensen liever:
SELECT field1, field2, field3... FROM Table
willen ipv
SELECT * FROM Table
de 1e is nl. efficienter.

Acties:
  • 0 Henk 'm!

Verwijderd

[b]Op donderdag 25 april 2002 21:45 schreef
data (LLBL stored proc)
----
dataaccess (LLBL dataaccess layer)
----
systemframework (BugTracking, Profiling, Logging)
----
common (data->datasets, specifieke methodes voor business + registry shit)
----
businessrules
businessfacade
----
presentation - webservices
______________ presentation
Even een paar vragen... want er is me iets niet duidelijk.

Wat is precies het verschil tussen "specifieke methodes voor business" in relatie tot businessrules.

En wat word er bedoeld met "businessfacade"? "Voorgevel"? API? Nu volgende stukje:

[Client] --> [ASP] --> [Systeem]

Client post een in xml vormgegeven commando naar een ASP pagina die vervolgens het "Systeem" aanroept. Is deze ASP laag (client connector, wellicht webservices?) nu een businessfacade?

Bedankt alvast.. :D

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Zodra een deel van je code over meerdere tiers wordt gebruikt valt het binnen de common. Bij mij zitten bv alle enums die ik in de business/dataaccess laag gebruik. Wat debug, tracking, tracing, config.

Data (Stored procedures, SQL server database)
Dataaccess (aanroepen laag naar stored procedures + connectieopbouw)
DataAccessWrapper (ik gebruik hem niet maar dit zou een extra abstractie laag kunnen worden met gebundelde transacties)
BusinessLogic bevat zowel BusinessRules en BusinessFacade... BusinessRules bevat erg strakke regels als contaminatie noem het maar op. BusinessFacade bevat specifieke zaken voor een bepaal component. Ik heb bv wel 100+ GUI draaien op de Business, om de Business een beetje netjes te houden stop ik alle specifieke logica van een GUI in een speciale Facade. De GUI Stock bevat dus zowel een referentie naar Stock.BusinessFacade.dll en naar de BusinessRules.dll. Mijn specifieke stock zooi verkracht dus niet mijn Business logica.

dit is wel een systeem van een paar miljoen regels code, honderden componenten etc etc. Windows DNA.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Op vrijdag 03 mei 2002 13:30 schreef Otis het volgende:
Overigens kun je binnen een class niet onderscheid maken tussen methods die transaction 'supported' zijn en die transaction 'required' zijn: je geeft dat nl. aan per class. (althans, dat is wat ik er van begreep)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using Product.Framework.Common;

using System;
using System.EnterpriseServices;

namespace Product.Framework.DataAccess.Bins
{
    /// <summary>
    /// Summary description for Bin.
    /// </summary>
    
    [Transaction( TransactionOption.Supported )]
    public class Bin : DA
    {
        public Bin()
        {
        }

        public Bin(/*params*/)
        {
            // schrijf bin naar db
            BinAdd baBin = new BinAdd();
            baBin.Add(/*params*/);
            // maak van mezelf een bin object, zodat
            // ik toegevoegd kan worden aan de BinManager
            // zijn linkedlist. Daar hoef ik zelf niet voor
            // te zorgen.
        }
    }

    [ Transaction( TransactionOption.Required ) ]
    class BinAdd : Bin
    {
        [AutoComplete]
        public BinAddStatus Add(/*params*/)
        {
            BinAddStatus stStatus;
            // schrijf bin naar database

            // update binmanger, zodat die weer een snapshot
            // omvat van de db. De BinManager krijgt automatisch
            // de status Changed, zodat deze een event raised en alle
            // observers notified om een update uit toe voeren.
            BinManager.Update();

            stStatus = BinAddStatus.Success;
            return stStatus;
        }
    }
}

Een bin zou je voor kunnen stellen als een vat met bier ;) Zodra mijn inhoud veranderd of ik gevuld wordt...of als nieuw vat de fabriek ingedragen wordt ga ik mezelf zowel toevoegen als relationele data alsmede het Framework verzoeken mij op te nemen in zijn kernel.

Wat een uitleg...schitterend ;)

Requered/Supported voorbeeld van een Bin object the .NET way alla Fitch and Mathers

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Maar je maakt dan dus 2 classes aan in feite, de een heeft een andere transaction attribute setting dan de andere. Ik moet nog ff hierover nadenken of ik dit ga doen, de calling code wordt dan wel ondoorzichtiger (niet veel, maar semantisch gezien wil je naar 1 class grijpen als je database werk wil verrichten, niet een keuze maken uit 2), of dat ik de select methods ook in dezelfde class stop met 'supported' als transaction option. -> Transactions die in de DA starten zijn in feite overbodig, we praten hier over veelal ondeelbare acties (semantisch gezien). Supporting zou toereikend moeten zijn: als je wilt dat je call naar de DA een onderdeel vormt van je transaction, dan moet je die starten in de caller van de DA method.

/me , die denkt dat paul ergens bij een blauwe kratten gebruikende fabriek zit ;)

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Op vrijdag 03 mei 2002 16:29 schreef Otis het volgende:
Maar je maakt dan dus 2 classes aan in feite, de een heeft een andere transaction attribute setting dan de andere. Ik moet nog ff hierover nadenken of ik dit ga doen, de calling code wordt dan wel ondoorzichtiger (niet veel, maar semantisch gezien wil je naar 1 class grijpen als je database werk wil verrichten, niet een keuze maken uit 2), of dat ik de select methods ook in dezelfde class stop met 'supported' als transaction option. -> Transactions die in de DA starten zijn in feite overbodig, we praten hier over veelal ondeelbare acties (semantisch gezien). Supporting zou toereikend moeten zijn: als je wilt dat je call naar de DA een onderdeel vormt van je transaction, dan moet je die starten in de caller van de DA method.

/me , die denkt dat paul ergens bij een blauwe kratten gebruikende fabriek zit ;)
Tja ik weet het, nou ik heb gekozen voor het volgende omdat:

Een insert/update moet altijd een Required zijn! Alle onderliggende klassen zouden supported moeten zijn, maar aangezien je vast toch al zo laag mogelijk de daadwerkelijk insert uitvoert np.

Omdat veel programmeurs waaronder ik al hoog ind e business logica brokken werk als transactie aan gaan bieden aan de dataaccess laag moeten dus "alle" Dataaccesss klassen supported zijn. De Business is namelijk Requered om die brok te bundelen.

Probleem is dat Requered enorm veel overhead van de MTS slurpt en in dergelijk kritische informatie systemen kun je er gewoonweg niet omheen. Een kantoorpik kan best een seconde wachten maar een batchverwerking voor machine aansturingen zouden een hoop schade aankunnen richten of zelfs bij overmatige belastingen of pieken deadlocks in de besturignen kunnen veroorzaken. Toch lastig als de klep van de silo open blijft zonder dat er een vrachtwagen onder staat ;)

Conclusie: omdat je de beperking per class hebt ga je een private class introduceren bij mij wel de BinAdd. Deze is niet te bereiken via Business logica en is eigenlijk een helper van de normale bin class. De is Requered en doet op een zo laag mogelijk nivo zijn werk om MTS te sparen. In de private helper klasse zitten dus concreet de insert/update methodes die al dan niet stored aanroepen of gewoon zelf de SQL implementeren.

Het is efficient en vrij duidelijk indien je dit consequent implementeerd voor alle "objecten" die als relationele data gepresenteerd worden aan de gebruiken.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ok dat required wanneer het niet hoeft is duidelijk ivm de overhead.

Ik zie het echter zo: indien je de insert/update/delete methods in een supported class stopt, dan leg je de verantwoordelijkheid van een transaction bij de caller neer. Maak je ze required, dan neem je zelf die verantwoordelijkheid. Omdat die insert/update/delete methods niet op zichzelf staan (ze krijgen hun input van een caller) lijkt het me voor de hand liggen dat de caller, indien nodig, een transaction start.

Dit gaat alleen 'fout', wanneer de caller niet een serviced component is maar wel gebruik wil maken van een transaction. Dat kan dan niet, want de called method (insert e.d.) starten niet een nieuwe op. Nu is dat voor deze specifieke functies niet een probleem imho, want ze zijn atomair: een insert is niet op te delen in meerdere acties, we praten immers over de dataaccess-layer.

Of zie ik iets over het hoofd? private classes is nl. wel wat extra werk, en als dat niet hoeft vermijd ik dat gaarne :)

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Neenee houd je tool maar lekker flexibel en zorg dat ze supported zijn middels:
code:
1
2
3
4
5
6
7
8
9
10
11
12
// DA.cs

sealed class DA : ServicedComponent {}


// ConfigManager.cs

sealed public class ConfigManager : DA {
SqlConnection _Connection;

// _Connection bieden we aan middels een property
}

Nogmaals kijk even Fitch & Mathers in, wat een perfect voorbeeld oplevert hoe dit concreet te implementeren. Misschien dat je die StoredProcedure klasse kunt gebruiken om je stored procedure uiteindelijk uit te voeren. Hier kun je in je interface van je tool een optie voor inbouwen om dan wel niet supported of required in te voeren doordat je dat nu centraal regelt. Die StoredProcedure klasse maak je dan mooi required en dus op 1 centrale plek te veranderen. Dam wat is inheritance toch lekker.

Ik hoop dat ie duidelijk is zo

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Misschien dat je de DBInteractionBase ook maar eens middels een singleton principe moet implementeren, of eigenlijk moet implementeren.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op zondag 05 mei 2002 21:46 schreef paulgielens het volgende:
Misschien dat je de DBInteractionBase ook maar eens middels een singleton principe moet implementeren, of eigenlijk moet implementeren.
Ik stam uit het 'C' tijdperk :) wat is het 'singelton principe' ? :)

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Op zondag 05 mei 2002 22:40 schreef Otis het volgende:
Ik stam uit het 'C' tijdperk :) wat is het 'singelton principe' ? :)
Heel kort en simpel:

Een enkele 'statische klasse' (ik gebruik het alleen in Java en dan heb je het gelijk over klassen natuurlijk ;) ) die dmv een speciale 'constructor' aangeroepen wordt. Hierdoor heb je altijd maar 1 instantie die je overal aan kan spreken. Je zou het bijvoorbeeld kunnen gebruiken om één enkele instantie van een ConnectionPool (in bijv een Java Servlet) te maken. Zoiets doe je, imho, voornamelijk als je een shared resource aan wil leggen :)

Zie bijv de reactie van mbravenboer in: [topic=413231/1/100]

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Here is an interesting article from MSDN: http://msdn.microsoft.com/library/en-us/dnbda/html/singletondespatt.asp

In .NET is het nog iets eenvoudig te implementeren, trouwens ik ben met een model view controller bezig... mijn god! Als je de .NET equivalent van een MVC tegen een Java implementatie legt is Java een lachertje. Nu moet ik daar wel bij zeggen dat ik over Java ook altijd zeer te spreken was, maar MS heeft het nog iets gesimplificeerd door Delegates/Events te gebruiken voor de IObserver/IObservable implementaties.

Een tip om die ook even door te lezen als je toch naar singleton kijkt.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik snap niet waarom de base class een singleton class moet worden. Je wilt ook niet dat de derived classes dat worden, althans niet in een data access layer.

De base class wordt niet stand alone gebruikt, maar alleen voor inheritance.

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Op maandag 06 mei 2002 09:29 schreef Otis het volgende:
Ik snap niet waarom de base class een singleton class moet worden. Je wilt ook niet dat de derived classes dat worden, althans niet in een data access layer.

De base class wordt niet stand alone gebruikt, maar alleen voor inheritance.
Omdat er maar 1 unieke instantie van je SQL connectie object hoeft te bestaan! Alle andere klassen krijgen een pointer (reference) naar dat object.

niet een kwestie van willen, maar bijna moeten in de object georienteerde wereld

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op maandag 06 mei 2002 14:07 schreef paulgielens het volgende:

[..]

Omdat er maar 1 unieke instantie van je SQL connectie object hoeft te bestaan! Alle andere klassen krijgen een pointer (reference) naar dat object.
NEE! Dit is DE fout die veel mensen maken! Jij wilt toch niet beweren dat 20 users tegelijk met dezelfde database connection moeten werken? Je helpt je complete scalability om zeep. Dit staat gelijk aan een ADO connection object in de application object stoppen in ASP.

Totaal NIET scalable. Je moet t.a.t. connection objects maken wanneer je ze nodig hebt en vrijgeven wanneer je ze niet meer nodig hebt. Zodoende support je een scalable aantal clients en gebruik je een feature die scalability verhoogd: connectionpooling.

Zodra je vele clients gaat voorzien van dezelfde connection naar de database zakt je performance als een pudding in elkaar, want er kan maar 1 actie per keer over een connection. Je moet nl. per actie de connection resetten. Erg erg erg foute keuze om 1 connection te gebruiken voor een data-access layer die wellicht door een veelvoud aan clients wordt gebruikt tegelijkertijd.
niet een kwestie van willen, maar bijna moeten in de object georienteerde wereld
Sorry Paul, maar dit heeft niets te maken met OO. Lees de scalability articles van MS er maar op na: gebruik connection pooling, creeer zo laat mogelijk een connection object en geef hem zo vroeg mogelijk weer vrij (dwz: open en close de connection zodat de connection terug in de pool kan en kan worden gereset.)

Wat verbetert zou kunnen worden is de class abstract te maken, zodat men geen instance kan creeeren van de base class. Maar een enkele connection naar de database is funest voor je scalability, ik durf wel te zeggen: doodzonde nummer 1.

Acties:
  • 0 Henk 'm!

Verwijderd

Op maandag 06 mei 2002 14:34 schreef Otis het volgende:
Sorry Paul, maar dit heeft niets te maken met OO. Lees de scalability articles van MS er maar op na: gebruik connection pooling, creeer zo laat mogelijk een connection object en geef hem zo vroeg mogelijk weer vrij (dwz: open en close de connection zodat de connection terug in de pool kan en kan worden gereset.)
Persoonlijk maak ik altijd in m'n applicaties per user één connectie aan, en gebruik die de hele tijd. Pas bij het sluiten van de applicatie verbreek ik die.
Maar als ik jou begrijp moet ik voor elk lullig SELECT/UPDATE/DELETE statement de connecties openenen en sluiten. Dat kost toch ongelooflijk veel tijd? Het openenen van connecties kost bij mij namelijk regelmatig meer dan een seconde, en om dat voor elk statement te doen...

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op dinsdag 07 mei 2002 10:12 schreef KoenM het volgende:
[..]
Persoonlijk maak ik altijd in m'n applicaties per user één connectie aan, en gebruik die de hele tijd. Pas bij het sluiten van de applicatie verbreek ik die.
Maar als ik jou begrijp moet ik voor elk lullig SELECT/UPDATE/DELETE statement de connecties openenen en sluiten. Dat kost toch ongelooflijk veel tijd? Het openenen van connecties kost bij mij namelijk regelmatig meer dan een seconde, en om dat voor elk statement te doen...
Het openen van een database connectie kost relatief veel tijd. Daarom is er ook connection pooling. Als je relatief weinig database verkeer hebt, en je gebruikt connection pooling, dan heb je op sommige momenten geen open connections in de pool, want die sluiten na X minuten (instelbaar).

Het is niet erg voor elke user een connection te openen in bv in desktop applicaties. Het is wel erg voor elke user een connection te openen in een webapplicatie: bij 1000 users op je site heb je 1000 open connections. Nou, dat trekt een gemiddelde database server minder goed :).

In de situatie van de 1 a 2-tier client/server applicaties (de zg 'fat clients') is het gebruikelijk per user 1 connection te openen en die open te houden, zoals jij schetst. Pooling heeft niet zoveel zin, want de enige applicatie die connections poolt is de fat client, dus dat is lood om oud ijzer.

In de situatie van een n-tier app, waarbij de client niet direct de database aanspreekt maar een middle-tier, is het zaak dat je vanaf de middle-tier WEL connection pooling gebruikt, want alle clients maken gebruik van dezelfde middle-tier INSTANCE, waardoor bv 40 of 50 users tegelijk niet 50 connections open houden maar bv 3 of 4, die telkens doorschuiven naar de caller via de POOL (en niet via een eigen mechanisme).

Verschillende situaties dus, die vragen om verschillende oplossingen. Het tijdperk van fat clients is echter wel over, daar dit een zeer beperkt paradigma is: code is veelal niet geshared en soms is zelfs de database niet geshared.

Acties:
  • 0 Henk 'm!

  • Yannick
  • Registratie: December 2000
  • Laatst online: 26-03-2024

Yannick

Bub MC

In de situatie van een n-tier app, waarbij de client niet direct de database aanspreekt maar een middle-tier, is het zaak dat je vanaf de middle-tier WEL connection pooling gebruikt, want alle clients maken gebruik van dezelfde middle-tier INSTANCE, waardoor bv 40 of 50 users tegelijk niet 50 connections open houden maar bv 3 of 4, die telkens doorschuiven naar de caller via de POOL (en niet via een eigen mechanisme).
Sorry dit wordt enigszins offtopic maar heb je misschien een linkje dit uitlegd hoe je dit praktisch moet doen? Ik heb nl. wel een app gebouwd met een dataaccesslayer maar die wordt in de codebehind files gewoon elke keer geinstantieerd per pagina en per request.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op dinsdag 07 mei 2002 13:15 schreef Yannick het volgende:
[..]
Sorry dit wordt enigszins offtopic maar heb je misschien een linkje dit uitlegd hoe je dit praktisch moet doen? Ik heb nl. wel een app gebouwd met een dataaccesslayer maar die wordt in de codebehind files gewoon elke keer geinstantieerd per pagina en per request.
Connection pooling staat standaard aan, dus als je gewoon connectoin objects aanmaakt per keer is er niets aan de hand.

Een connection object aanmaken en openen zijn 2 verschillende dingen: het object zelf instantiaten kost weinig tijd. Wanneer je het opent, wordt in de connectionpool (dit regelt ADO of ADO.net voor je) gekeken of er een open, vrije connection met de database is. Zo ja, dan wordt die aan het connection object gekoppeld. Zo nee, dan wordt een nieuwe aangemaakt en wordt die aan het object gekoppeld. Wanneer je de connection sluit, wordt de connection naar de database niet gesloten, maar wordt de connection slechts ontkoppeld van het connectionobject en gaat terug in de pool. Zodra jij weer een nieuw connection object opent wordt er weer inde pool gekeken door ADO of ADO.NET en wordt de zojuist in de pool gezette connection opnieuw gebruikt. Dit levert nauwelijks overhead op, maar zorgt wel voor een schaalbare applicatie.

Acties:
  • 0 Henk 'm!

Verwijderd

Nog ff een klein bugje: Als je de tool start vanaf een network share, dan krijg je een foutmelding, bij het maken van de connectie. Verder krijg je een foutmelding als je vergeet een property te set-ten. Bij bv. een string zou best de standaard waarde <NULL> of "" kunnen zijn, wel zo makkelijk :).

Verder is het een juweeltje O+ ;), echt ideaal!

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op woensdag 08 mei 2002 19:04 schreef KoenM het volgende:
Nog ff een klein bugje: Als je de tool start vanaf een network share, dan krijg je een foutmelding, bij het maken van de connectie.
Vaag... Ik zal ff kijken wat daar de oorzaak van kan zijn. Het kan zijn dat dat het wegschrijven van de app.config is.
Verder krijg je een foutmelding als je vergeet een property te set-ten. Bij bv. een string zou best de standaard waarde <NULL> of "" kunnen zijn, wel zo makkelijk :).
Komt er in, null value support :)
Verder is het een juweeltje O+ ;), echt ideaal!
:) :) En dat wordt alleen maar meer :) de volgende versie krijgt MS compliant code generation en een veel betere gui, serialization van options, table selection welke tables je processen wilt, meer opties voor de output etc. stay tuned :)

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
mmm mmm mmm ben aan vakantie toe denk ik...ben benieuwd naar de nieuwe versie. mijn mailbox wacht met smacht.

Trouwens ik ben eens aan het experimenteren met de SQL 2000 XML interface, welilcht dat ik nog eens iets concreets fab zodat je automatisch XML service in je tool kan plakken. Heeft "webbased" wel enkele voordelen. Weet trouwens niet of een DataTable wel naar XML? Ach... alles komt goed.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Op donderdag 09 mei 2002 12:22 schreef paulgielens het volgende:
mmm mmm mmm ben aan vakantie toe denk ik...ben benieuwd naar de nieuwe versie. mijn mailbox wacht met smacht.
hehe :) De gui heb ik klaar nu (is veel veranderd), nu die aansluiten op de codegenerator. komt goed :)
Trouwens ik ben eens aan het experimenteren met de SQL 2000 XML interface, welilcht dat ik nog eens iets concreets fab zodat je automatisch XML service in je tool kan plakken. Heeft "webbased" wel enkele voordelen. Weet trouwens niet of een DataTable wel naar XML? Ach... alles komt goed.
DataTable is XML intern. :) Dus dat gaat goed. De Schema retrieval functionaliteit in .net heb ik nog niet naar gekeken maar is wel een optie voor een volgende versie, het schijnt (maar dat moet ik nog uitzoeken) dat je door het XSchema op te vragen voor tables en columns je ook de structuurinfo krijgt. Die kun je dan snel dmv een XSLT'tje naar code converteren...

Acties:
  • 0 Henk 'm!

  • Scare360
  • Registratie: Juli 2001
  • Laatst online: 19-08 16:50
Op vrijdag 10 mei 2002 09:53 schreef Otis het volgende:
DataTable is XML intern. :) Dus dat gaat goed. De Schema retrieval functionaliteit in .net heb ik nog niet naar gekeken maar is wel een optie voor een volgende versie, het schijnt (maar dat moet ik nog uitzoeken) dat je door het XSchema op te vragen voor tables en columns je ook de structuurinfo krijgt. Die kun je dan snel dmv een XSLT'tje naar code converteren...
Dit kan ik bevestigen!
Pagina: 1