Jag är väl ingen hejare på C#, men så här tänker jag.
Sista två raderna ska du ersätta med bara return objDataReader;
VB's sätt att returnera saker funkar inte alls i C# (Iofs har jag inte prövat, men det vore dumt isf)
Vad gäller felhanteringentycker jag att du bör ta bort den helt ur denna funktion. OM det nu faktiskt sker ett fel bör det faktiskt kastas bör du ju se det så att du kan korrigera det, inte att felet bara ignoreras. Ev behöver du ändra funktionsdefinitionen till public OleDbDataReader DbReader(String mySql) throws Exception
för att kunna ta bort try...catch.
Personligen skulle jag inte returnera något inne i ett try-catch-block. Dessutom är det bra om du stänger din connection i metoden, förslagsvis i finally { ... }
public OleDbDataReader DbReader(String mySql)
{
OleDbConnection objConn = new OleDbConnection();
OleDbCommand objCmd = new OleDbCommand(mySql, objConn);
objCmd.CommandType = CommandType.Text;
OleDbDataReader objReader;
try
{
objConn.Open();
objReader = objCmd.ExecuteReader(CommandBehavior.CloseConnection);
// Inte returnera inne i try { .. }
}
catch(Exception Ex)
{
dbReader = Nothing;
//LogError(Ex.Message);
// Här skulle jag kasta om felet
throw new Exception(ex);
}
finally // Körs oavsett om ett fel uppstår, eller ej.
{
// Stäng databasanslutningen om den är öppen.
if (objConn.State == ConnectionState.Open)
objConn.Close(); //Stäng anslutningen
}
// Returnera readerobjektet
return objReader;
}
Det stämmer att man ofta stänger en datareader eller connection (båda i detta fallet) i ett finally block. Jag skulle göra som nitro2k01, men om man vill returnera den kan det tyckas märkligt att sedan returnera en stängd datareader. Det nitro2k01 menar med felhanteringen är att den som ropar på din funktion aldrig får reda på om det gick åt skogen, det enda som görs är loggingen. Din funktion kommer då inte att returnera någonting (den borde därför inte ens gå att kompilera) vilket kommer att generera ett annat (typ av) fel.
Det måste alltså vara upp till den som ropar på funktionen att stänga datareadern. Jag gör oftast inte på detta vis då det bäddar för fel och att man inte har kontroll över om den stängs eller inte. Men det kan vara befogat om en annan funktion använder funktionen som hjälp istället för att öppna en reader från scratch eller så.
Men som sagt: ta en funderare på om du är säker på att du vill skicka runt öppna datareaders hur som helst.
Vad det gäller själva koden ser den lite skum ut:
* Jag antar att OleDbConnection(objConn); och OleDbCommand(mySql, objConn); är anrop till andra funktioner. Lite otydliga namn i så fall ;)
* OM det är så att OleDbConnection och OleDbCommand returnerar objekt som du använder är det onödigt att skapa new på dom lite högre upp, de referenserna sätts ju om omgående.
* Du ska inte sätta DbReader till din datareader, det räcker med att returnera den.
* Varför skickar objConn med sig själv till OleDbConnection?
* Skicka vidare exception i din catch efter loggingen.
Försök att göra om den lite så ska vi hjälpa dig att få till det rätt :)
Detta kanske inte är det bästa sättet men så brukar jag göra i SQL SERVER:
lägg ConnectionString i web.config
t.ex
<connectionStrings>
<add name="NorthwindConnectionString"
connectionString="Data Source="din server";Initial Catalog="databas"; Integrated Security=True; Min Pool Size=20"
providerName="System.Data.SqlClient"/>
</connectionStrings>
Skapa särskild klass för connection till DB
t.ex:
public class ConnectionManager
{
public static SqlConnection GetNorthwindConnection()
{
// Hämta COnnectionString från web.config
string connectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
//Skapa DB Connection
SqlConnection connection = new SqlConnection(connectionString);
// Öppna Connection och return det
connection.Open();
return connection;
}
}
Sedan skapar jag egna klasser och metoder för DataAccess
t.ex
public static SqlDataReader GetProducts()
{
string sql = "SELECT * FROM Products";
//Använder SQL connection från min Connection klass
SqlConnection connection = ConnectionManager.GetNorthwindConnection();
//Skapar Command object
SqlCommand command = new SqlCommand(sql, connection);
command.CommandType = CommandType.Text;
//Fyller DataReader med data
SqlDataReader reader = command.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.CloseConnection);
return reader;
}
om du använder VS 2005 använder Du ObjectDataSource för att hämta resultatet till din aspx fil.
Jag skulle returnerat en DataTable istället, och stänga alla db conns så snabbt som möjligt.
Då kan man även passa på att slänga in en .net cache om önskvärt på ett enkelt sätt
Det beror ju förstås på ändamålet, det som han kanske vill göra sedan är att kopiera över det i en objektstruktur, det går ju minst lika bra om inte bättre :).
Det beror ju förstås på ändamålet, det som han kanske vill göra sedan är att kopiera över det i en objektstruktur, det går ju minst lika bra om inte bättre :).
Det är kanske sant. Vet inte riktigt vad som inte skulle gå att göra med DataTable. Vore trevligt med lite mer info om hur detta ska användas, dvs vart tar objDataReadern vägen :birp
Det är kanske sant. Vet inte riktigt vad som inte skulle gå att göra med DataTable. Vore trevligt med lite mer info om hur detta ska användas, dvs vart tar objDataReadern vägen :birp
Man kan nog göra lika mycket med en DataTable som man kan med en objektmodell, dock så kan det diskuteras hur "bra" koden blir. (beror ju helt och hållet på smak och hur duktig utvecklaren är på sin sak). Valet mellan DataTable tänkandet och objektmodell har ju också med kraven på applikationen att göra.
Det finns flera artiklar både för och emot DataTable's så jag tänker inte gå in på vad som är bäst.
Det finns även flera färdiga ramverk som man kan använda sig där man har en hel del funktionalitet färdigt för detta. bl.a. NHibernate som jag rekommenderar starkt.
Det beror ju förstås på ändamålet, det som han kanske vill göra sedan är att kopiera över det i en objektstruktur, det går ju minst lika bra om inte bättre .
Generellt så är det bättre ur skalbarhet att returnera DataTable än en dataReader eftersom man stänger databaskopplingen tidigare. Ju mer kod som man exekverar innan man är färdig med sin datareader, destu bättre blir det med DataTable.
Framför allt så skulle jag använda en DataTable eftersom jag inte riktigt gillar tanken på man stänger databaskopplingen någonstans i koden där "logiken" inte hör hemma. Speciellt viktigt blir det om man bygger ett DAL som andra kan använda sig av, som kanske inte riktigt förstår vikten av att stänga datareader så tidigt som möjligt.
Det beror ju förstås på ändamålet, det som han kanske vill göra sedan är att kopiera över det i en objektstruktur, det går ju minst lika bra om inte bättre .
Generellt så är det bättre ur skalbarhet att returnera DataTable än en dataReader eftersom man stänger databaskopplingen tidigare. Ju mer kod som man exekverar innan man är färdig med sin datareader, desto bättre blir det med DataTable.
Framför allt så skulle jag använda en DataTable eftersom jag inte riktigt gillar tanken på man stänger databaskopplingen någonstans i koden där "logiken" inte hör hemma. Speciellt viktigt blir det om man bygger ett DAL som andra kan använda sig av, som kanske inte riktigt förstår vikten av att stänga datareader så tidigt som möjligt.
- M
Håller med att man enklare kan stänga kopplingen om man retunerar en DataTable istället för en Reader, men det beror ju helt och hållet på vad man anser att sitt DAL är.
Ditt dal kan ju innehålla IList<Customer> UserDAL.GetCustomers() i det fallet så behöver dom andra ändå inte tänka på att readern överhuvudtaget.
Skapar man en Factory där man har en Create metod som retunerar en Customer eller IList<Customer> som tar emot en reader och låter Factoryn allt id stänga readern så har man en generell och konsekvent lösning.
Jag tycker nog inte att det är några problem att man exponerar en DataReader för andra klasser, det beror helt på vilken arkitektur man vill ha.
Rent exekveringstidsmässigt behöver ju inte databaskopplingen stängas senare.
Men visst det kan leda till fler felkällor osv, men som sagt det är en smaksak på vad man vill köra med, i större projekt tycker jag personligen att användade av DataTable's gör utvecklandet mer komplext och mer svårunderhållbar (samt att man lätt går ifrån OOPtänket tycker jag) kod än med en objektmodell.
Ditt dal kan ju innehålla IList<Customer> UserDAL.GetCustomers() i det fallet så behöver dom andra ändå inte tänka på att readern överhuvudtaget.
mmmmm... med det resonemanget så behöver vi ju knappast bry oss om man returnera DataTable eller DataReader, eller hur? Vilket vi diskuterade.
nickemannen skrev:
Skapar man en Factory där man har en Create metod som retunerar en Customer eller IList<Customer> som tar emot en reader och låter Factoryn allt id stänga readern så har man en generell och konsekvent lösning.
Här har du full koll på användandet av din datareader och du bör ju ha koll på att du skall stänga din datareader efter dig. Generellt är det dock en sämre lösning att använda sig av datareader för att skapa dina object än en datatable, eftersom du håller din koppling till databasen öppen längre, samt att du kan få exceptions i kod som inte är direkt relaterade till din datareader vilket gör att man lätt glömmer att stänga datareadern här när felet kastas...
nickemannen skrev:
Jag tycker nog inte att det är några problem att man exponerar en DataReader för andra klasser, det beror helt på vilken arkitektur man vill ha.
Jag är av en annan åsikt, det är det som är det härliga med kodningen det finns ingen absolut sanning.
nickemannen skrev:
Rent exekveringstidsmässigt behöver ju inte databaskopplingen stängas senare.
Det får du gärna utveckla för jag 1) förstår inte hur detta är möligt 2) förstår inte hur du tänker här.
nickemannen skrev:
Men visst det kan leda till fler felkällor osv, men som sagt det är en smaksak på vad man vill köra med, i större projekt tycker jag personligen att användade av DataTable's gör utvecklandet mer komplext och mer svårunderhållbar (samt att man lätt går ifrån OOPtänket tycker jag) kod än med en objektmodell.
Nu är det ju knappast så att vi diskuterat DataTables vs Object. Utan mer dataReaders vs DataTables. Jag använder mig alltid av Objektmodell/entiteter i mina projekt, men har alltid en DataTable när jag skapar mina objekt/listor av objekt istället för en datareader.
mmmmm... med det resonemanget så behöver vi ju knappast bry oss om man returnera DataTable eller DataReader, eller hur? Vilket vi diskuterade.
Du har rätt jag gick nog ifrån ämnet lite.
Det får du gärna utveckla för jag 1) förstår inte hur detta är möligt 2) förstår inte hur du tänker här.
När det gäller tidsmässigt som jag pratade om så använder ju sig DataTable'n sig själv av en DataReader och beroende på hur optimerat du bygger din mappning av data så kan den ju bli snabbare än hur en DataTable läser in sin data. Vid en typad datatable kan det nog gå riktigt snabbt, däremot är det en icketypad datatable så kan det nog ta lite längre tid att fylla din datatable gentemot fylla objekt, därav ser jag att man kan få sin datareader stängd lika fort eller till och med fortare.
När det gäller tidsmässigt som jag pratade om så använder ju sig DataTable'n sig själv av en DataReader och beroende på hur optimerat du bygger din mappning av data så kan den ju bli snabbare än hur en DataTable läser in sin data. Vid en typad datatable kan det nog gå riktigt snabbt, däremot är det en icketypad datatable så kan det nog ta lite längre tid att fylla din datatable gentemot fylla objekt, därav ser jag att man kan få sin datareader stängd lika fort eller till och med fortare.
Vid ett "otypat datatable" så skapas det en del collections som datan läggs ner i.
Typade datatable har jag aldrig ens hört talas om :) men om det finns misstänker jag att det är som ett typat dataset, det villsäga en klass med ett otypat dataset under sig som man anropar vid varje förfrågning av data och det görs en unbox/box vid varje förfrågning till datasetet, att fylla det med data tar dock inte längre tid än ett vanligt otypat dataset eftersom det är det som ligger i botten.
Jag har svårt att se hur det skulle gå fortare att fylla objekt med data jämfört med datatablen, eftersom om du vill fylla objektet så måste du använda dig av reflection (långsamt) för att hitta rätt medlemsvariabler som skall ha datan, du måste också igenom något sorts mappningsförfarande (vilket du slipper med datatablen). Dessutom så kan det finnas event kopplade till dessa, säg att du skapar ett objekt i din ORMapper och när det är gjort så skapar ORMappern ett ObjektCreated-event som du kan lyssna på och göra olika saker med.
Om du då har en datareader så är den fortfarande öppen när eventet skapas, medans med en datatable så är kopplingen stängd. Och du som skapar av ORMappern har ingen som helst anning om vad som sker i koden som lyssnar på eventet...
Nu har jag inte sett några som helst mättningar på detta, men då jag byggt ett par små ORMapper, samt kollat lite på DataTable koden, så kan jag säga att jag inte skulle klara av att optimera min kod så att jag skulle kunna fylla mina listor med skapade objekt snabbare än vad det tar för MS att fylla sitt DataTable. Men det är ju bara jag, du är helt enkelt en bättre programmerare än jag i detta fallet. Vilket ju är asbra eftersom du så fall har sparat in ett moment: data -> datareader -> objekt, medans jag gör: data -> datareader -> datatable -> objekt.
När det gäller tidsmässigt som jag pratade om så använder ju sig DataTable'n sig själv av en DataReader och beroende på hur optimerat du bygger din mappning av data så kan den ju bli snabbare än hur en DataTable läser in sin data. Vid en typad datatable kan det nog gå riktigt snabbt, däremot är det en icketypad datatable så kan det nog ta lite längre tid att fylla din datatable gentemot fylla objekt, därav ser jag att man kan få sin datareader stängd lika fort eller till och med fortare.
Vid ett "otypat datatable" så skapas det en del collections som datan läggs ner i.
Typade datatable har jag aldrig ens hört talas om :) men om det finns misstänker jag att det är som ett typat dataset, det villsäga en klass med ett otypat dataset under sig som man anropar vid varje förfrågning av data och det görs en unbox/box vid varje förfrågning till datasetet, att fylla det med data tar dock inte längre tid än ett vanligt otypat dataset eftersom det är det som ligger i botten.
Jag har svårt att se hur det skulle gå fortare att fylla objekt med data jämfört med datatablen, eftersom om du vill fylla objektet så måste du använda dig av reflection (långsamt) för att hitta rätt medlemsvariabler som skall ha datan, du måste också igenom något sorts mappningsförfarande (vilket du slipper med datatablen). Dessutom så kan det finnas event kopplade till dessa, säg att du skapar ett objekt i din ORMapper och när det är gjort så skapar ORMappern ett ObjektCreated-event som du kan lyssna på och göra olika saker med.
Om du då har en datareader så är den fortfarande öppen när eventet skapas, medans med en datatable så är kopplingen stängd. Och du som skapar av ORMappern har ingen som helst anning om vad som sker i koden som lyssnar på eventet...
Nu har jag inte sett några som helst mättningar på detta, men då jag byggt ett par små ORMapper, samt kollat lite på DataTable koden, så kan jag säga att jag inte skulle klara av att optimera min kod så att jag skulle kunna fylla mina listor med skapade objekt snabbare än vad det tar för MS att fylla sitt DataTable. Men det är ju bara jag, du är helt enkelt en bättre programmerare än jag i detta fallet. Vilket ju är asbra eftersom du så fall har sparat in ett moment: data -> datareader -> objekt, medans jag gör: data -> datareader -> datatable -> objekt.
- M
Typat dataset ja det stämmer.
Hmmm, jag menade i detta fallet utan en ORMapper, utan syftade mer på skriven mappning eller genererad kod vilket jag tror går snabbare, har för mig jag sett mätningar också som visar detta.
Dock har det inte med diskussionen som vi kommit utanför nu :|.. Men jag skulle iallfall säga att användandet av en DataReader behöver inte alls betyda att databaskopplingen stängs senare. Sedan har det upp till utvecklaren hur skickling han är på att hantera detta.
Om man lyssnar på object created event så om man är skicklig så triggar man inte detta under inläsningen.
Jag säger inte att man skall välja en DataReader före DataTables/DataSets för att den är snabbare. För även om den är snabbare så märks det knappt av slutanvändaren ändå, utan att man skall inte välja bort den för att man tror att den är långsammare för det är den absolut inte när den används korrekt.
För även om den är snabbare så märks det knappt av slutanvändaren ändå, utan att man skall inte välja bort den för att man tror att den är långsammare för det är den absolut inte när den används korrekt.
DataReader kan aldrig vara långsammare än en datatable, eftersom det är precis som du sagt tidigare att datatablen använder sig av datareadern för att fylla sig med data. Problemet med datareadern är ju att den måste hålla en koppling öppen till databasen så länge som man hämtar data från den, vilket gör att det inte är ett så bra val om man inte har riktigt kontroll över när och hur den används.
nickemannen skrev:
Hmmm, jag menade i detta fallet utan en ORMapper, utan syftade mer på skriven mappning eller genererad kod vilket jag tror går snabbare, har för mig jag sett mätningar också som visar detta.
Om du menar att man skriver specifik kod för varje object så kommer det givetviss öka upp hastigheten för att skapa objekten. Men fy vilket slavjobb.... nej då är ORMappern att rekomender alla dagar i veckan, eller möjligtviss någon generator som genererar kod utifrån databas och dina objekt.
Jag har iofs inte varit särskilt noga med att bygga upp strukturen på det viset som ni menar. Jag har två olika funktioner för att returnera data som ser i princip lika ut fast den ena returnerar ett datatable och den andra returnerar en datareader har inte tagit någon hänsyn till något annat än min lathet.
Om jag vill koda med OOP i tankarna hur ska jag då bygga upp dataåtkomsten? Var kan jag lära mig mer om C#? Boken jag har är bra men det är exempel som jag inte riktigt kan applicera på det projekt jag tänkt ta mig an nu.
Jag har iofs inte varit särskilt noga med att bygga upp strukturen på det viset som ni menar. Jag har två olika funktioner för att returnera data som ser i princip lika ut fast den ena returnerar ett datatable och den andra returnerar en datareader har inte tagit någon hänsyn till något annat än min lathet.
Om jag vill koda med OOP i tankarna hur ska jag då bygga upp dataåtkomsten? Var kan jag lära mig mer om C#? Boken jag har är bra men det är exempel som jag inte riktigt kan applicera på det projekt jag tänkt ta mig an nu.
Jag tycker du skall ta dig en titt på NHibernate eller NPersist.
290 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e