Halloj, jag har lite problem nu när jag vill hämta data från två tabeller och visa i en repeater...
Det är ett forum och jag vill hämta data från tabellen "anvandare", i det här fallet bara användarens bild beroende på anvID:t som finns i forum-tabellen.
Koden jag har för att hämta datan från tabellen forum ligger i forum.vb:
Function forumLista()
dim cn as new OdbcConnection("DRIVER={MySQL ODBC 3.51 Driver};SERVER=server;PORT=port;DATABASE=database;UID=uid;PWD=pwd;OPTION=option;")
Dim da As New OdbcDataAdapter("select * from forum order by senasteSvar desc",cn)
dim ds as new DataSet
da.Fill(ds, "forum")
dim objPds as new PagedDataSource()
objPds.DataSource = ds.Tables("forum").DefaultView
objPds.AllowPaging = true
objPds.PageSize = 15
dim currentPage as integer
if not Request.QueryString("s") = 0 then
currentPage=Convert.ToInt32(Request.QueryString("s"))
else
currentPage = 1
end if
objPds.CurrentPageIndex = currentPage-1
lblSida.Text = "Sida: " & currentPage.ToString()
if not objPds.IsFirstPage then
lnkPrev.NavigateUrl= "default.aspx?s="& Convert.ToString(currentPage-1)
end if
if not objPds.IsLastPage then
lnkNext.NavigateUrl= "default.aspx?s="& Convert.ToString(currentPage+1)
end if
return objPds
End Function
Och på sidan default.aspx har jag själva repeatern:
Vad jag har förstått så är kanske inte ItemDataBound det bästa att använda rent prestandamässigt om man ska köra en SQL-fråga för varje post?
ItemDataBound är alltid bäst ur prestanda synpunkt, eftersom du slipper en massa databinder.eval() som inte är så bra u prestanda synpunkt.
Det som inte är så bra är däremot att göra ett nytt SQL anrop för varje post som skall skrivas ut, detta är rent ut sagt korkat, och prestanda dödande. Det du skall göra är att utvidga din första SQL sats så att den även får med information om användaren med ett vanligt INNER JOIN sqlstatement.
Det andra du skall göra är att sluta med användandet av DataSet för sådana här lösningar eftersom DataSet är betydligt mer prestanda krävande än en DataReader.
Det tredje du skall göra är att inte använda dig av PagedSource utan se till så du bara hämtar den datan som du behöver från databasen. Och med tanke på att du använder MySQL som har det trevliga kommandot LIMIT så är den implementationen enkel (MicroSoft när kommer LIMIT till SQL Server?????). Med en SELECT * FORM [Tabel] som du använder så hämtar du ju ALL data som finns i den tabellen, har du då 1 Miljon poster så hämtar du ut alla dem för att kanske visa 10 stycken, det är ju inte så smart.
Gällande PagedSource, så är jag medveten om prestandaförlusten iom min lösning. Men då jag inte har så många poster i den tabellen, och inte kommer ha så många heller så ser jag det inte som ett problem. Än.
Jag har försökt få ihop det med INNER JOIN, men vid DataSet som du skriver om, fastnar jag... Har försökt få datakällan i en DataReader men icke.
Lite hjälp kodmässigt är uppskattat!
SqlConnection sqlConnection = new SqlConnection("DIN_CONNECTIONSTRIN");
SqlCommand sqlCommand = new SqlCommand();
SqlDataReader sqlDataReader = null;
sqlCommand.CommandType = CommandType.Text;
sqlCommand.CommandText = "SELECT.....";
sqlCommand.Connection = sqlConnection;
sqlConnection.Open();
sqlDataReader = sqlCommand.ExecuteReaderCommandBehavior.Close);
//-- Do what you want with your datareader
//-- But dont forgett to do sqlDataReader.Close() when
//-- your done with it, so you release connections to your databas
Skrivet helt ur huvudet så små fel har säkert smugit sig in.
Ok, tack. Men tyvärr löser det inte mitt problem.
Man kan inte, vad jag förstår, använda DataReader med PagedDataSource, det går inte att använda DataBind() och utan det får man ett felmeddelande gällande ICollection el liknande.
Jag läste en annan tråd där problemet var just att använda DataReader ihop med PagedDataSource, detta löstes precis så som min variant är, dvs med DataSet.
Jag vill ju bara kunna visa användarens bild, ska det vara så svårt att lösa... damnit :)
Man kan inte, vad jag förstår, använda DataReader med PagedDataSource
Hmm visste jag inte, men vid närmare eftertanke så är det en logisk slutledning eftersom en DataReader är en read-forward only cursor. Medans din PagedDataSource säkert kräver möjlighet att hoppa tillbaka bland posterna också.
alternativiet till datareader är så fall en DataTable som är lite lättare än ett DataSet, men det du verkar ha problem med är din SQL sats där du inte kan få till din INNER JOIN statement. Hör efter i SQL forumet för hjälp med din SQL sats.
Löste det...
Dock utan att använda DataTable, men om det för övrigt inte är en bra lösning så hojta gärna:
Function forumLista()
dim cn as new OdbcConnection(blabla)
Dim da As New OdbcDataAdapter("SELECT forum.*, anvandare.bild, count(*) as antalsvar FROM forum INNER JOIN forum_svar ON forum.FID=forum_svar.SID INNER JOIN anvandare ON forum.anvID=anvandare.ID GROUP BY forum.FID ORDER BY forum.senasteSvar desc",cn)
dim ds as new DataSet
da.Fill(ds, "forumet")
dim objPds as new PagedDataSource()
objPds.DataSource = ds.Tables("forumet").DefaultView
objPds.AllowPaging = true
objPds.PageSize = 15
dim currentPage as integer
if not Request.QueryString("s") = 0 then
currentPage=Convert.ToInt32(Request.QueryString("s"))
else
currentPage = 1
end if
objPds.CurrentPageIndex = currentPage-1
lblSida.Text = "Sida: " & currentPage.ToString()
if not objPds.IsFirstPage then
lnkPrev.NavigateUrl= "?visa=forum&s="& Convert.ToString(currentPage-1)
end if
if not objPds.IsLastPage then
lnkNext.NavigateUrl= "?visa=forum&s="& Convert.ToString(currentPage+1)
end if
return objPds
End Function
Det tredje du skall göra är att inte använda dig av PagedSource utan se till så du bara hämtar den datan som du behöver från databasen. Och med tanke på att du använder MySQL som har det trevliga kommandot LIMIT så är den implementationen enkel (MicroSoft när kommer LIMIT till SQL Server?????). Med en SELECT * FORM [Tabel] som du använder så hämtar du ju ALL data som finns i den tabellen, har du då 1 Miljon poster så hämtar du ut alla dem för att kanske visa 10 stycken, det är ju inte så smart.
Nu har jag stött på en liknande variant men där posterna är närmare 400 istället för c:a 40. Om jag nu vill använda LIMIT, hur ska jag då gå tillväga? Ska jag helt enkelt ha olika SQL-frågor beroende på vilket sidnummer det är? Förstod dig inte riktigt där Gladh...
400 eller 40 poster spelar inte så stor roll, det börjar nog märkas mer när det rör sig om tusentals poster.
Hur just LIMIT fungerar vet jag inte så bra eftersom jag inte arbetar mot MySQL, men OM det fungerar så här:
SELECT * FROM [Tabel] LIMIT 1, 10
Så säger den att ta första posten (1) och hämta 10 poster (10). Det betyder att du när du vill visa post 11-20 skall skriva
SELECT * FROM [Tabel] LIMIT 11, 10
och post 21-30
SELECT * FROM [Tabel] LIMIT 21, 10
Det betyder att du för varje sida som du vill visa måste ändra just startnummret, och det kommer att ge dig olika SQLsatser varje gång, men startsiffran kan du ju räkna ut så SQL satsen blir.
Ok, tack för svaret... Men om jag väljer endast de poster jag vill visa/sida så fungerar ju inte pagingen. Den räknar ju mellan alla poster, om jag då inte har alla med så finns det ju inga fler att bläddra mellan...
Nope den inbyggda pagingen fungerar inte eftersom den kräver att du hämtar ALL data från databasen.
Om du vill använda dig av Limit så får du själv hantera pagingen, genom att kontrollera hur många poster det finns totalt av din sökning och sedan själv bygga en pagingfunktion som visar nästa sida osv osv...
Helt klart mer jobb för dig, och om det endast rör sig om 400 poster och det inte är allt för mycket data i dem så är det kanske inte lönt att lägga ner den tiden, men om det rör sig om tusentalsposter och det är mycket data i varje post så är det helt klart en prestandavinst att göra det.
Function forumSvar()
dim startPos as Integer
dim currentPage as Integer
dim Page as String
Page = Request.QueryString("sidNr")
IF len(Page) = 0 OR Page = 1 THEN
currentPage = 0
Page = 1
ELSE
currentPage = Page-1
END IF
startPos = currentPage*10
lblForumInlaggSida.Text = "Sida: " & Page
IF NOT (Page = 1 OR len(Page) = 0) THEN
lnkForumInlaggPrev.NavigateUrl="?sida=visaInlagg&FID=" & Request.QueryString("FID") & "&sidNr=" & currentPage
END IF
lnkForumInlaggNext.NavigateUrl="?sida=visaInlagg&FID=" & Request.QueryString("FID") & "&sidNr=" & Page+1
dim cn as new OdbcConnection("DRIVER={MySQL ODBC 3.51 Driver};SERVER=;PORT=;DATABASE=;UID=;PWD=;OPTION=3;")
Dim Cmd as new OdbcCommand("SELECT forum_svar.*, anvandare.bild FROM forum_svar INNER JOIN anvandare ON forum_svar.anvID=anvandare.ID WHERE SID=" & Request.QueryString("FID") & " ORDER BY forum_svar.datum LIMIT " & startPos & ", 10",cn)
cn.Open()
return Cmd.ExecuteReader(CommandBehavior.CloseConnection)
End Function
Men jag vill ju också räkna hur många sidor det är så man inte kan bläddra all världens väg framåt... Frågan är alltså, hur gör jag det? :)
Du kan ju köra en count och returnera det samtidigt som ditt andra svar.
Ett litet tips kan också vara att alltid plocka 1 rad för mycket för varje sida. På så sätt så vet du om det finns fler sidor och därav också om du ska rita ut en "next page" knapp... (exempelvis hämta 11 resultat. Får du 11 resultat så vet du att du ska visa 10 resultat + en "next" knapp.. =)
Ett litet tips kan också vara att alltid plocka 1 rad för mycket för varje sida. På så sätt så vet du om det finns fler sidor och därav också om du ska rita ut en "next page" knapp... (exempelvis hämta 11 resultat. Får du 11 resultat så vet du att du ska visa 10 resultat + en "next" knapp.. =)
Smart, men jag kommer bara inte på hur jag ska göra rent kodmässigt! Vilket som är bäst...
274 ms totalt · 4 externa anrop · v20260731065814-full.1dc6f849