Avatar billede orca Nybegynder
12. juni 2002 - 09:51 Der er 15 kommentarer og
2 løsninger

Problem med visning af data

Hej alle. Jeg har en kode som denne:

            <%
                Dim sql As SqlCommand = New SqlCommand("SELECT * FROM [tblMenu] WHERE [SubID] = 0", Conn)
                Dim rs As SqlDataReader = sql.ExecuteReader()
               
                Do While rs.Read
                    Response.Write("<img src='images/menu/" & rs("Image") & "' width='130' height='35'><br><br>")
                    MakeSubs(rs("MenuID"))
                Loop
            %>

Den viser meget fint det den skal. MakeSubs funktionen skal så vise de underemner der er til menuemnet. I MakeSubs funktionen prøver jeg så at oprette en ny Reader for at kunne få fat i databasen og vise det nødvendige. Men jeg får fejlbeskeden "There is already an open DataReader associated with this Connection which must be closed first.". Hvad betyder det? Skal jeg så oprette endnu en connection, for at lave to readers på samme side, på samme tid?

Mvh Mark
Avatar billede jakobandersen Nybegynder
12. juni 2002 - 11:21 #1
Du lukker aldrig din connection, prøv at sende følgende parameter til ExecuteReader:

CommandBehavior.CloseConnection

Altså sådan her:
sql.ExecuteReader(CommandBehavior.CloseConnection)

Eller evt. blot fyre en Conn.Close() af.
Avatar billede orca Nybegynder
12. juni 2002 - 21:06 #2
Det hjælper jo ikke? Jeg kan naturligvis ikke lukke min connection før al kode er udført, og jeg skal vel ikke gentagne gange lukke og åbne connection? Der må da være en måde at have flere datareaders i gang på samme tid?
Avatar billede sunedh Nybegynder
12. juni 2002 - 21:49 #3
Du kan få flere datareaders igang ved at lave flere connections - en connection kan kun have med en datareader at gøre.

Når det er sagt så jo, man bør faktisk kalder close på connection objekter hver gang man er færdig med det og så åbne det igen når det skal bruges igen. Connection bliver ikke rigtigt lukket, men returneres til connection pool (hvorved en anden kan bruge den) og der er derfor ikke performance tab.

- sunedh
Avatar billede orca Nybegynder
12. juni 2002 - 22:22 #4
Det lyder jo fornuftigt nok, men jeg er egentligt stødt ind i endnu et problem mht denne funktion, det er nok lettest hvis lige jeg poster min kode:


<%@Import Namespace="System.Data"%>

<!--#Include File="../../includes/conn.aspx"-->

<script language="VB" runat="server">

    Sub MakeSubs(SubID As Integer)
        Dim sqlSub As SqlCommand = New SqlCommand("SELECT * FROM [tblMenu] WHERE [SubID] = " & SubID, Conn)
        Dim rsSub As SqlDataReader = sqlSub.ExecuteReader()
       
        Do While rsSub.Read
            Response.Write("<b>" & rsSub("Title") & "</b>")
        Loop
    End Sub

</script>


<table border="0" cellpadding="0" cellspacing="0" height="490">
    <tr>
        <td style="border-bottom: 2px solid #000000" valign="top">
            <br>
           
            <%
                Dim sql As SqlCommand = New SqlCommand("SELECT * FROM [tblMenu] WHERE [SubID] = 0", Conn)
                Dim rs As SqlDataReader = sql.ExecuteReader()
               
                Do While rs.Read
                    Response.Write("<img src='images/menu/" & rs("Image") & "' width='130' height='35'><br><br>")
                    MakeSubs(rs("MenuID"))
                Loop
            %>
           
        </td>
    </tr>
</table>

<!--#Include File="../../includes/connend.aspx"-->



Hvis bare jeg kører denne kode, beklager MakeSubs funktionen sig over at Conn ikke er blevet erklæret, mit andet loop kører fint. Så har jeg prøvet at medsende Conn som et objekt, og så er det den siger at jeg kun kan have een datareader, skal jeg så lukke og åbne conn her, eller hvorledes gøres det?

Jeg skal nok give lidt flere point hvis du/i gider hjælpe en n00b lidt på vej :)

Mvh Mark
Avatar billede jakobandersen Nybegynder
13. juni 2002 - 06:26 #5
Sådan her:

<%@Import Namespace="System.Data"%>

<!--#Include File="../../includes/conn.aspx"-->

<script language="VB" runat="server">

    Sub MakeSubs(SubID As Integer)
        Dim sqlSub As SqlCommand = New SqlCommand("SELECT * FROM [tblMenu] WHERE [SubID] = " & SubID, Conn)
        Dim rsSub As SqlDataReader = sqlSub.ExecuteReader(CommandBehavior.CloseConnection)
       
        Do While rsSub.Read
            Response.Write("<b>" & rsSub("Title") & "</b>")
        Loop
    End Sub

</script>


<table border="0" cellpadding="0" cellspacing="0" height="490">
    <tr>
        <td style="border-bottom: 2px solid #000000" valign="top">
            <br>
           
            <%
                Dim sql As SqlCommand = New SqlCommand("SELECT * FROM [tblMenu] WHERE [SubID] = 0", Conn)
                Dim rs As SqlDataReader = sql.ExecuteReader(CommandBehavior.CloseConnection)
               
                Do While rs.Read
                    Response.Write("<img src='images/menu/" & rs("Image") & "' width='130' height='35'><br><br>")
                    MakeSubs(rs("MenuID"))
                Loop
            %>
           
        </td>
    </tr>
</table>

<!--#Include File="../../includes/connend.aspx"-->
Avatar billede orca Nybegynder
13. juni 2002 - 19:13 #6
Så får jeg fejlen at Conn ikke erklæret... Det skyldes vel at Sub funktionerne kun kan bruge variabler som er dimensioneret/erklæret inden i selve funktionen? Hvordan løses det? :)
Avatar billede orca Nybegynder
13. juni 2002 - 19:13 #7
Har lige forhøjet til 60points.
Avatar billede jakobandersen Nybegynder
13. juni 2002 - 19:19 #8
Hvad har du i connend og conn.aspx?
Avatar billede jakobandersen Nybegynder
13. juni 2002 - 19:21 #9
ASP.NET kører som sunedh også sagde med en ret effektiv connection pooling derfor skal du køre efter hovedreglen om hurtigst muligt at lukke og åbne connection og ikke gøre som jeg tror du gør nu, åbne og lukke i henholdsvis toppen og bunden af filen.
Avatar billede orca Nybegynder
13. juni 2002 - 19:40 #10
:$, jo, jeg åbner og lukker i top og bund :)

conn.asp:
<%@ Import Namespace="System.Data.SqlClient" %>

<%
    Dim Conn As New SqlConnection("Server=212.242.193.110;UID=test;Password=test;Database=Improve;Trusted_Connection=yes")
    Conn.Open()
%>


connend.asp:
Conn.Close
Conn = Nothing



Jeg håber på nogle tips :) - er stadig ret ASP[Classic] vant.
Avatar billede jakobandersen Nybegynder
13. juni 2002 - 20:17 #11
Lad være med at åbne din connection i det første åben den istedet for lige før du skal bruge den. Og luk den igen med CommandBehavior.CloseConnection, så får du den mest optimale hastighed.
Avatar billede orca Nybegynder
13. juni 2002 - 20:46 #12
Tak for tippet, men det løser jo ikke mit problem... Mit problem er jo at jeg ikke kan vise de relationelle data. Her er et eksempel på hvad jeg vil vise:

Menutopic
  menuemne #1
  menuemne #2

Menutop #2
  menuemne #1

Hvordan klarer jeg det?

Mvh Mark
Avatar billede sunedh Nybegynder
13. juni 2002 - 23:31 #13
Nu er det jo somme tider lidt en religion hvordan man koder, så dette er ikke en opfording til en krig, men her er hvad jeg ville gøre:

1. opdel præsentation og logik i henholdsvis en aspx og en vb fil
2. undlad at bruge include filer - lav klasser i stedet, det er meget mere fleksiblet
3. til præsentation af data ville jeg anvende en repeater kontrol men en anden repeater kontrol indeni. Disse kan databindes direkte med din datareader. På den måde undgår du Response.Write, som man efter min mening aldrig bør bruge mere. Alternativt kunne man skrive de to forskellige SQL statement sammen til et og så kun anvende en repeater (og for den sags skyld datareader)

Så mit forslag kort: kig lidt på repeateren (evt. også datalist og datagrid) og adskil præsentation og logik.

- sunedh
Avatar billede orca Nybegynder
14. juni 2002 - 00:20 #14
Hej Sune. Jeg har fulgt dit råd og læst lidt på det... Men pinligt som det er, er jeg allerede stødt ind i problemer igen. Jeg har oprettet følgende kode:

<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>

<script language="VB" runat="server">

    Sub Page_Load()
        Dim Conn As New SqlConnection("Server=212.242.193.110;UID=test;Password=test;Database=Improve;Trusted_Connection=yes")
        Conn.Open()
       
        Dim sqlCmd As SqlCommand = new SqlCommand("SELECT * FROM [tblMenu] WHERE [SubID] = 0", Conn)
       
        TopicsRepeater.DataSource = sqlCmd.ExecuteReader(CommandBehavior.CloseConnection)
        TopicsRepeater.DataBind


       
        Conn.Close
        Conn = Nothing
    End Sub

</script>


Samt denne som udskriver:

                <asp:Repeater id=TopicsRepeater runat="server">
       
                    <ItemTemplate>
       
                          <%# DataBinder.Eval(Container.DataItem, "Title") & "<br>" %>
       
                    </ItemTemplate>
       
                </asp:Repeater>


Koden udskriver som den skal, topemnerne. Men hvordan laver jeg en Repeater#2 som skal være inde i den anden repeater?

... Øger lige points til 90 (i får begge :))
Avatar billede jakobandersen Nybegynder
14. juni 2002 - 00:31 #15
Noget ala dette:

<asp:Repeater id=TopicsRepeater runat="server">
  <ItemTemplate>
    <%# DataBinder.Eval(Container.DataItem, "Title") & "<br>" %>
    <asp:Repeater id="Undermenu" runat="server" DataSource='<%# GetSubs( DataBinder.Eval( Container.DataItem, "MenuID" )) %>' >
      <ItemTemplate>
        <%# DataBinder.Eval(Container.DataItem, "Title") & "<br>" %>
      </ItemTemplate>
    </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

Og så laver du en funktion der tager et menuid som parameter og returnerer en datareader med alle undermenuer til denne

Alternativt kan du relatere dine tables sådan her:
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q306154
Avatar billede orca Nybegynder
14. juni 2002 - 00:59 #16
Jamen det er jo smukt! Endelig fik jeg det til at virke :). Jeg siger mange tusind tak, og håber at i er tilfredse med 50/50 uddeling af points.

Endnu engang tak.

Mvh Mark
Avatar billede sunedh Nybegynder
14. juni 2002 - 08:59 #17
:o) - det er jo bare fedt at det er kommet til at virke

sunedh
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester