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

 

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

Αποθήκευση XML

Îåêßíçóå áðü ôï ìÝëïò dimos.homatas. Τελευταία δημοσίευση από το μέλος dimos.homatas στις 10-10-2011, 15:59. Υπάρχουν 15 απαντήσεις.
Σελίδα 1 από 2 (16 εγγραφές)   1 2 >
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  07-10-2011, 11:03 67660

    Αποθήκευση XML

    Καλημέρα σας,

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

    Έχψω κάποια XML δεδομένα τα οποία αποθηκεύω σε πεδίο varchar(MAX). Κάποια στιγμή παρατήρησα τουλάχιστον μία περίπτωση που το xml δεν αποηθηκεύονταν ολόκληρο! Από τα 500 kb του συγκεκριμένου πεδίου, αποθήκευε τα 41 και κάτι... έψαξα μήπως παίζει κάνας περίεργος χαρακτήρας, τίποτα. Ψάχνω στον κώδικα του SqlCommand (με parameters κλπ), όλα καλά. Αλλάζω το πεδίο, text, ntext, το ίδιο πράγμα.

    Τελικά η λύση δόθηκε όταν στο SqlCommand έφτιαξα το insert paramenter να παίρνει SqlXml object για value αντί για string. Να σας πω την αλήθεια, πρώτη φορά χρησιμοποίησα το εν λόγω object... σιγά το object δηλαδή, ένα string value έχει μόνο.

    Το ερώτημα είναι: τις πταίει; Είναι δυνατόν ο sql server να κάνει διακρίσεις στα πεδία και αν δει κάποιο xml schema να... κόβει το πεδίο; περίεργο μου φαίνεται. Από την άλλη θέμα μήκους δεν παίζει, μιλάμε για 2 gb χωρητικότητα. Και μου κάνει εντύπωση, γιατί εάν περάσει το parameter ως string, δεν παίζει σωστά, παρότι φαίνεται ολόκληρο το value μέσα στο parameter collection.

    Ο SQL είναι 2008 R2.

    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  07-10-2011, 11:13 67662 σε απάντηση της 67660

    Απ: Αποθήκευση XML

    Νομίζω ότι καλο θα ήταν να δοκίμασεις το XML data type.Για το λόγο αυτο φτιαχθηκε.
    Antonios Chatzipavlis

  •  07-10-2011, 11:49 67664 σε απάντηση της 67660

    Απ: Αποθήκευση XML

    Έχεις και άλλα XML που είναι περίπου στα 500Kb (Kb ή KB;) αλλά έχουν αποθηκευτεί σωστά στον server όταν είχες σαν τύπο το VARCHAR(MAX);

    Χρησιμοποιώ το NVARCHAR(MAX) εδώ και πολύ καιρό για XML και ποτέ δεν είχα κάποιο πρόβλημα και μιλάμε επίσης για αρχεία της τάξης των ΚΒ. Γνωρίζω τον ειδικό τύπο XML που έχει ο server αλλά δεν έτυχε ακόμα να τον χρησιμοποιήσω. Η μόνη απαίτηση που έχω από αυτά τα XML δεδομένα είναι απλά να σωθούν και τίποτα άλλο, οπότε το NVARCHAR με βόλεψε.

    Θα ήθελα να δω την δήλωση της παραμέτρου που έκανες στον SQLCommand για τα XML δεδομένα. Νομίζω πως το πρόβλημα είναι conversion error και θα πρέπει να έγιναν truncate όλα τα δεδομένα XML μεγάλου μεγέθους και όχι μόνο ένα.

  •  07-10-2011, 12:35 67665 σε απάντηση της 67664

    Απ: Αποθήκευση XML

    Αντώνη, παρέλειψα να αναφέρω ότι στην λύση ο τύπος στον server είναι πλέον xml. Το ερώτημα είναι το πως προέκυψε το πρόβλημα όμως, και από που και ως που ο server κάνει διακρίσεις.

    Γιώργο, είναι πλέον όλα xml. Σε όλα τα sp ήταν όλα varchar(MAX) και το πρόβλημα προέκυψε σε συγκεκριμένες εγγραφές, και μάλλον λόγω μεγέθους. Έχω πολλές άλλες μικρότερες που δούλευαν κανονικά. Και εγώ την ίδια απαίτηση με την δικιά σου έχω, αλλά ο sql server (μάλλον) δεν μας τα είπε καλά... Στο τέλος έγιναν όλα xml, και σε συνδυασμό με το SqlXml object parameter, έπαιξε.

    Το ερώτημα είναι, γιατί τέτοιες ... κόνξες! Κάποια δεδομένα του είπαμε να αποθηκεύσει σε έναν varchar... 

    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  07-10-2011, 12:55 67667 σε απάντηση της 67665

    Απ: Αποθήκευση XML

    Οκ κανένα πρόβλημα. Απλά ήθελα να δω στον SQL Command πως δήλωσες τον τύπο δεδομένων για την παράμετρο της stored procedure που δέχεται VARCHAR(MAX). Το πιο πιθανό, στο μέγεθος δεν είχες βάλει -1 όταν δήλωσες στην SQLCommand ότι αυτή η παράμετρος είναι τύπου VARCHAR. Όταν βάλεις σκέτο VARCHAR τότε σου το κόβει στα 4Κ αν θυμάμαι καλά. Αν βάλεις όμως και το μέγεθος στο -1 τότε δεν το κόβει. Νομίζω εκεί ήτανε το πρόβλημα.

     

  •  08-10-2011, 15:37 67681 σε απάντηση της 67667

    Απ: Αποθήκευση XML

    Άλλο πράγματ τα varchar, nvarchar με συγκεκριμένο μέγεθος και άλλο τα varchar(max), nvarchar(max). Ο πρώτος τύπος έχει όριο τα 8000 bytes (8000 varchar ή 4000 nvarchar). Τα αντίστοιχα max δεν έχουν μέγεθος και χωράνε οποιοδήποτε μέγεθος μέχρι 2^32-1. Πρόκειται για τους τύπους που παλαιότερα ονομάζονταν text και ntext αντίστοιχα.

    Επιπλέον, άλλο πως είναι αποθηκευμένα στο server και άλλο τί παραμέτρους δίνεις εσύ στην SQL που εκτελείς. Όπως αναφέρεται και στο documentation για τους διάφορους τύπους, οι σωστοί τύποι είναι οι SqlDbType.Text και SqlDbType.NText, όχι οι SqlDbType.Varchar και NVarchar. Αν περάσεις ένα πολύ μεγάλο string σε παράμετρο varchar, λογικό είναι να κοπεί, γιατί πολύ απλά ξεπερνάει το μέγεθος του τύπου που έδωσες.

    Πέρα από το θέμα των τύπων πάντως, διαπιστώνω ένα άλλο ΠΟΛΥ ΜΕΓΑΛΟ πρόβλημα. Εκτός και αν η εφαρμογή απευθύνεται σε αμερικάνους, θα έχει πρόβλημα με τα ελληνικά καθώς το XML αποθηκεύεται σε πεδίο ASCII (varchar) αντί για Unicode (nvarchar). Η χρήση ASCII είναι ένα πολύ μεγάλο ρίσκο όταν χρησιμοποιούμε ελληνικά γιατί θα πρέπει όλα τα μηχανήματα, από το server μέχρι τον client ή τον browser, να έχουν ρυθμιστεί σε ελληνικό locale για να αποφευχθεί η εμφάνιση "κινέζικων". Κάτι το οποίο συμβαίνει πολύ σπάνια γι αυτό και ακούμε συχνά κόσμο να λέει "Ο SQL Server δεν δουλεύει με ελληνικά" όταν θα έπρεπε να λέει "η εφαρμογή μου δεν δουλεύει σωστά".  Και φυσικά δεν το συζητάμε αν χρειαστεί να αποθηκεύσουμε δεδομένα σε καμμία βαλκανική γλώσσα ...

    Μόλις την προηγούμενη εβδομάδα ρώταγε κάποιος στο Autoexec τί να κάνει με το ελληνικό λογιστικό που του στήσανε και αρνιόταν να δουλέψει σε server με λατινικό locale. Η απάντηση των τεχνικών της εταιρείας "ξαναστήσε το server" δεν αξίζει καν χαρακτηρισμό.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  09-10-2011, 21:42 67700 σε απάντηση της 67681

    Απ: Αποθήκευση XML

    Δοκίμασα και τα text, ntext. Πήγε και εκεί το μυαλό μου, αν και μου βρωμούσε  η δουλειά ήδη από την αποτυχία του (n)varchar(MAX).

    Συμπληρωματικά να αναφέρω ότι έτρεξα το εν λόγω stored procedure και από το management studio, έκανα paste ΟΛΑ τα δεδομένα... σε εκείνη την περίπτωση από τα 500 κάτι kb, αντί για να τα 42 περίπου που έγραφε από το πρόγραμμα, έγραψε 30 και κάτι. 

    Πληροφοριακά, κανένας "περίεργος" χαρακτήρας μέσα, καθαρά αγγλικά.

    Δεν δοκίμασα πάντως τους binary τύπους δεδομένων... μπορεί να δουλεύει κάτι τέτοιο, αλλά μου φάνηκε πολύ "άγριο".

    Αφού λύθηκε το θέμα με το xml data type + sqlxml, πάλι καλά, τουλάχιστον έγινε η δουλειά. Απλά δεν μου αρέσει που υπάρχει αυτού του είδους η "δυσανεξία" από τους τύπους-κουβάδες προς τα xml δεδομένα.

    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  09-10-2011, 22:19 67702 σε απάντηση της 67700

    Απ: Αποθήκευση XML

    Ποιό stored procedure? Τί κάνει αυτό? Πού είναι? Δεν το έχεις κάνει post. Γιατί θεωρείς ότι το πρόβλημα είναι στον SQL Server και όχι στο stored procedure? Πέρα από το ότι οι πιθανότητες είναι 100000000000000:1 ότι φταίει ο κώδικας, αν υπήρχε κάποιο θέμα να είσαι σίγουρος ότι θα είχε γίνει βούκινο. 

    Δυσανεξία από τον server δεν υπάρχει, ούτε έχει διαπιστωθεί τα τελευταία 15 χρόνια. Προβλήματα στον κώδικα, άπειρα. Δείξε μας τον κώδικα σου να βρούμε τί συμβαίνει

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  10-10-2011, 11:34 67704 σε απάντηση της 67702

    Απ: Αποθήκευση XML

    Δεν έχω τον λάθος κώδικα πλέον, θα ποστάρω το ένα sp και το xml καθώς και τα σωστά με υποσημειώσεις.
    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  10-10-2011, 11:59 67705 σε απάντηση της 67704

    Απ: Αποθήκευση XML

    Για να μην έχεις καμμία αμφιβολία, δημιούργησα ένα πίνακα με αυτό το script:
    create table TestTable
    (
    	Id int PRIMARY KEY,
    	XmlField nvarchar(max)
    )

    Και έβαλα μέσα ένα XML των 300KB με τον παρακάτω κώδικα
    static void Main(string[] args)
            {
                var contents=File.ReadAllText("Castle.Core.xml");
    
                using (var connection = new SqlConnection(Settings.Default.TestConnection))
                {
                    var cmd = new SqlCommand("insert into TestTable (ID,XmlField) VALUES(@id,@xmlField)",connection);
                    var paramXml=cmd.Parameters.Add("@xmlField", SqlDbType.NText);
                    var paramId = cmd.Parameters.Add("@id", SqlDbType.Int);
                    paramId.Value = 1;
                    paramXml.Value = contents;
    
                    connection.Open();
                    cmd.ExecuteNonQuery();
                }
    
                using (var connection = new SqlConnection(Settings.Default.TestConnection))
                {
                    var cmd = new SqlCommand("select XmlField from TestTable where ID=1", connection);
                    
                    connection.Open();
                    var result=(string)cmd.ExecuteScalar();
                    Debug.Assert(result.Length==contents.Length);
    
                }
            
            }

    Δεν αντιμετώπισα κανένα πρόβλημα. Άλλαξα τον τύπο του πεδίου σε varchar και τον τύπο της παραμέτρου σε SqlDbType.Text, επίσης κανένα πρόβλημα. Άλλαξα τον τύπο της παραμέτρους σε SqlDbType.Varchar ΠΑΛΙ κανένα πρόβλημα. Άλλαξα τον κώδικα που δημιουργεί την παράμετρο σε 
    cmd.Parameters.AddWithValue("@xmlField", contents);

    Παρότι δεν περνάω τύπο και μέγεθος, πάλι δεν είχα πρόβλημα.

    Νομίζω ότι πρέπει να ρίξεις μία ματιά πως φορτώνεις τα XML δεδομένα και τί SQL statement εκτελείς γιατί απλά δεν μπορώ να αναπαράγω το πρόβλημα που αναφέρεις. Ακόμη και η αρχική μου υπόθεση ότι έφταιγε ο τύπος της παραμέτρου αποδείχθηκε λάθος. Ο SQL server και το ADO.NET χειρίζονται άνετα τα XML δεδομένα, όσο μεγάλα και να είναι, φτάνει το πεδίο που χρησιμοποιείς να μπορεί να τα χωρέσει.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  10-10-2011, 12:13 67706 σε απάντηση της 67704

    Απ: Αποθήκευση XML

    Ορίστε το Insert sp

    USE [mwIBS]
    GO
    /****** Object:  StoredProcedure [dbo].[sp_InsertTrace]    Script Date: 10/10/2011 11:37:58 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    ALTER PROCEDURE [dbo].[sp_InsertTrace] 
    	@Service varchar(100),
    	@Method varchar(100),
    	@RequestXML xml,
    	@ResponseXML xml,
    	@RequestObject varchar(50),
    	@ResponseObject varchar(50)
    AS
    BEGIN
    -- InsertTrace
    INSERT INTO Traces
    (
    	Service,
    	Method,
    	RequestXML,
    	ResponseXML,
    	RequestObject, 
    	ResponseObject
    )
    VALUES
    (
    	@Service,
    	@Method,
    	@RequestXML,
    	@ResponseXML,
    	@RequestObject,
    	@ResponseObject
    );
    SELECT SCOPE_IDENTITY();
    
    END
    Τα πεδία RequestXML και ResponseXML είναι το σημείο τριβής, ειδικότερα το ResponseXML. Σε αυτό δοκίμασα και το varchar(MAX), nvarchar(MAX), text, ntext. Εδώ είναι πλέον xml.



    Ορίστε και η κλήση του κώδικα:

        public Trace InsertTrace(Trace trace)
        {
          using (SqlConnection Conn = new SqlConnection(Properties.Settings.Default.connectionString))
          {
            Conn.Open();
            using (SqlTransaction trans = Conn.BeginTransaction())
            using (SqlCommand cmd = new SqlCommand("sp_InsertTrace", Conn, trans))
            {
              cmd.CommandType = CommandType.StoredProcedure;
              cmd.Parameters.Add(new SqlParameter("@Service", trace.Service));
              cmd.Parameters.Add(new SqlParameter("@Method", trace.Method));
              cmd.Parameters.Add(new SqlParameter("@RequestXML", trace.RequestSqlXml));
              cmd.Parameters.Add(new SqlParameter("@ResponseXML", trace.ResponseSqlXML));
              cmd.Parameters.Add(new SqlParameter("@RequestObject", trace.RequestObjectName));
              cmd.Parameters.Add(new SqlParameter("@ResponseObject", trace.ResponseObjectName));
              trace.TraceId = Convert.ToInt32(cmd.ExecuteScalar());
    
              foreach (TraceCriterion traceCriterion in trace.TraceCriteria)
              {
                traceCriterion.TraceId = trace.TraceId;
                InsertCriterion(traceCriterion, Conn, trans);
              }
    
              trans.Commit();
              Conn.Close();
              return trace;
            }
          }
        }
    
        private TraceCriterion InsertCriterion(TraceCriterion traceCriterion, SqlConnection conn, SqlTransaction trans)
        {
          using (SqlCommand cmd = new SqlCommand("sp_InsertTraceCriterion", conn, trans))
          {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Transaction = trans;
            cmd.Parameters.Add(new SqlParameter("@TraceId", traceCriterion.TraceId));
            cmd.Parameters.Add(new SqlParameter("@Criterion", traceCriterion.Criterion));
            cmd.Parameters.Add(new SqlParameter("@CannedValue", traceCriterion.CannedValue));
            traceCriterion.TraceCriterionId = Convert.ToInt32(cmd.ExecuteScalar());
            return traceCriterion;
          }
        }
    Στις παραμέτρους που περνάει το αντικείμενο, τα members RequestSqlXml & ResponseSqlXml είναι πλέον τύπου SqlXml. Πιο πριν, στις δοκιμές με τα varchar κλπ ήταν απλώς string - το οποίο επαναλαμβάνω, ήταν ολόκληρο, και ελέγχοντας ακόμα και το parameters collection, δεν έλειπε τίποτα.

    Μπορώ να ανεβάσω και το επίμαχο xml, είναι καμιά 40αριά kb συμπιεσμένο.

    Παρέλειψα το δευτερεύον sp του InsertCriterion... δεν έχει σημασία.




    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  10-10-2011, 12:15 67707 σε απάντηση της 67704

    Απ: Αποθήκευση XML

    Πόσταρα κώδικα, αλλά θέλει administrator approval? Καινούριο κόλπο;
    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  10-10-2011, 12:20 67709 σε απάντηση της 67707

    Απ: Αποθήκευση XML

    Για κάποιον λόγο το φόρουμ μου λέει ότι το ποστ θέλει έγκριση - αν και αυτά τα ποστάρει. 

    Παναγιώτη, είναι όντως πολύ straightforward, και δεν νομίζω να έχω καμιά "κουλαμάρα" μέσα. Έχω και το επίμαχο xml αν θες, αλλά πρέπει να το ανεβάσω κάπου. Από ότι βλέπω δεν έχουμε attachments.

    "When the darkness rises up from inside - that is normal.
    It's when you reach down to pull it up - that the noxious warnings sound."
    Tuzak, Farscape
  •  10-10-2011, 12:28 67710 σε απάντηση της 67709

    Απ: Αποθήκευση XML

    Αν δεν σταματήσεις τα απανωτά post δεν θα προλάβω ποτέ να κάνω approve τον κώδικα. Έλεος! Αφού σου λέει ότι θέλει approval, πρέπει να αφήσεις κάποιον να κάνει το approval!

    Ο Community Server μαρκάρει για approval οποιοδήποτε post φαίνεται να περιέχει περίεργα πράγματα.

    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  10-10-2011, 13:19 67711 σε απάντηση της 67710

    Απ: Αποθήκευση XML

    Δοκίμασα ξανά με αυτόν τον πίνακα και stored procedure:
    create table TestTable
    (
    	Id int PRIMARY KEY IDENTITY,
    	XmlField varchar(max)
    )
    ALTER PROCEDURE [dbo].[sp_InsertTest] 	
    	@XML varchar(max)
    AS
    BEGIN
    INSERT INTO TestTable
    (
    	XmlField
    )
    VALUES
    (
    	@XML
    );
    SELECT SCOPE_IDENTITY();
    
    END
    Και αυτόν τον κώδικα:
    decimal newID ;
    using (var connection = new SqlConnection(Settings.Default.TestConnection))
    {
            var cmd = new SqlCommand("sp_InsertTest", connection);
            cmd.CommandType = CommandType.StoredProcedure;
            //var paramXml = cmd.Parameters.Add(new SqlParameter("@XML", contents));
            cmd.Parameters.AddWithValue("@XML", contents);
    
            connection.Open();
            newID= (decimal) cmd.ExecuteScalar();                
    }
    Οι δύο γραμμές για τη δημιουργία της παραμέτρου κάνουν ακριβώς το ίδιο, καθώς η AddWithValue κυριολεκτικά είναι μόνο ένα 
    return this.Add(new SqlParameter(parameterName, value));

    Και πάλι δεν υπήρξε truncation. Πρόβλημα εμφανίστηκε μόνο όταν αντί για varchar(max) έβαλα στο stored procedure σκέτο varchar (το οποίο είναι αντίστοιχο του varchar(1)) ή varchar με συγκεκριμένο μέγεθος.

    Καλό είναι να απομονώνεις τον ύποπτο κώδικα σε ένα ξεχωριστό test project  όταν αντιμετωπίζεις "περίεργες" συμπεριφορές. Το πρόβλημα μπορεί να οφείλεται σε κάτι εντελώς διαφορετικό από αυτό που νομίζεις αρχικά αλλά δεν φαίνεται μέσα στην εφαρμογή γιατί το ένα κομμάτι κώδικα επηρεάζει το επόμενο. Απομονώνοντας τα διάφορα τμήματα μπορείς να αποκλείσεις εύκολα τα πράγματα που δεν φταίνε για να βρεις τον πραγματικό ένοχο.

    Το debugging δεν είναι και τόσο διαφορετικό από το CSI και πολλές από τις τεχνικές του ενός χρησιμοποιούνται και στο άλλο. Από το "απομόνωσε τα στοιχεία" μέχρι το "μην εμπιστεύεσαι τους μάρτυρες"

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