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

 

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

Πως θα πάρω το τελευταίο Id πίνακα?

Îåêßíçóå áðü ôï ìÝëïò gmlogic. Τελευταία δημοσίευση από το μέλος gmlogic στις 18-09-2006, 09:23. Υπάρχουν 43 απαντήσεις.
Σελίδα 3 από 3 (44 εγγραφές)   < 1 2 3
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  10-09-2006, 16:52 16521 σε απάντηση της 16519

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

     gmlogic wrote:
    Λοιπόν !!!!

    Ποιό πάνω έχω τον κώδικα που ανάλογα το DataRowState φτιάχνει

    ο command_builder τα sql querys

    Μπορώ να πάρω το ID μετά το

    da_Sql.InsertCommand = command_builder.GetInsertCommand()

    ή δεν μπορώ?

    Ή πρέπει να αλλάξω τον κωδικά μου και να τα κάνω χειροκίνητα

    ή πρέπει να γυρίσω τα queries σε store procedures ή ......

    ή γιατί πρέπει να μιλάμε για MSSQL2005

    Δέν ξερω :)

    Όπως μς χαρά θα συμβούλευα ένα με λιγώτερη γνώση από μένα

    έτσι θέλω και εγώ να μάθω από κάποιον που ξέρει ποιό πολά από μένα

    γιατί σίγουρα κάποιος ξέρει ποιό πολλά από μένα ......

    Γιώργος Μ.

    Εγώ το κάνω πολύ καιρό αυτό και με generic κώδικα, όπως περίπου αυτόν που έχεις και εσύ. CommandBuilder και δημιουργία του select statement με loop. Λειτουργεί πολύ καλά τόσο σε sql2000 όσο και σε sql2005.


    Dimitris Papadimitriou
    Software Development Professional
    dotNETZone.gr News

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Διαβάστε επίσης τους όρους χρήσης.
  •  10-09-2006, 20:35 16525 σε απάντηση της 16521

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Λοιπόν, το κοίταξα το πρόβλημα κι έγραψα λίγο κώδικα για να δοκιμάσω στην πράξη αυτά που θεωρητικά είπαμε. Ανακεφαλαιώνοντας, έχουμε και λέμε:

    Υπάρχουν τρεις τρόποι για να κάνεις αυτό που θέλεις. Ας ξεκινήσουμε από τον πρώτο που είναι να χρησιμοποιήσεις το RowUpdated event του DataAdapter και την στιγμή που γράφεται κάθε εγγραφή να στέλνεις ένα Query που να ρωτάς το νέο ID.

    Σε όλα τα παραδείγματα, υποτίθεται ότι δουλεύουμε σε έναν πίνακα στη Northwind που τον έχω φτιάξει με αυτήν την εντολή

    CREATE TABLE DataBuilderDemo(ColumnID int identity NOT NULL PRIMARY KEY, Column1 nvarchar(16) NOT NULL)

    O κώδικας στην φόρμα έχει ως εξής:

        Dim ConnectionNorthwind As New SqlConnection("Data Source=.;Initial Catalog=Northwind;Integrated Security=True")
        Dim DataAdapterCategories As New SqlDataAdapter("SELECT ColumnID, Column1 FROM DataBuilderDemo", ConnectionNorthwind)
        Dim CommandBuilderCategories As New SqlCommandBuilder(DataAdapterCategories)
        Dim DataTableCategories As New DataTable
        Dim CommandRefresh As New SqlCommand("SELECT @@IDENTITY", ConnectionNorthwind)

        Private Sub CreateInsertCommandButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CreateInsertCommandButton.Click
            DataAdapterCategories.InsertCommand = CommandBuilderCategories.GetInsertCommand
            AddHandler DataAdapterCategories.RowUpdated, AddressOf RowUpdatedHandler
        End Sub

        Private Sub FillTableButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FillTableButton.Click
            DataAdapterCategories.Fill(DataTableCategories)
        End Sub

        Private Sub AddNewRowButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddNewRowButton.Click
            Dim RowNew As DataRow
            RowNew = DataTableCategories.NewRow
            RowNew.Item(0) = 0
            RowNew.Item(1) = "New Row"
            DataTableCategories.Rows.Add(RowNew)

            PrintRows("Rows before update:")
        End Sub

        Private Sub UpdateButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UpdateButton.Click
            Try
                DataAdapterCategories.Update(DataTableCategories)
            Catch ex As Exception
                Console.WriteLine(ex.Message)
            End Try

            PrintRows("Rows after update:")
        End Sub

        Private Sub PrintRows(ByVal message As String)
            Console.WriteLine(message)

            For Each row As DataRow In DataTableCategories.Rows
                Console.WriteLine(String.Format("    {0}, {1}", row.Item(0), row.Item(1)))
            Next row

            Console.WriteLine()
        End Sub

        Private Sub RowUpdatedHandler(ByVal sender As Object, ByVal e As SqlRowUpdatedEventArgs)
            If e.Status = UpdateStatus.[Continue] AndAlso (e.StatementType = StatementType.Insert) Then
                e.Row("ColumnID") = CInt(CommandRefresh.ExecuteScalar)
                e.Row.AcceptChanges()
            End If
        End Sub
     

    Προσοχή χρειάζεται στα εξής σημεία: Δεν μπορούμε να χρησιμοποιήσουμε SCOPE_IDENTITY() αντί για @@IDENTITY γιατί στη RowUpdatedHandler, κάθε φορά που τρέχουμε το CommandRefresh, δημιουργείται νέο connection και το SCOPE_IDENTITY() επιστρέφει null. Επίσης, αυτή η τεχνική δουλεύει και σε Access.

    Η δεύτερη τεχνική είναι να αλλάξεις το InsertCommand που σου δίνει ο CommandBuilder έτσι ώστε να έχεις ένα Batched Query. Στη νέα έκδοση των παραπάνω, καταργείται η ρουτίνα RowUpdatedHandler, και το περιεχόμενο της CreateInsertCommandButton_Click αλλάζει σε:

        Private Sub CreateInsertCommandButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CreateInsertCommandButton.Click
            DataAdapterCategories.InsertCommand = CommandBuilderCategories.GetInsertCommand
            DataAdapterCategories.InsertCommand.CommandText &= "; SELECT @@IDENTITY AS ColumnID"
            DataAdapterCategories.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord
        End Sub

    Όμως φρούδες οι ελπίδες... Το παραπάνω δεν δουλεύει αν και θα έπρεπε! Λέω "αν και θα έπρεπε" γιατί αν αντί γι αυτό, γράψουμε

        Private Sub CreateInsertCommandButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CreateInsertCommandButton.Click
            Dim InsertCommand As SqlCommand
            Dim strSQL As String
            strSQL = "INSERT INTO DataBuilderDemo (Column1) VALUES (@Column1); SELECT SCOPE_IDENTITY() AS ColumnID"
            InsertCommand = New SqlCommand(strSQL, ConnectionNorthwind)
            InsertCommand.Parameters.Add("@Column1", SqlDbType.NVarChar, 16, "Column1")
            InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord
            DataAdapterCategories.InsertCommand = InsertCommand
        End Sub

    δηλαδή κατασκευάσουμε χειροκίνητα την InsertCommand, τότε παίζει! Απλά δεν του κάνει η InsertCommand που γυρίζει ο CommandBuilder, ακόμα κι αν προσθέσει κανείς στο τέλος το "; SELECT SCOPE_IDENTITY() AS ColumnID". Βασικά, έκανα πολλές δοκιμές αλλά δεν βρήκα καμιά ειδοποιό διαφορά ανάμεσα στα δύο Commands ώστε να καταλάβω τι δεν πάει καλά με το command που παράγει το CommandBuilder. Όποιος έχει όρεξη ας το ψάξει περισσότερο να μας πει.

    Υπάρχει και μία τρίτη τεχνική που είναι να χρησιμοποιήσεις stored procedure η οποία θα επιστρέφει ως output το νέο ID.

    CREATE PROCEDURE spInsertDataBuilderDemo
     (@ColumnID int OUTPUT,
      @Column1 nvarchar(16))
    AS
     INSERT INTO tblAutoIncrementTest(Column1) VALUES (@Column1)
     SELECT @ColumnID = SCOPE_IDENTITY()

    Και αντίστοιχα, η CreateInsertCommandButton_Click γίνεται κάπως έτσι:

        Private Sub CreateInsertCommandButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CreateInsertCommandButton.Click
            Dim InsertCommand As SqlCommand
            Dim strSQL As String
            Dim param As SqlParameter
            strSQL = "spAutoIncrementTestInsert"
            InsertCommand = New SqlCommand(strSQL, ConnectionNorthwind)
            param = InsertCommand.Parameters.Add("@ColumnID", SqlDbType.Int, 0, "ColumnID")
            param.Direction = ParameterDirection.Output
            InsertCommand.Parameters.Add("@Column1", SqlDbType.NVarChar, 16, "Column1")
            InsertCommand.CommandType = CommandType.StoredProcedure
            InsertCommand.UpdatedRowSource = UpdateRowSource.OutputParameters
            DataAdapterCategories.InsertCommand = InsertCommand
        End Sub

    Από τις τρεις λύσεις, εφόσον θέλεις απαραιτήτως να χρησιμοποιήσεις CommandBuilder ουσιαστικά σου κάνει μόνο η πρώτη. Θα σου πρότεινα να επανεξετάσεις το κατά πόσο είναι εφικτό να μην χρησιμοποιήσεις τον CommandBuilder και να περάσεις στην δεύτερη ή ακόμα καλύτερα την τρίτη λύση που έχει καλύτερο performance. Προσωπικά, ποτέ δεν τον έχω χρησιμοποιήσει και τώρα βλέπω πόσο δίκιο έχουν όλοι αυτοί που έγραφαν στα blogs και τα βιβλία τους ότι είναι μόνο για quick & dirty και όχι production κώδικα.


     


    Vir prudens non contra ventum mingit
  •  10-09-2006, 21:06 16526 σε απάντηση της 16525

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Το βρήκα! Η 2η λύση είναι εφικτή!

    Πρέπει να μπει κάπου εκεί και το CommandBuilderCategories.RefreshSchema()
    Dimitris Papadimitriou
    Software Development Professional
    dotNETZone.gr News

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Διαβάστε επίσης τους όρους χρήσης.
  •  10-09-2006, 21:20 16527 σε απάντηση της 16526

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    To δοκίμασες; Που ακριβώς να πάει το RefreshSchema; Γιατί αν θυμάμαι καλά, το RefreshSchema απλά καθαρίζει τα Commands του CommandBuilder.
    Vir prudens non contra ventum mingit
  •  11-09-2006, 01:42 16528 σε απάντηση της 16527

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    OK, ανακάλυψα τι φταίει στο δεύτερο σενάριο και τώρα μπορώ να πάω για ύπνο...

    Λοιπον, οι δύο βασικές εντολές είναι:

     
            DataAdapterCategories.InsertCommand = CommandBuilderCategories.GetInsertCommand
            DataAdapterCategories.InsertCommand.CommandText &= "; SELECT @@IDENTITY AS ColumnID"

    Από τον Profiler είδα ότι όταν ο DataAdapter στέλνει την InsertCommand, o SQL Server λαμβάνει προς εκτέλεση το παρακάτω:


    exec sp_executesql N'INSERT INTO [DataBuilderDemo] ([Column1]) VALUES (@p1)',N'@p1 nvarchar(5)',@p1=N'New Row'

    που σημαίνει ότι άσχετα αν εμείς προσθέτουμε το "; SELECT @@IDENTITY AS ColumnID" στο τέλος του CommandText property, αυτό αγνοείται! Το κόλπο είναι να πάρουμε όλο το Command object μέσω του CommandBuilder (γιατί μας ενδιαφέρει το CommandText αλλά και το Parameters collection) αλλά να μην διατηρήσουμε το reference στo  CommandBuilder ώστε μετά να μπορούμε να το αλλάξουμε. Δεν ξέρω τα inner workings του DataAdapter, ενδεχομένως να ξανακαλεί κάποια στιγμή την GetInsertCommand. Εν κατακλείδει, το πρόβλημα τελικά λύνεται αν πούμε

     
            DataAdapterCategories.InsertCommand = CommandBuilderCategories.GetInsertCommand.Clone
            ...

     


    Vir prudens non contra ventum mingit
  •  11-09-2006, 09:32 16532 σε απάντηση της 16528

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

     KelMan wrote:

    Δεν ξέρω τα inner workings του DataAdapter, ενδεχομένως να ξανακαλεί κάποια στιγμή την GetInsertCommand. Εν κατακλείδει, το πρόβλημα τελικά λύνεται αν πούμε

    Και εγώ δεν τα ξέρω, αλλά επειδή όντως κάτι συμβαίνει εκεί, το refreshschema το λύνει. Εγώ το βάζω αφού έχω πάρει το insert command από τον commandbuilder και το έχω τροποποιήσει και πριν το θέσω στον adapter.


    Dimitris Papadimitriou
    Software Development Professional
    dotNETZone.gr News

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Διαβάστε επίσης τους όρους χρήσης.
  •  11-09-2006, 14:40 16559 σε απάντηση της 16499

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Μου έμεινε ένα κενό για την δεύτερη λύση.

    Πώς πέρνω το ColumnID σε μιά μεταβλητή?

    Καί πάλι σας ευχαριστώ
    George Matzouranis
  •  11-09-2006, 20:21 16584 σε απάντηση της 16559

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Όταν γίνεται το Update από τον DataAdapter η νέα τιμή του ID μπαίνει στην θέση της παλιάς μέσα στο DataRow. Κοίταξε τον κώδικα step-by-step, την δεύτερη φορά που τρέχει η PrintRows μπορείς να διαβάσεις την τιμή και να την περάσεις σε μεταβλητή.
    Vir prudens non contra ventum mingit
  •  12-09-2006, 11:52 16606 σε απάντηση της 16506

    Embarrassed [:$] Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Ok Μάνο το κατάλαβα και μου δούλεψε.

    Μόνο υπάρχει ένα μικρό πρόβλημα

    Όταν δίνω DataAdapterCategories.InsertCommand = CommandBuilderCategories.GetInsertCommand.Clone

    γιά να δουλέψει επειδή όπως επισήμανες και συ αν δεν δώσω clone δεν κρατάει το

    SELECT @@IDENTITY AS ColumnI

    Επειδή χρησιμοποιώ το παραδειγμά σου

    Dim command_builder As DbCommandBuilder = dataFactory.CreateCommandBuilder()

    το clone δεν υπάρχει

    Μήπως το RefreshSchema που λέει ο Δημήτρης πέζει?

    Πάντως με το

    Dim CommandBuilderCategories As New SqlCommandBuilder(DataAdapterCategories)

    Πέζει μιά χαρά
    George Matzouranis
  •  12-09-2006, 17:12 16633 σε απάντηση της 16606

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    H DbCommandBuilder είναι abstract base class που σημαίνει ότι δεν μπορείς να την χρησιμοποιήσεις απ'ευθείας, δηλαδή δεν μπορείς να πεις


    Dim command_builder As New DbCommandBuilder(...)

    και γι αυτόν το λόγο δεν έχει την clone μέθοδο.

    Σχετικά με το RefreshSchema, στο MSDN λέει:


    The DbCommandBuilder also uses the Connection, CommandTimeout, and Transaction properties referenced by the SelectCommand. The user should call RefreshSchema if any of these properties are modified, or if the SelectCommand itself is replaced. Otherwise the InsertCommand, UpdateCommand, and DeleteCommand properties retain their previous values.

    Πραγματικά, δεν μπορώ να φανταστώ το πως μπορεί να βοηθήσει το RefreshSchema από την στιγμή που αλλάζεις το CommandText property του InsertCommand.

     


    Vir prudens non contra ventum mingit
  •  12-09-2006, 17:58 16639 σε απάντηση της 16407

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Ok Μάνο ευχαριστώ

    Μήπως θα μπορούσε ο Δημήτρης να μας στείλει ένα παραδειγματάκι.

    Γιατί λέει οτι του δουλεύει με το RefreshSchema σε ποιά σημεία το βάζη?


    George Matzouranis
  •  13-09-2006, 14:00 16689 σε απάντηση της 16639

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    1) δημιουργώ commandbuilder

    2) παίρνω insert command (σε προσωρινή μεταβλητή, όχι στον adapter)

    3) τροποποιώ insert command : προσθέτω στο τέλος του command text ένα SELECT MyIdentityColumn, Col1, Col2 .... FROM MyTable WHERE MyIdentityColumn=SCOPE_IDENTITY()

    4) αλλάζω το UpdatedRowSource του insert command σε Both

    5) εκτελώ το commandBuilder.RefreshSchema

    6) θέτω το insert command στον adapter


    Dimitris Papadimitriou
    Software Development Professional
    dotNETZone.gr News

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Διαβάστε επίσης τους όρους χρήσης.
  •  13-09-2006, 14:04 16690 σε απάντηση της 16689

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Επίσης, αν χρησιμοποιείς την getchanges, ενημερώνεις, και μετά κάνεις merge στο αρχικό dataset, πρέπει να έχεις υπόψη σου κάποια πράγματα που αναφέρονται εδώ: http://msdn2.microsoft.com/en-us/library/ks9f57t0.aspx

    Δες το σημείο που μιλάει για "Merging New Identity Values".


    Dimitris Papadimitriou
    Software Development Professional
    dotNETZone.gr News

    Οι απαντήσεις παρέχονται για συγκεκριμένες ερωτήσεις και χωρίς καμιά εγγύηση. Διαβάστε επίσης τους όρους χρήσης.
  •  18-09-2006, 09:23 16830 σε απάντηση της 16690

    Απ: Πως θα πάρω το τελευταίο Id πίνακα?

    Σας ευχαριστώ όλους για τη βοήθεια :)


    George Matzouranis
Σελίδα 3 από 3 (44 εγγραφές)   < 1 2 3
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems