Jag sitter och skriver om min MembershipProvider efter en artikel här på PelleSoft och ska anpassa den till min 3-skikts-lösning med min DAL-class. jag skulle ha returnerat ett custom objekt med värdena istället för readern , för den hör hämma i dal klassen. Hur fångar jag upp ett custom object i mitt affärslager så att jag kan få med mig mina två fält? class MinEnitet Är det dumt att lagra readern i en array och returnera över arrayen istället från mitt DAL-lager? dumt å dumt , det är ju nästan samma sak , fast har du ett custom object Jag fick en förklaring om att kör man en reader med using i en DAL-klass så förstörs readern när den lämnar DAL-klassen... Men eftersom jag är van att jobba med GetRows i klassisk ASP och har min SQL-sträng i BLL-lagret så är det inga problem med att fiska upp array numren... http://msdn2.microsoft.com/en-us/library/aa479317.aspx Tommy, Patrik har helt rätt. Med hjälp av using ser du till att connectionen stängs så fort man lämnar det scopet vilket leder till att din datareader tappar uppkopplingen. Antingen måste du skapa ett objekt och flytta över datat till det, eller så får du behålla connectionen öppen efter du returnerar readern. Då bör du lägga till CommandBehavior.CloseConnection som stänger connectionen när man stänger readern. Bara ett tips om du nu inte vill flytta datat till ett annat objekt. Och när du fixat bort din using och låter din koppling till databasen vara öppen så du kan läsa från din reader i ditt BLL, så kommer nästa problem (Johan Normén här kommer lagbrottet :) ). "Och även om du har en try-catch runt hela ditt kodblock (som du inte visar här) så kommer inte det hjälpa dig eftersom din reader skapas innanför detta block och kan alltså inte accessas i ditt finally-block. " Tack alla för svaren... ExecuteReader...
Jag har skapat mig en DAL-class för att plocka ut en rad ur databasen som ser ut så här... Kod:
public static MySqlDataReader ExecuteReader(MySqlCommand command)
{
using (MySqlConnection conn = GetConnection())
{
command.Connection = conn;
MySqlDataReader result = command.ExecuteReader(CommandBehavior.SingleRow);
return result;
}
}
Sen anropar jag det ifrån min kod så här...Kod:
MySqlCommand cmdGetPassword = new MySqlCommand("SELECT password, user_id FROM `" + tableName + "` WHERE Username = ?Username");
cmdGetPassword.Parameters.Add("?Username", MySqlDbType.VarChar, 25).Value = username;
int userId = 0;
string pwd = "";
MySqlDataReader reader = DAL.ExecuteReader(cmdGetPassword);
if (reader.HasRows)
{
reader.Read();
pwd = reader.GetString(0);
userId = reader.GetInt32(1);
}
reader.Close();
I min DAL-klass när jag kör en WATCh så har HasRows = true och FieldCount = 2 med rätt inloggning och rätt lösenord. Men när jag kommer till if (reader.HasRows) i mitt "affärslager" så har den tappat allt som den inte har fått... känns som om jag använder fel metod för att få över infot ifrån min DAL-class över till min "reader" i MySqlDataReader reader = DAL.ExecuteReader(cmdGetPassword); ...
Sv: ExecuteReader...
jag misstänker att det är din using(...) som kör lite gc magi på din reader när du lämnar metoden.Sv:ExecuteReader...
Sv: ExecuteReader...
{
.. lite properties och sånt...
}
i dal gör du ( lite pseudo snabbskriven kodliknande syntax :)
minEntitet = new MinEntitet();
reader.read();
minEntiet.falt1= reader.get....;
minEntiet.falt2= reader.get....;
return minEntiet; // istället för readern
sen får du ha referens till MinEntiet eller ett interface i ditt affärslager.Sv:ExecuteReader...
Sv: ExecuteReader...
så blir det mer läsbar kod
om man tex har ett id att hämta ut så blir det ju nått sånt här.
minArray[0] vs. mittObjekt.Id
jag förerar det senare då slipper man skriva kommentar om vad position 0 i arrayen är för något.Sv:ExecuteReader...
Som sagt var det är svårt att släppa klassisk ASP... :)
Finns det någon bra tutorial som man kan få ett hum om hur man kan få till ett custom object istället för min array... I början så är det svårt att hitta rätt sökord för att finna saker via google... Sv: ExecuteReader...
kolla in den artikeln Sv: ExecuteReader...
Om du använder using som du gör så anropas Dispose på din connection innan du lämnar metoden. Det är nog det som ställer till det för din reader.Sv:ExecuteReader...
Sv: ExecuteReader...
Och det är följande kod
<code>
MySqlDataReader reader = DAL.ExecuteReader(cmdGetPassword);
if (reader.HasRows)
{...}
{
reader.Read();
pwd = reader.GetString(0);
userId = reader.GetInt32(1);
}
reader.Close();
</code>
Om något fel inträffar i efter du hämtat din reader och innan du kommer till reader.Close() så kommer din databaskoppling inte att stängas, utan fortsätta att ligga öppen... och det är därför som man inte vill lämna över ansvaret att stänga databaskopplingen från DAL:et till kodaren...
Och även om du har en try-catch runt hela ditt kodblock (som du inte visar här) så kommer inte det hjälpa dig eftersom din reader skapas innan för detta block och kan alltså inte accessas i ditt finally-block. Just detta fenomen är allt för vanligt och något som jag sett många gånger i kod, och oftas så upptäcks det först i produktion när man får lite last och längre körningar och kopplingarna till databasen helt plötsligt tar slut....
- MSv:ExecuteReader...
"
Och även om du har en try-catch runt hela ditt kodblock (som du inte visar här) så kommer inte det hjälpa dig eftersom din reader skapas innan för detta block och kan alltså inte accessas i ditt finally-block.
"
Vad är det för problem med att accessa en reader från ett finally-block ?
Du deklarerar den ju bara före try-satsen.
MySqlDataReader reader = null;
try {
reader = ...
...
}
finally {
if(reader != null) {
reader.Close();
}
}
/ TomasSv: ExecuteReader...
Läs om och läs rätt, jag skrev inte att det var något problem, bara att det inte skulle hjälpa om det fanns något try-catch block utanför koden som inte syntes...
- MSv:ExecuteReader...
Jag tror jag nog gjorde det mest enkla att ha readern i min BLL och inte i min DAL-klass... Eftersom koden är helt styrd mot MySQL så kan jag "släppa" lite på att ha alla DB-anrop i DAL-classen, men utnyttja MySqlConnection som finns i DAL-classen när jag hämtar info till readern...