Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

SQL Server 2005 και IDENT_CURRENT

Îåêßíçóå áðü ôï ìÝëïò kkara. Τελευταία δημοσίευση από το μέλος Παναγιώτης Καναβός στις 09-03-2006, 21:19. Υπάρχουν 5 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  08-03-2006, 11:17 10457

    SQL Server 2005 και IDENT_CURRENT

    Εδώ και κάποιους μήνες αναπτύσσω μια εφαρμογή σε ASP.NET (1.1) και SQL Server 2000. Όλα καλά και ωραία, όμως λόγω κάποιων διαδικαστικών θεμάτων αναγκάζομαι να κάνω switch σε SQL Server 2005. Σύμφωνα με ότι διάβασα, δεν θα έπρεπε να έχω κανένα πρόβλημα, απλά να μεταφέρω τη βάση και τσουυυπ... να παίξει. Όταν λέω μεταφορά βάσης, εννοώ παραγωγή του SQL script που δημιουργεί τη βάση στον SQL Server 2000 και μετά εκτέλεσή του στον SQL Server 2005. Αμ δε... Άρχισαν να χτυπάνε κάποια σφάλματα και άρχισα και εγώ να ψάχνω τι συμβαίνει.

    Να σημειώσω ότι όλη η επικοινωνία προς τη Βάση γίνεται μέσω stored procedures και ADO.NET, χρησιμοποιώντας το namespace System.Data.SqlClient. Μετά από αρκετό ψάξιμο λοιπόν, διαπίστωσα ότι το πρόβλημα υπήρχε σε εκείνες τις sp στις οποίες έκανα insert εγγραφής και επέστρεφα με OUTPUT παράμετρο την τιμή μιας IDENTITY στήλης. Δίνω ένα παράδειγμα μιας sp :

    CREATE PROCEDURE [insertTestTable]
        (@ID     [bigint] OUTPUT,
         @Value1     [nvarchar](100),
         @Value2     [nvarchar](100))
    AS
    INSERT INTO [TestTable] ([Col1], [Col2])
    VALUES (@Value1, @Value2)
    SET @ID = IDENT_CURRENT('TestTable')


    Προφανώς στο παραπάνω, η στήλη ID είναι IDENTITY και γι' αυτό επιστρέφω την τιμή αφού γίνει το insert. Εκτελώντας αυτή την sp με το χέρι (π.χ. Query Analyzer) έπαιρνα κανονικά πίσω την τιμή (και στα δύο DBMS). Εκτελώντας την όμως από κώδικα C# η SqlParameter που είχα ορίσει στο SqlCommand δεν λάμβανε με τίποτα τιμή όταν εκτελούσα την sp σε SQL Server 2005, ενώ σε SQL Server 2000 έπαιζε με τη μία. Εντυπωσιακό;;;

    Το workaround είναι ότι αντικατέστησα όλα τα IDENT_CURRENT με SCOPE_IDENTITY. Σε αυτή την περίπτωση έπαιξε και στα δύο DBMS. Παρότι γνωρίζω ότι είναι καλύτερο ως πρακτική να χρησιμοποιείται το SCOPE_IDENTITY, αυτό δεν με καθησυχάζει καθόλου. Κι αν υπάρχει και κάτι ακόμα που δεν λειτουργεί το ίδιο μεταξύ SQL Server 2000 και 2005; Πως μπορώ να το ξέρω;

    Ομολογώ ότι λόγω πίεσης δεν είχα όσο χρόνο θα ήθελα για να ασχοληθώ και να ψάξω περαιτέρω τι συμβαίνει, αλλά είναι κάπως ανησυχητικό το συμβάν. Έχει πετύχει κάποιος κάτι αντίστοιχο; Έψαξα για κάποιο άρθρο που να εξηγεί αυτή τη συμπεριφορά αλλά δεν έπεσα πάνω σε κάτι.

    Στερνή μου γνώση να σε είχα πρώτα...
  •  08-03-2006, 12:57 10472 σε απάντηση της 10457

    Απ: SQL Server 2005 και IDENT_CURRENT

    Δεν κάνεις καλύτερα Post το κομμάτι του κώδικα που εκτελείς την  SP γιατί σε μένα λειτουργεί. Μήπως έχεις trigger στο table; 

    Άσχετα με αυτό το σωστό είναι σίγουρα το SCOPE_IDENTITY. Δες και αυτό το post για το Identity :

    http://www.dotnetzone.gr/cs/forums/8889/ShowPost.aspx


    Sex is like programing; One mistake, and you will have to support it for the rest of your life…
  •  08-03-2006, 13:38 10473 σε απάντηση της 10472

    Απ: SQL Server 2005 και IDENT_CURRENT

    Ο κώδικας που χρησιμοποιώ είναι νομίζω straightforward :

    SqlCommand cmd = new SqlCommand();
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText="[insertTestTable]";
    cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@ID", System.Data.SqlDbType.BigInt, 8, System.Data.ParameterDirection.Output, false, ((System.Byte)(0)), ((System.Byte)(0)), "", System.Data.DataRowVersion.Current, null));
    cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Value1", System.Data.SqlDbType.NVarChar, 100));
    cmd.Parameters.Add(new System.Data.SqlClient.SqlParameter("@Value2", System.Data.SqlDbType.NVarChar, 100));
    cmd.Parameters["@Value1"].Value = "testABCD";
    cmd.Parameters["@Value2"].Value = "test";
    SqlConnection sqlconn = new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings.Get("DataBase.ConnectionString"));
    sqlconn.Open();
    cmd.Connection = sqlconn;
    cmd.ExecuteNonQuery();
    sqlconn.Close();
    Console.Write("\tID : " + cmd.Parameters["@ID"].Value.ToString());


    Να σημειώσω ότι απλά αλλάζοντας την τιμή του Connection String από ένα instance με 2000 σε ένα instance με 2005 δεν βλέπω πλέον το επιθυμητό αποτέλεσμα. Όσον αφορά το SCOPE_IDENTITY, γνωρίζω ότι είναι πιο σωστή η χρήση του, αλλά δεν είναι αυτό που με απασχολεί εν προκειμένω, αλλά η διαφορά στην συμπεριφορά μεταξύ των SQL Server 2000 και SQL Server 2005...

    Στερνή μου γνώση να σε είχα πρώτα...
  •  09-03-2006, 00:04 10490 σε απάντηση της 10472

    Απ: SQL Server 2005 και IDENT_CURRENT

    Δοκίμασα τον κώδικα σου και δουλεύει κανονικά σε SQL Server 2005. Κάτι άλλο θα φταίει και όχι η IDENT_CURRENT. Η συμπεριφορά της IDENT_CURRENT δεν έχει αλλάξει στον 2005, ούτε φυσικά ο τρόπος με τον οποίο επιστρέφονται οι παράμετροι.

    Έχε υπόψη ότι η IDENT_CURRENT επιστρέφει NULL αν δώσεις ανύπαρκτο όνομα πίνακα. Μήπως συμβαίνει κάτι τέτοιο?

    Επίσης, μπορεί το script της βάσης να έχει πρόβλημα. Ένας εύκολος τρόπος να κάνεις migrate μια βάση από 2000 σε 2005 είναι να κάνεις backup από τον 2000 και restore στον 2005. Η νέα βάση που θα δημιουργηθεί θα τρέχει σε compatibility level 8 (2000). Δοκίμασε την έτσι και σε level 9 μήπως υπάρχει διαφορά.


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  09-03-2006, 17:55 10517 σε απάντηση της 10490

    Απ: SQL Server 2005 και IDENT_CURRENT

    Idea [I]Εύρηκα, Εύρηκα, και δεν χάρηκα καθόλου...

    Μετά και από τις προτροπές σας που δήλωναν ότι μάλλον κάτι έκανα στραβά, αποφάσισα να το ψάξω περισσότερο. Έπειτα λοιπόν από αρκετές δοκιμές με ότι μπορείτε να φανταστείτε (ούτε καν μπαίνω στον κόπο να τις αναφέρω), διαπίστωσα που βρισκόταν το πρόβλημα! Φαίνεται ότι στην περίπτωση του SQL Server 2005 δεν είχε ο χρήστης αρκετά permissions για να εκτελέσει την μέθοδο IDENT_CURRENT, ενώ με τα ίδια ακριβώς δικαιώματα στον SQL Server 2000 δεν υπήρχε κανένα πρόβλημα Surprise [:O]. Μάλιστα η εκτέλεση δεν έβγαζε κάποιο μηνυματάκι βρε αδερφέ, απλά επέστρεφε NULL. Να σημειώσω ότι για λόγους security είχα αφήσει μόνο δικαιώματα "Execute" για τον χρήστη που χρησιμοποιούσα για συγκεκριμένες stored procedure. Δεν χρειάζεται βέβαια να πω ότι το SCOPE_IDENTITY δεν τραβάει τέτοια κολλήματα και γι' αυτό και με παραπλάνησε...

    Επιβεβαίωσα λοιπόν την αρχική μου υπόνοια ότι όντως πέτυχα σε ένα σημείο στο οποίο συμπεριφέρεται διαφορετικά ο SQL Server 2005 από τον 2000. Μετά από λίγο Google-σμα (από το ρήμα Google-ίζω Smile [:)]) πέτυχα και αυτό το blog. Τουλάχιστον δεν θα μείνω με την απορία. Πάντως δεν είναι και πολύ ευχάριστο το γεγονός της αλλαγής συμπεριφοράς (σε οτιδήποτε κι αν είναι αυτή)...

    Στερνή μου γνώση να σε είχα πρώτα...
  •  09-03-2006, 21:19 10532 σε απάντηση της 10517

    Angry [:@] Απ: SQL Server 2005 και IDENT_CURRENT

     kkara wrote:
    Idea [I]Εύρηκα, Εύρηκα, και δεν χάρηκα καθόλου...

    Εγώ να δεις! Angry [:@] Υποθέστε ότι ακολουθούν τα διόλου κολακευτικά μου σχόλια προς τους συγγραφείς του Books Online του SQL Server 2005. Η αλλαγή αυτή θα έπρεπε να αναφέρεται στο documentation. Είναι απόλυτα λογικό η IDENT_CURRENT να μην επιστρέφει τιμές για ένα πίνακα στον οποίο δεν έχεις permissions, αλλά αυτό ΠΡΕΠΕΙ ΝΑ ΑΝΑΦΕΡΕΤΑΙ στο documentation!

    Το λιγότερο που μπορούμε να κάνουμε είναι να πάμε στη σελίδα του IDENT_CURRENT στο Books Online, να τραβήξουμε ένα 1 στο feedback για την ποιότητα του documentation (το έκανα) και να στείλουμε και ένα feedback με τις διαμαρτυρίες μας προς την Microsoft (κι αυτό το έκανα). Τουλάχιστον περιλαμβάνεται το link για το feedback.

    Το documentation του SQL Server 2005 δεν με έχει ικανοποιήσει καθόλου. Σε αφήνει ξεκρέμαστο σε πάρα πολλά σημεία, ακριβώς το αντίθετο με το πολύ καλό documentation του 2000 και του 7. Δείχνει υπερβολικά βιαστική δουλειά ...


    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems