Avatar billede dsj Nybegynder
09. november 2004 - 13:01 Der er 10 kommentarer og
1 løsning

Forbindelse lukkes ikke til MS SQL

Jeg har lavet en lille, simpel SqlHandler-klasse, hvorigennem jeg kører alle SQL-kommandoer. Mit problem er, at forbindelserne ikke lukkes efter brug, og til sidst løber MS SQL tør for poolede forbindelser. Nogen der kan se/ved hvad der går galt?? Min klasse ser ud som følger:

using System;
using System.Data;
using System.Data.SqlClient;

namespace Shockwaved.Data {
    public class SqlHandler {
        private static string _conStr;


        public static void Init(string conStr) {
            _conStr = conStr;
        }

        private static SqlConnection GetConnection() {
            return new SqlConnection(_conStr);
        }

        public static IDataReader ExecuteReader(SqlCommand cmd) {
            SqlConnection con = GetConnection();
            con.Open();
            cmd.Connection = con;
            return cmd.ExecuteReader(CommandBehavior.CloseConnection);
        }

        public static DataSet ExecuteDataSet(SqlCommand cmd) {
            SqlConnection con = null;
            try {
                con = GetConnection();
                con.Open();
                cmd.Connection = con;
                SqlDataAdapter da = new SqlDataAdapter(cmd);
                DataSet ds = new DataSet();
                da.Fill(ds);
                return ds;
            } finally {
                if (con != null)
                    con.Close();
            }
        }

        public static int ExecuteNonQuery(SqlCommand cmd) {
            SqlConnection con = null;
            try {
                con = GetConnection();
                con.Open();
                cmd.Connection = con;
                return cmd.ExecuteNonQuery();
            } finally {
                if (con != null)
                    con.Close();
            }
        }
    }
}

Jeg sørger for at lukke alle forbindelser explicit, og metoden ExecuteDataReader anvendes kun, hvor IDataReader'en sættes som source til et GUI-element, og dermed altid itereres helt igennem og automatisk skulle blive lukket af .NET.
Avatar billede arne_v Ekspert
09. november 2004 - 13:09 #1
Det må jo være ExecuteReader der giver problemet.

PS: Hvorfor sende en SqlCommand og ikke en String over ?
Avatar billede casualty Nybegynder
09. november 2004 - 13:09 #2
Jeg vil gætte på at du aldrig kommer in i din "finally" når du kalder return i dit try statement....

det er en gammel sandhed at Finally altid bliver kørt... men jeg tror ikke at den bliver det nhvis du når at kalde return...

Mvh Casualty
Avatar billede casualty Nybegynder
09. november 2004 - 13:11 #3
Prøv dette:

public static int ExecuteNonQuery(SqlCommand cmd) {
            SqlConnection con = null;
            try {
                con = GetConnection();
                con.Open();
                cmd.Connection = con;
                int i = cmd.ExecuteNonQuery();
                con.Close();
                return i;
            } finally {
                if (con != null)
                    con.Close();
            }
        }
Avatar billede dsj Nybegynder
09. november 2004 - 13:14 #4
arne_v >> Hvorfor sende en SqlCommand og ikke en String over ?
Er der nogen fordel i det, og er det muligt at konvertere SqlCommand til en string?

Hvordan kan det være ExecuteReader der er problemet, når den altid - hvis den itereres helt igennem - lukkes automatisk af .NET?

casualty >> Så vidt jeg ved bliver finally _altid_ afviklet, uanset retur-metoden - er det ikke korrekt?
Avatar billede guidmaster Nybegynder
09. november 2004 - 13:20 #5
Den metode der gør brug at din datareader SKAL lukke den.
Avatar billede arne_v Ekspert
09. november 2004 - 13:21 #6
Ja du kan godt hente SQL strengen ud af en Command, men hvis du har en
command så skal du naturligvis bare sende den over. Jeg synes måske bare
at det var pænere også at holde Command's nede i denne her klasse
og nøjes med SQL strenge og DataReader/DataSet udenfor. Ikke noget
funktionelt. Kun smag og behag.

Jeg mener også at finally udføres selvom der er en return.
Avatar billede casualty Nybegynder
09. november 2004 - 13:21 #7
Jeg har lige lavet en test:
*********************
using System;

namespace ConsoleApplication1
{
  class Class1{
    private static void MinTest(){
      try{
        Console.WriteLine("Try");
        return;
      }
      finally{
        Console.WriteLine("Finally");
      }
    }
       
    [STAThread]
    static void Main(string[] args){
      MinTest();
      Console.ReadLine();
    }
  }
}
************************
Finally bliver afviklet... men det var også kun et gæt fra min side...

Mvh Casualty
Avatar billede dsj Nybegynder
09. november 2004 - 13:22 #8
Grunden er, at jeg ikke vil opbygge SQL'en som streng, men som en SqlCommand, hvor det er muligt at tilføje attributter - jeg synes koden bliver pænere...
Avatar billede Slettet bruger
09. november 2004 - 13:47 #9
Du skal explicit kalde close på din reader - det er mig bekendt - ikke nok at itererer til enden af reader. CommandBehavior.CloseConnection sørger blot for at lukke connection når close kaldes på reader.
Avatar billede dsj Nybegynder
09. november 2004 - 15:04 #10
Kryptos, du må gerne komme med et svar.

Nu kan jeg ikke lige finde et eksempel, men i flere artikler jeg tidligere har læst antydes det, at DataReader'en automatisk lukke sig selv (og dermed db-forbindelsen, hvis CommandBehavior.CloseConnection er sat), når alle elementer er itereret igennem, men det kan jeg så forstå er en generelt misforståelse.
Avatar billede Slettet bruger
09. november 2004 - 17:24 #11
svar
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