Avatar billede mach3 Nybegynder
04. januar 2005 - 20:10 Der er 18 kommentarer og
2 løsninger

Try catch

Hej,

Jeg har noget ASP.NET kode og jeg har lavet en Database facade som indeholder alt koden vedrørende database kald.

Jeg har valgt at gøre det på denne måde, da det så vil blive nemmere at skifte databasen ud - så skal man kun ændre i facadeklassen. Det kører pt med access, men skal over på MS Sql om ikke så lang tid.

Men mit spørgsmål:

Bør jeg skrive try-catch blokke i facade klassen, eller skal jeg gøre det der hvor facade klassens metoder rent faktisk bliver kaldt?

Mvh
Avatar billede arne_v Ekspert
04. januar 2005 - 20:14 #1
Du bør catche der hvor du kan gøre noget fornuftigt ved fejlene.

Jeg tror at der er stor sandsynelighed for at det betyder der hvor
du kalder facade klassens metoder.

Der bør du vide lidt om hvad du er igang med.

Hvorimod nede i facade klassen ved du ikke nødvendigvis ret meget
om hvad du er igang med.


Men der er ikke nogen forgyldt løsning på exception handling.

Bortset fra at den skal være konsistent og dokumenteret.
Avatar billede mach3 Nybegynder
04. januar 2005 - 20:35 #2
Den skal jeg lige tygge lidt på :o

Vender tilbage senere
Avatar billede burningice Nybegynder
05. januar 2005 - 07:19 #3
en mulighed var evt. at fange dine fejl i facade-klassen og kaste en ny generisk exception med indholdet af den originale. Dette har jeg selv gjort med success, da jeg ellers skal vide hvilken slags database jeg har med at gøre når jeg kalder metoderne i facade-klassen. Og hvorfor det? Jo, fordi at der findes SqlConnectionException, OleDbConnectionException, MySqlConnectionException osv. osv.
Avatar billede mach3 Nybegynder
05. januar 2005 - 12:19 #4
Ja, det giver mening cyberfessor.

Men jeg har et problem - her er udpluk fra en af funktionerne i facade klassen:
OleDbDataAdapter adapter = new OleDbDataAdapter(objCmd);

DataSet ds = new DataSet();
adapter.Fill(ds, "dt");
try
{   
  strTest = ds.Tables["dt"].Rows[0]["test"].ToString();
  return strTest;
}
catch(Exception e)
{
blabla
}

Funktionen returnerer, som det fremgår, en string. Men hvis jeg compiler ovenstående kode siger den: "Not all paths have a return value" (eller noget i den stil).

Det hvor det kan gå galt er der hvor strTemp tilskrives - hvis ds.Tables ikke indeholder noget får man en fejl under runtime med den gule skærm der melder fejl - dvs applikationen går ned (det ønsker jeg ikke). Så det er dette jeg forsøger at fange. Jeg kunne bare skrive return "etellerandet" udenfor try-catch blokken, men jeg ønsker, at det skal fanges hvis strTemp ikke får nogen værdi.

Som i kan høre er jeg ikke helt inde i koncepterne for exception handling. Hvordan kan man løse ovenstående problem?

Mvh
Avatar billede mach3 Nybegynder
05. januar 2005 - 12:21 #5
Det her er fejlen, der kommer under runtime:
"Exception Details: System.IndexOutOfRangeException: There is no row at position 0."
Avatar billede arne_v Ekspert
05. januar 2005 - 12:51 #6
Du har vel kun 2 muligheder:

1) catch den exception der hvor du kalder denne kode.

2) returner et eller andet som markerer at der ikke er data f.eks. null
Avatar billede mach3 Nybegynder
05. januar 2005 - 13:08 #7
Ok, har lige prøvet med følgende:
try
{
strTest = ds.Tables["dt"].Rows[0]["test"].ToString();
return strTest;
}
catch(Exception e)
{
               
}

return null;

Der kommer stadig den der
"Exception Details: System.IndexOutOfRangeException: There is no row at position 0."

hvis der ikke er noget data. Må lige google lidt :0)
Avatar billede burningice Nybegynder
05. januar 2005 - 16:43 #8
hvad så med at teste for null istedet? det er også hurtigere end at gøre sig afhængig af en try-catch
Avatar billede arne_v Ekspert
05. januar 2005 - 21:58 #9
try
{
strTest = ds.Tables["dt"].Rows[0]["test"].ToString();
return strTest;
}
catch(Exception e)
{
return null;             
}

og et test på null udenfor f.eks.
Avatar billede mach3 Nybegynder
09. januar 2005 - 21:59 #10
jeg har besluttet mig for at catche der hvor jeg kalder metoderne fra klient klasserne. dvs der er INGEN exception handling i facade klassen til databasen.

hvad nu hvis databasen fx ikke eksisterer? den fanger jeg også fra klientklasserne som det er nu - håber ikke det er helt forkert :-)
Avatar billede burningice Nybegynder
09. januar 2005 - 22:11 #11
på ingen måde forkert... bare pas på du ikke ender med at catche f.eks. SqlConnectionException dine klientklasser, da hele ideen med facadeklassen så ryger sig en tur
Avatar billede mach3 Nybegynder
09. januar 2005 - 22:49 #12
ok så skal jeg bare lade være med at fange database specifikke exceptions?

det giver god mening det du siger, for jeg kører pt med access men skal over på ms sql og ideen er jo at man kan nøjes med at udskifte facade klassen...
Avatar billede burningice Nybegynder
10. januar 2005 - 03:28 #13
i så fald skal du finde en mindste fællesnævner. Efter at have kigget i dokumentationen ser det ud til at det ikke helt er tilfældet.

OleDbException arver fra ExternalException, da der nok bliver lavet en del COM-kald tilbage til det gamle ADO, mens at SqlClient er skrevet i fuld managed code, og derfor arver direkte fra SystemException.

Så, enten skal du fange SystemException i dine klientklasser, hvilket ikke er særlig optimalt da ideen med try-catch jo netop er at man kan gøre noget forskelligt, alt efter hvilken exception der bliver kastet, eller du kan bruge det her trick:

en ny exception:

using System;

namespace MPAConsult.ToolBox.Data
{
    /// <summary>
    /// Summary description for DataStoreException.
    /// </summary>
    public class DataStoreException : System.SystemException
    {
        public DataStoreException(string message, Exception exc) : base(message, exc)
        {
        }

        public DataStoreException(string message) : base(message)
        {
        }

        public DataStoreException() : base()
        {
        }
    }
}

kast af den i facadeklassen:

public void Open()
        {
            if (conn.State == ConnectionState.Closed)
            {
                try
                {
                    conn.Open();
                }
                catch (OleDbException exc)
                {
                    throw new DataStoreException(exc.Message, exc);
                }
            }
        }

og en anden:

        public void Open()
        {
            if (conn.State == ConnectionState.Closed)
            {
                try
                {
                    conn.Open();
                }
                catch (MySqlException exc)
                {
                    throw new DataStoreException(exc.Message, exc);
                }
            }
        }

og en tredie:

        public void Open()
        {
            if (conn.State == ConnectionState.Closed)
            {
                try
                {
                    conn.Open();
                }
                catch (SqlException exc)
                {
                    throw new DataStoreException(exc.Message, exc);
                }
            }
        }



på den måde kan du teste for DataStoreException i din klientclass, og være sikker på at fange evt. db-fejl, ligemeget hvilket facadeklasse du bruger.
Avatar billede burningice Nybegynder
10. januar 2005 - 03:30 #14
bemærk, at de tre Open()-metoder er fra tre forskellige facadeklasser :)
Avatar billede mach3 Nybegynder
13. oktober 2008 - 20:55 #15
Kom med svar :-) Tak for hjælpen.
Avatar billede arne_v Ekspert
13. oktober 2008 - 21:03 #16
hvem ?
Avatar billede mach3 Nybegynder
19. oktober 2008 - 12:48 #17
arne_v: dig og burningice.
Avatar billede arne_v Ekspert
19. oktober 2008 - 16:39 #18
OK

(lang tid siden vi har set burningice her)
Avatar billede burningice Nybegynder
16. december 2008 - 18:17 #19
det har du ret i arne... får dog stadigvæk emailnotifikationer, og selvom min pingtid kan være lidt lang (der er jo langt til Grønland), så kommer jeg da forbi i ny og næ :)
Avatar billede mach3 Nybegynder
20. december 2008 - 18:23 #20
Takker.
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