Toon posts:

[ASP.NET] DataTables/DataRows gebruiken als DTO?

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

Verwijderd

Topicstarter
In een ander topic schreef ik al over een web applicatie met drie lagen, die momenteel alleen een website als interface heeft, maar later waarschijnlijk ook een webservice.

Voor de DAL gebruik ik die handige DataSet designer van Visual Studio 2005. Dat resulteert in TableAdapters. Het resultaat van de methodes van deze TableAdapters is vrijwel altijd een DataRow of een DataTable.

Mijn vraag is of er nadelen zitten aan het gebruik van deze DataRows en DataTables in zowel de BLL als de GUI? De entiteiten worden nu gerepresenteerd door DataRows en verzamelingen van de entiteiten door DataTables. Ik zie regelmatig voorbeelden van specifieke klassen voor entiteiten en verzamelingen m.b.v. generics (bijvoorbeeld: Product en List<Product> i.p.v. ProductsDataRow en ProductsDataTable). Deze klassen worden dan vaak al in de DAL aangemaakt en komen via de BLL bij de GUI.

Ik wil graag de Typed DataSets van Visual Studio gebruiken voor de DAL (scheelt veel tijd) maar weet niet zeker of ik er verstandig aan doe om de DataRows en DataTables in de BLL om te zetten naar eigen klassen en collecties. Vandaar mijn vraag of er nadelen zitten aan de DataRows en DataTables die dit de moeite waard maken.

Verwijderd

Ik ben niet zo'n fan van typed datasets. (Maar mijn ervaring ermee is beperkt, dus het kan daar aan liggen).

Stel je voor je hebt een Doos. En in die Doos gaan Dingen. Op het scherm wil ik een lijst met de Inhoud van die Doos tonen.

Ik stel me zo voor dat je dit soort code krijgt met typed datasets:

C#:
1
2
3
4
5
6
7
8
9
dstInhoud myInhoud = new dstInhoud();

dstInhoud.tblDingenRow myDing = myInhoud.tblDingen.NewtblDingenRow();

myDing.Naam = "Schroevendraaier";

myInhoud.tblDingen.AddtblDingenRow(myDing);

dataGrid1.DataSource = myInhoud.tblDingen;


En dat allemaal op basis van een xml file:

XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema id="dstInhoud" targetNamespace="http://tempuri.org/dstDing.xsd" elementFormDefault="qualified"
    attributeFormDefault="qualified" xmlns="http://tempuri.org/dstDing.xsd" xmlns:mstns="http://tempuri.org/dstDing.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="dstInhoud" msdata:IsDataSet="true">
        <xs:complexType>
            <xs:choice maxOccurs="unbounded">
                <xs:element name="tblDingen">
                    <xs:complexType>
                        <xs:sequence></xs:sequence>
                        <xs:attribute name="Naam" type="xs:string" />
                        <xs:attribute name="Gewicht" type="xs:int" />
                    </xs:complexType>
                </xs:element>
            </xs:choice>
        </xs:complexType>
    </xs:element>
</xs:schema>



Het lastige vind ik dat je zomaar extra rijen aan de tabellen kan gaan toevoegen, zonder dat er een controle wordt uitgevoerd.
Is de Doos al verzegeld zodat er niks meer in kan?
Kan het Ding niet in de Doos omdat dat type er niet in mag? (Een fiets mag niet in een kleine doos)
etc.

Met custom objects lijkt me dat makkelijker gaan:

C#:
1
2
3
4
5
6
7
public class Doos
{
   public bool AddDing(Ding ding)
   {
      //If Doos.IsSealed return false;
   }
}


Maar goed, misschien kan dat met Typed Datasets ook wel heel makkelijk?

Verwijderd

Topicstarter
Hey, bedankt voor je antwoord. Typed DataSets maak ik met de Visual Studio Designer. Het resultaat is partial classes. Dat betekent dat ik validatie toe kan voegen door de klasse uit te breiden in een ander bestand (de rest van de partial class).

Ik gebruik zoals gezegd DataTables en DataRows omdat het makkelijk is. Als ik eigen klassen zou gebruiken zou ik volgens mij ook de TableAdapters niet meer gebruiken. Dan moet ik dus zowel de DTO's als de DAL zelf schrijven.

Kortom, ik ben liever lui dan moe. Maar vroeg me af of iemand met meer ervaring mij kan waarschuwen voor eventuele valkuilen inherent aan mijn aanpak.

Verwijderd

Als ik er even over nadenk, dan kom ik op de volgende nadelen:

1)
Je hebt alle overhead van datasets.


2)
In plaats van
code:
1
Dossier.Close

ga je al snel dingen doen als
code:
1
myDossier.Closed = 1;



3)
Voor je het weet zit je in de UI-laag te programmeren met rows en tables. Terwijl je dat moet laten aan de data-laag.


4)
Er is een gevaar dat je DTO's eigenlijk gewoon de database-tabellen representeren, i.p.v. domein objecten.
Dan ga je straks aan de gang met een dtoDossier en dtoMedwerker, omdat je per dossier de naam wilt weten van de eigenaar. Terwijl je juist een object moet hebben als:
dossier.ID
dossier.Eigenaar
dossier.CreateDate
etc.


Misschien kunnen deze nadelen ontkracht worden, of zijn het geen nadelen, of weten anderen en nog meer.

  • whoami
  • Registratie: December 2000
  • Laatst online: 18:04
Verwijderd schreef op donderdag 30 november 2006 @ 12:48:

Mijn vraag is of er nadelen zitten aan het gebruik van deze DataRows en DataTables in zowel de BLL als de GUI? De entiteiten worden nu gerepresenteerd door DataRows en verzamelingen van de entiteiten door DataTables. Ik zie regelmatig voorbeelden van specifieke klassen voor entiteiten en verzamelingen m.b.v. generics (bijvoorbeeld: Product en List<Product> i.p.v. ProductsDataRow en ProductsDataTable). Deze klassen worden dan vaak al in de DAL aangemaakt en komen via de BLL bij de GUI.
Ik wil graag de Typed DataSets van Visual Studio gebruiken voor de DAL (scheelt veel tijd) maar weet niet zeker of ik er verstandig aan doe om de DataRows en DataTables in de BLL om te zetten naar eigen klassen en collecties. Vandaar mijn vraag of er nadelen zitten aan de DataRows en DataTables die dit de moeite waard maken.
Zoals anderen voor mij reeds gezegd hebben:
Die datasets laten je veel meer vrijheid toe (ze laten dingen toe die je misschien niet wil toelaten), wat er dus voor zorgt dat je geen 'rijk domein model' hebt in je software, waarbij je domein model duidelijk aangeeft / laat zien wat kan en niet.

Het voordeel van het werken met DataTables / DataRows is natuurlijk dat ze
a) heel wat werk uit jouw handen nemen
b) .NET er nogal op gefocussed is, en je dus makkelijk en snel iets in elkaar kunt zetten.

Het nadeel is natuurlijk dat je geen 'expressief domein model' hebt.

Echter, ik zie niet direct in waarom je het in je titel hebt over DTO's. Een DTO kan imho perfect een dataset zijn, want een DTO hoeft helemaal geen logica te bevatten. Een DTO is gewoon een 'dom' object dat data bevat, en de bedoeling van een DTO is om die data over verschillende lagen te transporteren. Natuurlijk moet je hier niet in gaan overdrijven, want een dergelijk iets voegt alleen maar complexiteit toe, maar een DTO zou zeer geschikt kunnen zijn als je bv met remoting werkt, om je gegevens van client naar server te sturen. (Dit doe ik atm ook zelf in een project).

Wat je ook zou kunnen doen mbt je BLL, is eigen classes maken die een wrapper zijn rond je DataTable of DataRows. Maw, een custom class die een member heeft die van het type myDataTable of myDataRow is.
In die custom class kan je er dan makkelijk voor zorgen dat bepaalde velden niet zo maar mogen geset worden, en daar kan je ook een aantal BL methods in schrijven.

https://fgheysels.github.io/


  • Shir
  • Registratie: November 2000
  • Laatst online: 25-11 20:55
N.a.v. de laatste opmerking van whoami, zie ook de tutorial op asp.net:

Working with Data in ASP.NET 2.0 :: Creating a Business Logic Layer

Verwijderd

Persoonlijk zou ik een andere insteek kiezen dan in deze tutorial wordt aangereikt.

In de tutorial wordt een business laag gemaakt die wat mij betreft nog te 'data gericht' is. Kijk bijvoorbeeld eens naar de method namen:

GetProducts
GetProductByProductID
GetProductsByCategoryID
GetProductsBySupplier
AddProduct
UpdateProduct
GetCategories
GetCategoryByCategoryID
GetSuppliers
GetSupplierBySupplierID
GetSuppliersByCountry
UpdateSupplierAddress
GetEmployees
GetEmployeeByEmployeeID
GetEmployeesByManager

Dat zijn allemaal methodnamen die aanduiden dat er iets met data wordt gedaan. Zeker de dukgedrikte namen passen naadloos in een datalaag.

Ik ontken niet dat het nodig is om via de businesslaag informatie op te halen, ik vind het wel jammer dat er zoveel nadruk ligt op de data-georienteerde acties.

Vooral de methode UpdateProduct is een drama:
Als ik een product uit de roulatie wil nemen, dan moet ik deze regel opnemen in mijn presentatielaag:

code:
1
productLogic.UpdateProduct("Scott s Tea", 1, 1, null, -14m, 10, null, null, true, 1);


Als ik een product aan een andere categorie wil toevoegen, dan moet ik deze regel opnemen in mijn presentatielaag:

code:
1
productLogic.UpdateProduct("Scott s Tea", 2, 1, null, -14m, 10, null, null, false, 1);


Als ik de prijs van het product wil wijzigen, dan moet ik deze regel opnemen in mijn presentatielaag:

code:
1
productLogic.UpdateProduct("Scott s Tea", 1, 1, null, -19m, 10, null, null, false, 1);


En hoe meer updates er mogelijk zijn, hoe meer checks er moeten worden uitgevoerd en hoe groter mijn UpdateProduct method wordt. Totaal onoverzichtelijk en niet onderhoudbaar.


Mijns inziens is het netter en beter om te maken:

C#:
1
2
3
4
5
6
7
8
9
10
11
Class productLogic
{
   public void NeemUitRoulatie (int productId)
   {
      // 1. Haal het product op uit de database via de DAL

      // 2. Verander de waarde van het veld 'discontinued' van 0 naar 1

      // 3. Geef de DAL de opdracht om een update uit te voeren
   }
}


Nu kan mijn presentatielaag simpelweg zeggen:

code:
1
productLogic.NeemUitRoulatie ( 164 ) ;



En:

C#:
1
2
3
4
5
6
7
8
9
10
11
Class productLogic
{
   public void WijzigCategorie(int productId, int CategorieId)
   {
      // 1. Haal het product op uit de database via de DAL

      // 2. Verander de waarde van het veld 'categoryID' in de doorgegeven waarde

      // 3. Geef de DAL de opdracht om een update uit te voeren
   }
}


Nu kan mijn presentatielaag simpelweg zeggen:

code:
1
productLogic.WijzigCategorie( 164, 4 ) ;



Ok, dit is in een notendop hoe het wat mij betreft beter kan op een redelijk eenvoudige en snelle manier. (En dan wordt het nu tijd voor het Model-View-Controller principe (MVC pattern) )

Verwijderd

Topicstarter
Verwijderd schreef op maandag 18 december 2006 @ 18:54:
[...]
Nu kan mijn presentatielaag simpelweg zeggen:

code:
1
productLogic.WijzigCategorie( 164, 4 ) ;


Ok, dit is in een notendop hoe het wat mij betreft beter kan op een redelijk eenvoudige en snelle manier. (En dan wordt het nu tijd voor het Model-View-Controller principe (MVC pattern) )
MVC in ASP.NET kan wel, maar doe dan maar een ander topic, want dat is een heel verhaal. Maar ontopic: ik stelde de vraag omdat ik het 'vreemd' vond (lees: mogelijkerwijs niet de beste oplossing) dat de GUI uiteindelijk met DataTables en Rows werkt. Deze manier lijkt mij ook erg op de database gericht.

Nou moeten we voor een oplossing van Microsoft wachten op ADO.NET 3.0 (ADO.NET Entities heet het geloof ik), maar in de tussentijd vraag ik mij af of je WEL met typed DataSets en TableAdapters kunt werken (en die handige designer) in je DAL maar NIET in je GUI? M.i. moet je dan je eigen entiteitobjecten maken in de BLL en deze doorgeven aan de GUI, en dan vraag ik me dus af of je dan niet gelijk ook die TableAdapters van Microsoft moet laten gaan en de hele DAL opnieuw schrijven, zodat je gelijk die entiteitobjecten hebt.

Disclaimer: ik heb theoretische kennis uit het boek van Fowler, maar weinig praktijkervaring met dit soort architectuur.
Pagina: 1