webForumDet fria alternativet

Bygga en egen dbklass

.NET

118 svar · 5 017 visningar · startad av Swordfishy · sida 4 av 6

Frågan, av Swordfishy

Goddagens, Tidigare har jag sysslat en del med klassiska ASP tillsammans med mySQL. Nu är det dock dags att övergå till ASP.NET med mySQL. Jag står inför ett hinder, funderar på att bygga en serverkontroll (kompilerad kod till .dll) som sköter arbetet (anslutning, hämtar data, uppdaterar, ta bort data osv..) mot min mySQL databas. Tror det kan kallas DAL? Min tanke är att en sådan här lösning:

Läs frågan i sin helhet →
Medlem sedan maj 20012 812 inlägg
#61

P:

Du kan använda dig av vanlig SQL i en O/R Mapper också, många av de kommersiella O/R Mappers gör detta, eftersom du då slipper steget med att skriva SP själv. Du har med andra ord inte någon som helst kontakt med SQL eller databasen så fall.

Med en O/R Mapper så slipper du skriva alla methoder för att fylla dina objekt med data samt spara dessa till databasen.

Detta gör O/R Mappern till dig. Du har alltså fortfarande kvar dina BusinessObjekt och skickar ett sådant till O/R Mappern som då "konverterar" ditt objekt till en SQL sträng (eller parameters till en SP) som sedan skickas till DAL:et.

Krast kan man säga att följande görs.

1. Du vill ha ett kund objekt.
då kan du gör följande(beroende på hur O/R Mappern ser ut)

Customer cust = new Customer();
cust.Id = 1;
ORMapper.Load(cust);

eller

Customer cust = ORMapper.LoadById(typeof(Cust),1);

Båda två kommer att ge dig ett kundobjekt med data från databasen där id = 1.

Om du sedan uppdaterar lite i din objekt, och sedan spara så gör du så här.

cust.Name = "Magnus";
cust.Decription ="Simple the best";

ORMapper.Save(cust);

I det första exempelet så skapar OR/Mappern en SQL sträng som typ ser ut så här:
SELECT * FROM [Customer] WHERE [ID] = 1

Denna sträng skickas till DAL:et som hämtar informationen och skickar tillbaka ett DataTable eller en DataReader.

Sedan tar O/RMapper och fyller ditt Customer objekt med data från DataTablen/DataReadern. Och skickar tillbaka detta objekt.

Vid Save så görs motsvarande att datan i objektet plockas ut och skapar en SQL sträng, sedan så skickas denna sträng till DAL:et och uppdaterar databasen.

- Magnus

Medlem sedan maj 20012 812 inlägg
#62

Har jag skrivit att den tillverkar en collection av DataTables?, var har du fått det ifrån. Den skapar en egen Collection av DataTable:t har du svårt för att läsa?.

Faktiskt, så hade jag det där. Det ber jag om ursäkt för.

Din Collection är också starkt typat, så du kastar stenar i glashus än en gång. Så det där höll inte.

Men det är ju det jag säger, att dina datasets måste göra typecasting precis som en Collection, alltså har du prestandförlust där med.

Antingen har du det när du laddar datan i ett Typat Dataset (precis som en collection) eller så har du det när du hämtar datan i icke Typade DataSets.

[updaterat]
Det är värre än jag trodde, jag trodde att typcastning endast sker en gång med TypatDataset, men icke så nicke, varje gång man hämtar samma värde så görs en typcasting. Se nedan.
[/updaterat]

Och angåend vad som händer bakom, så sker följande när du skall hämta ut ett värde i ett Typat DataSet.

            public int TransactionId {
                get {
                    try {
                        return ((int)(this[this.tableelement1.TransactionIdColumn]));
                    }
                    catch (InvalidCastException e) {
                        throw new StrongTypingException("Cannot get value because it is DBNull.", e);
                    }
                }

För att hämta ut ett värde från ditt TypadeDataset så måste plocka fram ett indexvärde:
this.tableelement1.TransactionIdColumn

Som du använde som indexer för att hämta själv värde av din variable:
this[this.tableelement1.TransactionIdColumn])

Efterdet så måste du typcasta ditt värde till rätt typ:
((int)(this[this.tableelement1.TransactionIdColumn]));

Jämfört med ett objekt:

            public int TransactionId {
                get {return myTransactionId;}
                }

Hur du kan få det sista att vara mer prestandakrävande övergår alla fysikaliska lagar, inte nog med att det översta kräver mer prestanda du gör det desutom VARJE gång du hämtar värdet, inte bara engång och sedan spara undan det, Nej då varje gång skall man hämta index, hämta värde ur en collection, och sedan typkasta.

Jag tror nog du är den enda som tycker att det är snabbare än att hämta direkt från objektet.

- M

Medlem sedan juli 20011 304 inlägg
#63

Ok. Jag har två knäckfrågor att fundera på här:

Ett:
Microsoft har ju ett gäng referensapplikationer. Alla är uppbygda på ett ganska liknande sätt. Den kanske mest kända av alla är .NET petshop som microsoft skapade för att visa att .NETvar snabbare än j2ee. Gissa hur denna applikation är uppbyggd. Jo visst är det så att den består av ett DAL som bygger upp objekt och returnerar. Varför kan microsoft tänkas ha gjort på detta viset i sina lösningar. Jo svaret är ju naturligtvis att dom inte har förstått att Datasetet egentligen är snabbare och skapar en bättre kodseparation. Dom är ju trots allt ganska dumma och kan inte så mycket om hur dataset fungerar. Eller har jag fel?

Två:
Microsofts stora satsning och stolthet i whidbey är ObjectSpaces, som är - en o/r mapper. Varför i hela fridens namn vill dom göra en sådan när man så enkelt kan använda det redan överlägsna datasetet?

Dom där Microsoft är ju verkligen ute och cyklar :OO

Medlem sedan jan. 20012 204 inlägg
#64

Ahh lägger nog ner det med att försöka göra en egen O/R, blir alldeles för grötigt. Blir istället att vidareutveckla
CodeGen

Medlem sedan apr. 2004778 inlägg
#65

Ta en titt på Paul Wilsons ORMapper på http://www.wilsondotnet.com
En livstids prenumeration på hans sajt kostar $50 (ca 390 spänn) och då får du alla hans komponenter med sourcekod. Har länge funderat på att signa upp och jag gjorde det idag. Värt varenda öre.

Medlem sedan okt. 2002188 inlägg
#66

P skrev:

Ahh lägger nog ner det med att försöka göra en egen O/R, blir alldeles för grötigt. Blir istället att vidareutveckla
CodeGen

Har du kikat på de opensource projekt som finns?

Finns en hel del o/r mappers på sourceforge.. en del fungerar inte men man lär sig en rackans massa på att läsa hur de löst problemen..

Medlem sedan nov. 2003569 inlägg
#67

För att hämta ut ett värde från ditt TypadeDataset så måste plocka fram ett indexvärde:
this.tableelement1.TransactionIdColumn

Klart man måste veta vilken rad man ska ta ut data/skriva till.
dataset.kunder[12].namn.
Det gör du också, antingen från DataTable:t(under ytan) eller från din Collection.

Efterdet så måste du typcasta ditt värde till rätt typ:
((int)(this[this.tableelement1.TransactionIdColumn]));

Du tycks ha glömt att din O/R mapper fyller ett DataTable från databasen, och från DataTable:t fyller den en Collection, det handlar alltså om 2 feta objekt som måste fyllas innan du har tillgång till dina data. När det handlar om dataset så fylls BARA DataTablet och inget mer, alltså bara 1 objekt, DataSet-DataTables gör hälften av vad O/R mappern gör, därav går det snabbare.

Vilken O/R mapper använder du?.

Microsofts stora satsning och stolthet i whidbey är ObjectSpaces, som är - en o/r mapper. Varför i hela fridens namn vill dom göra en sådan när man så enkelt kan använda det redan överlägsna datasetet?

Jag är inte emot O/R mapper, tanken är god, men om jag får ge mig på en kvalificerad åsikt så är ADO.NET är inte riktigt mogen för sådant ännu, därför blir det som det blir tyvärr, man behöver andra snabbare objekt som är skapta enbart för sådana här saker, och det är dom objekten vi kommer få se i ADO.NET2.0.

Medlem sedan apr. 2004778 inlägg
#68

Nöff, ge dig nu, du har fortfarande inte greppat något av vad någon sagt här.

1. Du säger återigen att O/R mappern fyller ett DataTable
- FEL. DAL hämtar DataTable, DataReader, DataSet, vad man nu vill och ger den till mappern som skapar ett starkt typat objekt.

2. Du säger "Klart man måste veta vilken rad man ska ta ut data/skriva till.
dataset.kunder[12].namn.
Det gör du också, antingen från DataTable:t(under ytan) eller från din Collection."
- FEL. Jag använder som sagt inte O/R mapper men bygger ett eget affärslogik lager som utför samma saker. Med mina starkt typade object behöver jag inte veta vad databaskolumnerna heter, objektet har sina attribut istället. Kanske fattade ditt inlägg fel.
När jag har en collection av mina objekt kan jag databinda rakt av mot t.ex ett DataGrid. Jag behöver bara plocka ut objektets attribut i griddets ItemTemplate.
DET är vad flerskiktslösningar handlar om. PresentationsLogiken behöver inte veta något om datalagret, det sköter affärslogiklagret.

Nu får du sluta tjafsa om dina dataset som Visual Studio genererar. Du jobbar på det sättet och kan tydligen inte ta åt dig andras åsikter. Du har snurrat in dig i att VS.NET hjälper dig att snabbt bygga dina applikationer men vad jag förstår så finns det inget som helst återanvändbart till nästa projekt.

Flerskiktslösningar och objekt-orienterad programmering är något som funnits länge och det av en anledning. Man vill inte göra samma saker om och om igen. Det är därför ObjectSpaces kommer i nästa version av VS.NET.

Sen som du säger, tanken med O/R mapper är god, men jag använder det inte heller därför att jag anser att de inte kan göra tillräckligt komplicerade frågor. Jag bygger mina applikationer på en välutvecklad databas och vill ha stored procedures som returnerar specifika resultat. Ju mindre data en sp returnerar desto bättre prestanda. Det är en av de stora nackdelarna med en OR mapper, OCH den lösningen du pratar om hela tiden.

Medlem sedan juli 20011 304 inlägg
#69

walker:
Ta en titt på Gentle.net och obj.net
Båda har sina för och nackdelar.

Nöff:
Vet inte om du menar vilken o/r mapper jag eller gladh använder men jag använder en egenutvecklad. Den använder en datareader för att fylla objekten.

Det som gör att den blir lite slö är att jag använder reflection men det påverkar inte prestandan annat än på pappret. Hela debatten om prestanda är imho grovt överdiven. Hur man än gör blir prestandan så väldigt bra med .NET särskilt jämfört med asp eller php :)

Den största applikationen som använder o/r mappern har ca 2500 användadre. Det räknar jag som ett medelstort projekt.
Det lite mer kluriga i historien är att flera olika databaser används - ibland t.om på samma sida.

Dat är helt ovärderligt att ha en oo-struktur och en vettigt lagerstryktur på projekten när de blir stora. Detta har jag bittert fått erfara tidigare.

Grundfrågan i den här tråden var ju Bygga en egen db-klass. Jag antog att det var en fråga som syftade till att skapa kunskap eller förutsättningar för att bygga större projekt. Därför tycker jag att heöa debatten med Datasets och prestanda är i helt fel tråd. Lite synd om vi kom ifrån ämnet även om jag tycker att det ska debatteras och växlas åsikter!

Medlem sedan apr. 2004778 inlägg
#70

Ja du Jon, den här tråden spårade ur för längesen.

Medlem sedan apr. 2004778 inlägg
#71

En liten fråga. En sådan här diskussion med så olika åsikter gör mig nyfiken på vad alla har för bakgrund.
Hur länge har ni hållit på? Vad har ni gjort? Vad har ni gått för väg?

Medlem sedan okt. 2002188 inlägg
#72

Jon skrev:

walker:
Ta en titt på Gentle.net och obj.net
Båda har sina för och nackdelar.

du menar ojb.net? tycker inte om den koden.. kan dock inte sätta fingert på varför jag inte tycker om den, men där är något i tänket i den som jag inte tycker om..

Gentle ser intressant ut.. Är ett tag sedan jag tittade på den men är där inte någon skum lösning i lazyload.. ahh strunt samma..

Nöff:
Klipp...

Det som gör att den blir lite slö är att jag använder reflection men det påverkar inte prestandan annat än på pappret. Hela debatten om prestanda är imho grovt överdiven. Hur man än gör blir prestandan så väldigt bra med .NET särskilt jämfört med asp eller php :)

de flesta or-mappers använder sig nog av reflections.. Jag lekte lite med sisyphus innan, och där används också reflection vilket jag inte var så förtjust i pga prestandan.

Så jag ryckte ut alla de objekt som använde reflection och sedan skapade jag ett objekt som endast hade hand om mappningen, som sker mha av reflections men, denna info kan skriva ut till en xmlfil som jag sedan mha av codesmith kan generera klasser som sköter mappningen utan reflektions. Sisyphus har ganska snygg arkitektur så det var lätt att plocka ut det, dock är där lite buggar i det, dock inte relaterade till detta, som jag inte vet hur jag skall lösa..

Medlem sedan maj 20012 812 inlägg
#73

citat:
--------------------------------------------------------------------------------

Efterdet så måste du typcasta ditt värde till rätt typ:
((int)(this[this.tableelement1.TransactionIdColumn]));

--------------------------------------------------------------------------------

Du tycks ha glömt att din O/R mapper fyller ett DataTable från databasen, och från DataTable:t fyller den en Collection, det handlar alltså om 2 feta objekt som måste fyllas innan du har tillgång till dina data. När det handlar om dataset så fylls BARA DataTablet och inget mer, alltså bara 1 objekt, DataSet-DataTables gör hälften av vad O/R mappern gör, därav går det snabbare.

Nu prata vi helt två skilda saker här:

Jag pratar om att hämta ut värden från ett Typat DataSet som redan har all data inladdad.

Du pratar om att ladda in data i mina collections av objekt.

Eftersom det typade Datasetet inte fungerar som jag trodde så kan jag hålla med dig om att det går fortare att ladda ett DataSet med data än collections av object med O/R Mapper.

MEN MEN MEN.
Eftersom det typade datasetet inte fungerar som jag trodde så blir prestandan när det används så mycket sämre än vanliga objekt. Så här fungerar det nämligen.

1. Både DataSetet och O/RMappern får en DataTable från DAL:et (ingen av dem fyller en DataTable (vi borde snart kunna vara överens om detta tycker jag)). Och här kommer skillnaderna.

DataSetet lägger in DataTablen i en collection av något slag(säkert en HashTable) och sedan är den färdig.

O/R Mappern måste loppa igenom DataTablen och hämta ut datan, skapa ett objekt och sedan fylla detta objekt med data. Detta tar längre tid än att bara stoppa DataTablen i ett DataSet.

Denna skillnad är dock nästan försummbar då det som tar tid är inte skapandet av DataTable/DataSet/Object/Collection av objent. Utan Databasanropet och transport av data från databaservern till din applicationsserver. Vi pratar millisekunder och sekunder i detta skede, medans vi pratar mikrosekunder för att skapa och fylla ett objekt. Alltså kommer den slutliga prestanda skillnaden var extremt liten.

2. Vi har nu ett Typat DataSet som innehåller en DataTable med data, och vi har Collections av object som innehåller data.

Datan i ett objekt finns redan lagrat i sina rätta variabler, alltså behövs ingen vidare bearbetning för att få ut rätt data.

Datan i typade datasets ligger i DataTablen och alltså behövs minst 3 operationer för att få ut rätt data och oftas inkluderas en TypCastning från ett objekt till en ValueType (så kallad boxing/unboxing) och detta är prestandkrävande. Problemet med ett typat dataset är att detta sker varje gång som man vill hämta ut data. Så vill du hämta ut Namnet på en kund 4 gånger så görs det alltså 3*4 operationer. Medans för ett objekt som är fyllt från en O/R Mapper så görs detta endast när objektet fylls med data alltså 1 gång.

Detta betyder att det tar längre tid att ladda in storamängder data via en O/R Mapper än via ett typat DataSet, återigen så är denna tid iprincip försumbar eftersom den största tiden läggs på att hämta data från Databasen och inte skapandet av objekt. Igengäld så är prestandavinsterna större när man väl skall använda datan, eftersom datan redan finns i rätt format, och man slipper söka efterden i ett DataTable.

man behöver andra snabbare objekt som är skapta enbart för sådana här saker, och det är dom objekten vi kommer få se i ADO.NET2.0.

Om man inte har byggt in stöd för att lagra objekt i Yukon, alltså en objektorienterad databas istället för relationsorienterad, så kommer ObjectSpacer som kommer i ADO.NET 2.0 fungera på samma sätt som O/R Mappers fungerar idag.

Och har man byggt in stöd för OO databas, så behöver man ingen O/R Mapper eftersom den då har flyttats in i databasen. Matrise (tror jag den heter) är en objeckt orienterad databas som har stöd för .NET. Där kan man hämta och spara object direkt ner mot database, vilket gör att "O/R Mappern har flyttats in i databasen"

Vilken O/R mapper använder du?.
Min egen som jag har knåppat ihop.

- M

Medlem sedan maj 20012 812 inlägg
#74

En sak som jag är nyfiken på är relationerna i ett typat dataset.

Säg att jag har en Kund, och denna kund har en massa ordrar.

I mitt kund objekt lägger jag ett CollectionObjekt av Ordrar och på detta sätt kan jag få reda på vilka ordrar som en kund har.

i DataSeten så lägger du en DataRelation mellan dessa 2 tabeller, det stämmer va? Om du gör det så borde båda tabellerna laddas in vid skapande av DataSetet. Om det är fallet så laddar man ju mer data än vad man behöver. Det kan ju faktiskt vara så att du aldrig använder dig av information om Ordrarna utan nöjer dig med kund informationen.

Däremot i mitt objekt så har jag ett tomt OrderCollectionobjekt som jag fyller med data när jag efterfrågar just denna information.

- Magnus

Medlem sedan apr. 2004778 inlägg
#75

Gladh: Antar att du syftar på Matisse som är en Post-Relational databas. Finns mer information på http://www.codeproject.com/dotnet/introtomatisse_part1.asp
Känns som att det börjar bli läge att ta en titt på det.

Medlem sedan maj 20012 812 inlägg
#76

Hur länge har ni hållit på? Vad har ni gjort? Vad har ni gått för väg?

Jobbat som C# utvecklar för ett kreditinstitut i lite mer än ett år nu, där vi bygger Middleware lösningar och integrationsprogram.
Har dock sysslat med .NET sedan Beta 2 av VS.NET kom ut.

Har jobbat 2 år tidigare som VB programmerar, och har en 3 årig högskoleutbildning.

Började som webutvecklar med ASP 97 som man lärde sig helt själv.

- M

Medlem sedan maj 20012 812 inlägg
#77

de flesta or-mappers använder sig nog av reflections..

Man måste (väl) använda sig av reflections för att fylla sitt objekt med data. Annars får man göra lösningen som finns i typade datasets, alltså lägga datan i en HashTable och sedan hämta ut den efterhand.

Jag har då inte hittat något sätt att fylla en variabel i ett objekt dynamiskt utan att använda mig av GetType() och SetValue(). Om du vet något annat sätt är jag riktigt intresserad.

Själv har jag Attribute på alla variabler som skall fyllas med data, dessa hämtas ut med hjälp av reflections, men cachas sedan, så att om man fyller en collections med data, så behöver man endast hämta ut attributen en gång.

- M

Medlem sedan maj 20012 812 inlägg
#78

Antar att du syftar på Matisse som är en Post-Relational databas.

Japp, tittade lite på den, men "demo" verison var tidsbegränsad till typ 30 dagar eller något sånt löjligt.

Antar att Yukon blir ett lyft då man skall kunna skriva C# kod i den, helt plötsligt finns det risk att man flyttar ner sin O/R Mapper ner i SP's som fyller ett objekt med data och skickar till applikationen :)

- M

Medlem sedan apr. 2004778 inlägg
#79

Ja, det verkar som att med Yukon så flyttas affärslogiken ner till datalagret. Förhoppningsvis så funkar det som det ska.

Medlem sedan juli 20011 304 inlägg
#80

Hur länge har ni hållit på? Vad har ni gjort? Vad har ni gått för väg?

Har 4 års utbildning i systemvetenskap/datalogi
Har jobbat i ca 5 år med utveckling. Har drivit eget företag i 3 år och jobbat på ett par stora förtag ett par år.

Började mest utveckla i VB, men har jobbat en del med C, C++, asp, php och java och nu jobbar jag nästan uteslutande med .NET :)

Ja, det verkar som att med Yukon så flyttas affärslogiken ner till datalagret. Förhoppningsvis så funkar det som det ska.

mmm. Jag blir direkt lite skeptiskt. Men men. Man får väl vara öppen för nya lösningar. Jag har gärna 4-5 lager när jag ska designa lösningar men jag kanske är lite extrem i vissa fall. Beror väl på att jag har varit inblandad i bygget av ett riktigt stort system i VB för ett par år seddan som inte hade någon egentlig lagerstruktur. Det var en mardröm att underhålla koden som ni säkert förstår.

267 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
118 ms — deklarationer (db)
0 ms — hämta statistik (cache)
145 ms — hämta tråd, inlägg och bilagor (db)
120 ms — ändringar (db)