Avatar billede Lasse Novice
30. december 2004 - 18:47 Der er 8 kommentarer og
1 løsning

SqlDataReaders late bound parameter

Jeg oensker at spoerge om en hvis kolonne er i datareaderen, kan det lade sig goere?

Lidt a la:

if(dtr.Contains("KolonneNavn")) var = dtr["KolonneNavn"];

Jeg kan se at man kan faa alle kolonne navnene ud, men det er vist lige lovligt voldsomt at skulle hente alle kolonne navnene ud bare for at checke for dette.
Avatar billede arne_v Ekspert
30. december 2004 - 18:50 #1
En måde er at kalde GetOrdinal og catche IndexOutOfRangeException, hvis den ikke
er der.
Avatar billede a1a1 Novice
30. december 2004 - 19:13 #2
jeg kan ikke lige forstå hvorfor du ikke ved om dit felt er der?
Avatar billede a1a1 Novice
30. december 2004 - 19:15 #3
eller kan du gøre noget som arne siger

try
var = drt["kolone"];
catch

end try (?) eller hvad det nu er i C# :)
Avatar billede driis Nybegynder
30. december 2004 - 20:32 #4
Det er også muligt at hente tabellens skema ud i en tabel og på den kontrollere om det givne kolonnenavn eksisterer:
public static bool DoesReaderContainColumn(IDataReader reader,string columnName)
{
    DataTable dt = reader.GetSchemaTable();
    DataRow [] rows = dt.Select("ColumnName='" + columnName + "'");
    return rows.Length != 0;       
}
Avatar billede driis Nybegynder
30. december 2004 - 20:46 #5
Jeg synes ikke det er kønt at bruge en try ... catch til formålet, men det virker fint. Jeg har lavet en hurtig test, og jeg kan ikke måle nogen forskel i hastighed på de forskellige metoder. Dog fandt jeg ud af, at hvis kolonnen ikke eksisterer er try ... catch metoden langsomst idet exception handlingen er tidskrævende. Hvis kolonnen eksisterer kan jeg ikke måle nogen forskel.
Avatar billede Lasse Novice
30. december 2004 - 21:03 #6
a1>> Grunden til dette er rent kosmetisk. Derfor syntes jeg ikke at try - catch er en koenloesning.
driss>> dit forslag er godt... jeg har kigget lidt paa dette:
dr.GetSchemaTable().Columns.Contains("KolonneNavn");
Avatar billede Lasse Novice
30. december 2004 - 21:13 #7
ok, det virkede saa ikke... (mit forslag), men det goer driss'. Jeg kigger lige lidt paa hastighed og vender tilbage
Avatar billede driis Nybegynder
30. december 2004 - 22:03 #8
gooky >> Jeg har testet med flg. simple eksempel. Som du sikkert kan se er forskellen performancemæssigt så lille at jeg ikke mener det bør have indflydelse på dit valg af metode - med mindre du skal bruge metoden ekstremt ofte.

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

namespace ReaderTest
{
    /// <summary>
    /// Summary description for Class1.
    /// </summary>
    class Class1
    {
        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        private static extern bool QueryPerformanceCounter(ref long lpPerformanceCount);
        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        private static extern bool QueryPerformanceFrequency(ref long lpFrequency);

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            long frequency = 0, startTime = 0, endTime = 0;
            float elapsed = 0;
            QueryPerformanceFrequency(ref frequency);
           
            SqlConnection conn = new SqlConnection(CONNECTIONSTRING);
            conn.Open();
            SqlCommand com = new SqlCommand("SELECT * FROM tblProducts",conn);
            SqlDataReader sdr = com.ExecuteReader(CommandBehavior.CloseConnection);
           
            string c = Console.ReadLine();
            DateTime dt = DateTime.Now;
            bool columnExists;
            while ( c != "q" )
            {
                QueryPerformanceCounter(ref startTime);
                columnExists = DoesReaderContainColumn1(sdr,c);
                QueryPerformanceCounter(ref endTime);
                elapsed = (float)(endTime - startTime) / frequency;
                Console.WriteLine(columnExists.ToString() + " {0:0000.00000}ms ", elapsed);
               
                QueryPerformanceCounter(ref startTime);
                columnExists = DoesReaderContainColumn2(sdr,c);
                QueryPerformanceCounter(ref endTime);
                elapsed = (float)(endTime - startTime) / frequency;
                Console.WriteLine(columnExists.ToString() + " {0:0000.00000}ms ", elapsed);

                QueryPerformanceCounter(ref startTime);
                columnExists = DoesReaderContainColumn3(sdr,c);
                QueryPerformanceCounter(ref endTime);
                elapsed = (float)(endTime - startTime) / frequency;
                Console.WriteLine(columnExists.ToString() + " {0:0000.00000}ms ", elapsed);
               
                c = Console.ReadLine();
            }
            sdr.Close();
        }

        public static bool DoesReaderContainColumn1(IDataReader reader,string columnName)
        {
            DataTable dt = reader.GetSchemaTable();
            DataRow [] rows = dt.Select("ColumnName='" + columnName + "'");
            return rows.Length != 0;       
        }

        public static bool DoesReaderContainColumn2(IDataReader reader, string columnName)
        {
            try
            {
                reader.GetOrdinal(columnName);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public static bool DoesReaderContainColumn3(IDataReader reader, string columnName)
        {
            for ( int i = 0 ; i < reader.FieldCount ; i++ )
            {
                if ( reader.GetName(i) == columnName )
                    return true;
            }
            return false;
        }

        private const string CONNECTIONSTRING = "din connectionstring";
    }
}
Avatar billede driis Nybegynder
30. december 2004 - 22:06 #9
I øvrigt er grunden til:
dr.GetSchemaTable().Columns.Contains("KolonneNavn");

ikke virker, at GetSchemaTable returnerer en tabel der definerer dataskemaet. Denne tabel indeholder så en række for hver kolonne i din data reader. Disse rækker indeholder information om hver enkelt kolonne i datareaderen.
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