webForumDet fria alternativet

Bygga en egen dbklass

.NET

118 svar · 5 017 visningar · startad av Swordfishy · sida 6 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 nov. 2003569 inlägg
#101

Clarkbones.

Jag har nu hittat 3 böcker (2 från Wrox) som skriver att globala variablar i allra högsta grad existerar.
Vilka ska jag välja att tro på?, ni eller vad 2 erkända författare skriver?.
I "Beginning ASP.NET 1.0 with C#.NET" från Wrox finns på denna Download-sida i Chapter 6 svart på vitt.
http://www.wrox.com/dynamic/books/download.aspx

Här har du nu en applikation som har använt ett objekts variabel, 3 gånger. Till denna sker endast 1 typcastning, medans ditt DataSet kräver 3.

Du glömmer att med ditt sätt måste du fylla ytterligare 1 collection med alla data, jag fyller bara 1, DataTable:t.

Medlem sedan apr. 2004778 inlägg
#102

Nöff, du måste lära dig förstå vad du läser och vad andra säger.
Det finns globala variabler men sen måste man ta reda på var variabeln är "global". Traditionellt sett så är en Global variabel tillgänglig från alla delar av en applikation. I en webbapplikation skulle denna läggas i global.asax under Application.

Det förra exemplet du visade var en variabel som var GLOBAL för den klassen. Det vill säga den var tillgänglig för klassens alla metoder.
Exemplet du visar du demonstrerar en variabel som är global för den sidan. Alltså Pageklassen. Den är inte global i applikationen. Endast global på den sidan.

Så man kan säga så här, du har både rätt och fel. Men lär dig att skilja på begreppen.

Medlem sedan maj 20012 812 inlägg
#103

Du glömmer att med ditt sätt måste du fylla ytterligare 1 collection med alla data, jag fyller bara 1, DataTable:t.

Måste nog hålla med PDahlen. Maken till svårighet att ta till sig information har jag aldrig varit med om. Har redan skrivit ett otal gången att när man fyller collectionen med data från databasen, så är det inte själva skapandet av collectionen som tar tid. Det är hämtandet av data, och det måste du göra med ditt DataSet med.

Tyvärr kan jag inte föklara det tydligare, om det är någon annan än Nöff som tycker att jag har varit otydlig så får ni gärna säga till, för jag tycker verkligen jag har förklarat det så gott jag kunnat.

Om man inte vill lära sig något så kan man inte ta det till sig, det kanske passar in på dig Nöff, så därför frågar jag alla andra som läst tråden om de förstår vad jag menar?

Angående de global variablerna, så behöver vi inte ta upp det i denna tråd de kan diskuteras i den sin egen tråd.

- Magnus

Medlem sedan juli 20022 537 inlägg
#104

Gladh, då du verkar kunna en hel del om ADO.NET undrar jag om du har några tips på böcker som tar upp ämnet (gärna om hur man bygger upp en O/R Mapper).

Tack på förhand

Medlem sedan nov. 2003569 inlägg
#105

gladh, körningsstrukturen från Databasen till DataTable:t är exakt samma med O/R och DataSet, det är efter det som kommer efter skillnaden ligger:

Om vi jämför lite, med 1 kolumn med ett Int värde för att göra det enklare att se.

Vad kostar mest?:

1. Instansiera 1 DataRow.
2. Fyll DataRow:et med 1 värde.
2. Typkonvertera värdet i DataRow:et 1 eller 2 gånger , beror helt på situationen.

Eller:

1. Instansiera 1 DataRow.
2. Fyll DataRow:et med 1 värde.
2. Instansiera 1 nytt Object.
3. Typkonvertera värdet i DataRow:et 1 gång .
4. Lägg det typkonverterade värdet i Object:et.

Medlem sedan apr. 2004778 inlägg
#106

Vad kostar mest?:

Gör en exempel körning med testdata och presentera resultatet.
Sen kan du diskutera vad som "kostar" mest.

Om du läser denna länk, som redan skickats in en gång, http://weblogs.asp.net/pwilson/archive/2004/01/14/58721.aspx
så kan man läsa att i detta testfall så är DataSet snabbare än OR-mappern.
Så ja, din lösning är då snabbare.

MEN, här kommer det jättestora MEN som du vägrar greppa. Om du jobbar på ett stort projekt, dvs. ett projekt där ni är fler än en person, så håller inte din lösning.
Den håller inte heller i en objekt-orienterad miljö, vilket oftast är fallet i verkliga livet.
Den håller heller inte om applikationen t.ex. ska kunna användas både som webb-applikation och desktopapplikation.
Så det du vinner i mikrosekunder på att använda din lösning förlorar du i längden för du måste göra precis samma sak varenda gång du börjar med ett nytt projekt och du kan inte bygga några standardlösningar.

Nu ger jag fan upp, jag har aldrig stött på en människa som är så obenägen att lära sig nya saker och utvecklas.

Medlem sedan okt. 2002188 inlägg
#107

Gladh skrev:

Mapperklassen konveterar objektet till rätt typ och sätter sen alla properties. Så istället för setValue så blir det ex. item.Name = reader(2);

Walker, jag gör som din första beskrivning, har attribut på alla variabler, och läser in dessa i en cache. Och med SetValue så sätter jag datan.

Däremot så blir jag riktigt intresserad av ovanstående: item.name = reader(2);
Jag har letat efternågot sånt. Att matcha ihop reader(2) och name är ingen konst, det är att göra en dynamisk: item.name som blir svår. Eller är detta något som skapas för varje klass, så om du har 2 klasser så får du 2 stycken funktioner, alltså en funktion som fyller klass1 och en som fyller klass2 och dessa funktioner skapas som kod utifrån klasserna. Alltså lite som en codegen.

Har du en länk till sisyphus så man kan se hur de har gjort?

- magnus

Hej

Yepp, det är ungefär så som du beskriver som jag gjort..
Men jag tror jag vilseledde dig lite innan.. men här kommer lite kod och kommentarer

Om du laddar ner koden för sisyphus så ta den som finns i cvs'en, den andra fungerar inte. (den kanske fungerar men den är out of date)

Allting händer i klassen SpfEntityStorageDefn och det är metoden PopulateEntity som jag ändrat i.


		public void PopulateEntity(IDataReader p_Reader, SpfEntity p_Entity)
		{
			this.Populate(p_Reader, p_Entity);

//			foreach (SpfFieldDefn fieldDefn in m_FieldDefns) {
//				if (fieldDefn.IsLoaded) {
//
//					object fieldValue;
//					if (p_Reader[fieldDefn.ColumnName] == DBNull.Value) {
//						fieldValue = null;
//					}
//					else {
//						fieldValue = fieldDefn.DataType.ConvertValue(p_Reader[fieldDefn.ColumnName]);
//					}
//
//					fieldDefn.Member.SetValue(p_Entity, fieldValue);
//
//				}
//			}

		}

Som du ser så anropar jag populate som ser ut så här

private void Populate(IDataReader p_Reader, SpfEntity p_Entity)
		{
			IMap _currentMapper = MappersCollection.GetMapper(p_Entity.GetType());
			p_Entity = _currentMapper.Populate( p_Reader,  p_Entity, this.m_FieldDefns);
		}

Vidare..

public static IMap GetMapper(System.Type type)
		{
			if (_mappers == null)
			{
				InitMappers();
			}

			IMap currentMapper = (IMap)_mappers[type];

			if (currentMapper  != null)
			{
				return currentMapper;
			}
			else
			{
				return _defaultMapper;
			}
		}

_defaultMapper är egentligen den koden som finns i PopulateEntity i SpfEntityStorageDefn klassen, men inkapslad i en klass och i denna så har sist i koden lagt in.

#if DEBUG
  WriteXml(fieldDefs, entity);
#else 		
// gör inget.
#endif

från den xmlfilen som skrivs ut så skapar jag sedan en mappningsklass som ser ut som följer. Denna lägger jag till sedan i MappersCollection, antingen så genererar jag denna också mha codesmith eller så lägger jag till dem för hand.

public class UserMap : Sisyphus.IMap
	{
		public UserMap()
		{
			
		}

		public Sisyphus.SpfEntity Populate(System.Data.IDataReader reader, Sisyphus.SpfEntity user, SpfFieldDefn[] fieldDefs)
		{
			BO.User usr = (BO.User)user;
			usr.Name = reader["name"].ToString();
			return ( Sisyphus.SpfEntity)usr;
		}

	}

det är ett tag sedan jag gjord detta, la ner det pga sisyphus innehöll för mycket buggar som jag aldrig orkade rätta, om jag ens kunde hitta vart det gick fel.. och det är egentligen väldigt enkelt gjort..

Nackdelarna är att man alltid måste dra med sig sisyphusprojektet så att detta finns i samma sln som ens affärslogik och man skapar en ganska hård koppling mellan bl och dl.. men det fungerade för mig. Man kan nog lösa det genom att trixa lite med interfaces, men la ner det hela pga buggar och att det kom lite andra saker emellan..
Jag har inte testat om man kan göra samma sak med collections men det borde fungera.. Men som sagt, koden är inte 100%, ser nu att null hantering inte finns med och inga try and catch, osv.. men men..

Medlem sedan apr. 2004778 inlägg
#108

Är det OK om vi fortsätter ORM diskussionen i en annan tråd? Har skapat en ny på http://www.webforum.nu/showthread.php?s=&threadid=99550

Medlem sedan okt. 2002188 inlägg
#109

Hej

Är ingen stor fan av dataset så tänkte ställa lite frågor till nöff som verkar tycka om dem.

Hur sköter du valideringen av fälten, är det genom händelsen som inträffar när du uppdaterar raden dvs, RowChanging händelsen?

Vart lägger du valideringsmetoderna?

Om du döper om ett fält i databasen, innebär inte det att du får döpa om en hel del saker i hela applikationen, om du jobbar så som du säger att du gör? Dvs drag and drop för att skapa ds. Eller om applikationen skall översättas till engelska och du har svenska namn på fälten i dbn?

Hur löser du lazlyload?

Hur delar du upp datatabellerna? Om jag förstår dig rätt så laddar du tex alla kunder i ett dataset och sen alla produkter för alla kunder? Blir inte detta en väldig massa saker att ladda? Har iofs bara gjort ett riktigt stort projekt, på egen hand, men där hade jag ca 10000 kunder där varje kund hade ungefär 40 orders, varje order bestod sen av en massa orderrader.

Eller har du någon annan logisk uppdelning av tabellerna?

Hade varit intressant om du hade något projekt som du kunde dela med dig av så att man ser hur du jobbar med dataseten.. Tycker som sagt inte om dem, men de har sina fördelar.

(Ibland när jag skriver så låter det provocerande, det är absolut inte meningen att det skall tolkas så.)

Medlem sedan nov. 2003569 inlägg
#110

Den håller heller inte om applikationen t.ex. ska kunna användas både som webb-applikation och desktopapplikation.

Det är precis det den gör, du har HELT missuuppfattat hur jag använder dataset , adapter.
Det jag har försökt visa i de 3 senaste sidorna är hur man gör ett "extended" dataset.
Något som inte finns i VS.NET naturligt. Du tror att jag "drar in" adapters i VS.NET och trycker "generate DataSet" på alla mina projekt.
Visst, detta visade jag i sid 1, men 2 sid och frammåt använde jag ett helt annat sätt att använda
dataset:t, alltså göra det till en fristående klass med ALL dataccess inbyggd, med pricken över i:et att
dataset:et också blir händelstyrt, detta dataset existerar INTE "naturligt" i VS.NET, och jag har aldrig
sett det byggas någon annanstans. kanske är möjligt att någon gjort det, men jag har då aldrig
sett det.

Så det du vinner i mikrosekunder på att använda din lösning förlorar du i längden för du måste göra precis samma sak varenda gång du börjar med ett nytt projekt och du kan inte bygga några standardlösningar.

Detta citat bevisar att du missuppfattat ALLT från början.
Det är precis detta jag INTE gör med mitt "extended" dataset, jag drar inte in alla adapters och trycker Generate dataset på alla mina projekt.
På sid 2 visade jag HUR man bygger ett extended DataSet så att man kan ÅTERANVÄNDA det i hur många web och winform projekt som helst.
Alltså, Jag skapade en .dll av mitt dataset, och bygger in ALL dataacces inne i dataset:et!, och samtidigt gör den händelsestyrd.
Med det menas är att om jag ändrar mitt dataset i runtime, tex lägger till en ny rad i DataTable:t så känner dataset:et av detta och gör en update i den riktiga databasen
UTAN att jag behöver anropa något DAL (detta görs i dataset:ets inbyggda event istället). Och denna "extended" dataset KLASS med sitt inbyggda DAL återanvänder jag sen
i 1000 olika webprojekt och 1000 olika winformsprojekt precis som jag visade!. UTAN att jag behöver "dra in" några adaptrars.
Jag instansierar bara min dataset klass på de projekt
jag vill ha den på.
DataSet1 mittdataset=new DataSet1(); //kan det bli enklare? , nej!
och ALL dataccess finns inbyggt i dataset:et, trodde du på fullaste allvar att jag sitter
som en dåre och drar in 10 adaptrar och skapar ett nytt dataset i VS.NET varje gång jag skapar ett nytt projekt?

Du behöver läsa detta inlägg om det extended dataset jag skrev om i sid 2 om och om igen:
http://www.webforum.nu/showthread.php?postid=831587#post831587
Och där skrev jag ocskå hur man gör dataset:et objektorienterat så man kan instansiera ur varje DataTable klass för sig. precis som en O/R mapper(Collection)

Medlem sedan maj 20012 812 inlägg
#111

public Sisyphus.SpfEntity Populate(System.Data.IDataReader reader, Sisyphus.SpfEntity user, SpfFieldDefn[] fieldDefs)
{
BO.User usr = (BO.User)user;
usr.Name = reader["name"].ToString();
return ( Sisyphus.SpfEntity)usr;
}

Det betyder att du behöver en sådan här funktion för varje klass som du skapat. Här har du en för User, om du har en klass som heter Order så behöver du en ny funktion, har jag rätt?

Så fall har man slagit ihop en codegenerator och en O/R Mapper? Tagit det bästa från 2 världar, det kanske är vägen att gå, med din Populate funktion så slipper man ju reflections, och på det sättet så ökar man prestandan. Det har ju dock nackdelen att man måste skapa nya Mapfunktioner när man gör om i sin klass, om man dock lägger det i en ifDef #debug så görs det ju automatiskt när man debugar, och aldrig när man gå live. Klart värt att tänka på, sitter dock och väntar lite på vad som händer i objectSpacer innan jag orkar ta tag i min O/R Mapper, känns som att MS kommer slå undan benen för många andra O/R Mappers.

- magnus

Medlem sedan nov. 2003569 inlägg
#112

...jag vill röka fredspipa ;)

Medlem sedan okt. 2002188 inlägg
#113

Gladh skrev:

Det betyder att du behöver en sådan här funktion för varje klass som du skapat. Här har du en för User, om du har en klass som heter Order så behöver du en ny funktion, har jag rätt?

Yepp.. Men i och med att xmlfilern skrivs ut så så är det bara att ta dessa och låta codesmith generera filerna, sen lägger jag bara in dem i projektet. Jag får göra detta manuellt men det tar inte många sekunder. Skulle det inte finnas någon mappningsklass så används reflections så det är inte hela världen om man glömmer det eller struntar i det. En nackdel är att man endast kan sätta värden i properties som är publika, men jag har aldrig haft behov av något annat..

Gladh skrev:

Så fall har man slagit ihop en codegenerator och en O/R Mapper? Tagit det bästa från 2 världar, det kanske är vägen att gå, med din Populate funktion så slipper man ju reflections, och på det sättet så ökar man prestandan. Det har ju dock nackdelen att man måste skapa nya Mapfunktioner när man gör om i sin klass, om man dock lägger det i en ifDef #debug så görs det ju automatiskt när man debugar, och aldrig när man gå live. Klart värt att tänka på, sitter dock och väntar lite på vad som händer i objectSpacer innan jag orkar ta tag i min O/R Mapper, känns som att MS kommer slå undan benen för många andra O/R Mappers.

Jag vet inte om det är bästa vägen att gå, men man kommer runt det där med reflections, vilket var mitt mål. Har aldrig sett någon O/R-mapper som gör så här.
Men egentligen så passar det kanske inte in i ett färdigt ramverk för det blir lite pusslande inne i koden. Så det är kanske därför folk inte använder det. Men om man vet hur ramverket fungerar så borde det inte vara någon risk med att göra det.. Fint med opensource, så att man ser vad som händer.

En rolig sak skulle vara att skapa dessa mappningsklasser dynamiskt och kompilera dem direkt till en dll som man sedan laddar , om man lyckas med detta så skulle man aldrig behöva pilla i koden.

Men som sagt, jag gjorde inte allt klart pga statusen på sisyphus. Det hade varit intressant och se om man kunde komma från reflections helt och hållet, jag tror det skulle fungera.

hmm..nu blev jag sugen på c# igen..

Medlem sedan apr. 2004778 inlägg
#114

Nöff

...jag vill röka fredspipa

Jo, det skulle vara bra.

Först kan jag be om ursäkt att jag missförstod några saker i din diskussion.

Nu är jag med på vad du försökte få fram. Har rotat igenom mina bookmarks och jag har en bunt med artiklar på ämnet. Jag håller fortfarande inte med dig men jag tror att hela .NET programmeringsvärlden är uppdelad i den här frågan.
Det pågår en väldigt intressant diskussion på http://objectsharp.com/Blogs/barry/archive/2004/02/10/273.aspx
Där finns även hänvisningar till andra diskussioner.

Många bra punkter åt båda hållen, men som sagt, jag håller på custom entities.

Medlem sedan maj 20012 812 inlägg
#115

En rolig sak skulle vara att skapa dessa mappningsklasser dynamiskt och kompilera dem direkt till en dll som man sedan laddar , om man lyckas med detta så skulle man aldrig behöva pilla i koden.

Skall inte vara så svårt, titta lite på Emit i reflections klassen, den skall man använda för att skapa kod, där kan du även kompilera din .cs/.vb filer i runtime. Alltså kan du i debugläge:
1. skapa dina mapningsfiler utifrån dina attribute i klassen.
2. kompilera dessa in i ditt "framework".

Nu kommer du alltid få rätt mapningsfiler när du kör i debug-läge, och du slipper pilla in några filer själv. Så hade jag löst det.

Anledningen till att du aldrig sett det i O/R Mappers (tror wilson gör något liknande, PDahlen har kanske sourcecode, han hade iallafall mappern, eftersom han kan ha både reflections och direkt, som han kallar det) är att det mer liknar en codegenerering. Du skulle iprincip istället kunna generera alla dina businesklasser utifrån din databas, då slipper du en O/R mapper helt och hållet och kan fokuser på prestanda.

Tyvärr lär all din businesslogik försvinna om du generera om dina klasser. Jag skulle i sådant läge istället använda mig av en massa manager-klasser som man skriver förhand och så pillar man aldrig i businessklasserna. Det vill säga att dina klasser endast är dumma databärare som kan serialiseras. Sedan får dina Managerklasser sköta all logik. Gissar att det blir någotsånt man får göra när man går över till SOA tekniken, för att spara nätverkstrafik.

- Magnus

Medlem sedan apr. 2004778 inlägg
#116

Så det funkade inte att flytta till tråden för O/R Mappers? :(

Medlem sedan maj 20012 812 inlägg
#117

Så det funkade inte att flytta till tråden för O/R Mappers?

FÖRLÅT!!! Skall använda den tråden hänadefter, hoppas du inte är allt för ledsen på mig. :r

- Magnus

Medlem sedan apr. 2004778 inlägg
#118

Joo, :( *snyft* *snyft*

Medlem sedan juli 20022 537 inlägg
#119

PDahlen skrev:

Joo, :( *snyft* *snyft*

Bjuder PDahlen på en öl som tröst :bire

289 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
126 ms — deklarationer (db)
0 ms — hämta statistik (cache)
157 ms — hämta tråd, inlägg och bilagor (db)
129 ms — ändringar (db)