|
Îåêßíçóå áðü ôï ìÝëïò dimos.homatas. Τελευταία δημοσίευση από το μέλος dimos.homatas στις 10-10-2011, 15:59. Υπάρχουν 15 απαντήσεις.
-
07-10-2011, 11:03
|
-
dimos.homatas
-
-

-
Μέλος από τις 13-12-2010
-
Θεσσαλονίκη
-
Δημοσιεύσεις 319
-
-
|
Καλημέρα σας,
χθες αντιμετώπισα ένα περίεργο πρόβλημα. Το έλυσα μεν, αλλά δεν πολυκατάλαβα το πως προέκυψε.
Έχψω κάποια 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
|
|
Νομίζω ότι καλο θα ήταν να δοκίμασεις το XML data type.Για το λόγο αυτο φτιαχθηκε.
Antonios Chatzipavlis
|
|
-
-
07-10-2011, 12:35
|
-
dimos.homatas
-
-

-
Μέλος από τις 13-12-2010
-
Θεσσαλονίκη
-
Δημοσιεύσεις 319
-
-
|
Αντώνη, παρέλειψα να αναφέρω ότι στην λύση ο τύπος στον 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
|
-
08-10-2011, 15:37
|
|
Άλλο πράγματ τα 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
|
-
dimos.homatas
-
-

-
Μέλος από τις 13-12-2010
-
Θεσσαλονίκη
-
Δημοσιεύσεις 319
-
-
|
Δοκίμασα και τα 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
|
|
Ποιό stored procedure? Τί κάνει αυτό? Πού είναι? Δεν το έχεις κάνει post. Γιατί θεωρείς ότι το πρόβλημα είναι στον SQL Server και όχι στο stored procedure? Πέρα από το ότι οι πιθανότητες είναι 100000000000000:1 ότι φταίει ο κώδικας, αν υπήρχε κάποιο θέμα να είσαι σίγουρος ότι θα είχε γίνει βούκινο.
Δυσανεξία από τον server δεν υπάρχει, ούτε έχει διαπιστωθεί τα τελευταία 15 χρόνια. Προβλήματα στον κώδικα, άπειρα. Δείξε μας τον κώδικα σου να βρούμε τί συμβαίνει
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
10-10-2011, 11:34
|
-
10-10-2011, 11:59
|
|
Για να μην έχεις καμμία αμφιβολία, δημιούργησα ένα πίνακα με αυτό το 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
|
-
dimos.homatas
-
-

-
Μέλος από τις 13-12-2010
-
Θεσσαλονίκη
-
Δημοσιεύσεις 319
-
-
|
Ορίστε το 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
|
-
10-10-2011, 12:20
|
-
dimos.homatas
-
-

-
Μέλος από τις 13-12-2010
-
Θεσσαλονίκη
-
Δημοσιεύσεις 319
-
-
|
Για κάποιον λόγο το φόρουμ μου λέει ότι το ποστ θέλει έγκριση - αν και αυτά τα ποστάρει.
Παναγιώτη, είναι όντως πολύ 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
|
|
Αν δεν σταματήσεις τα απανωτά post δεν θα προλάβω ποτέ να κάνω approve τον κώδικα. Έλεος! Αφού σου λέει ότι θέλει approval, πρέπει να αφήσεις κάποιον να κάνει το approval!
Ο Community Server μαρκάρει για approval οποιοδήποτε post φαίνεται να περιέχει περίεργα πράγματα.
Παναγιώτης Καναβός, Freelancer Twitter: http://www.twitter.com/pkanavos
|
|
-
10-10-2011, 13:19
|
|
Δοκίμασα ξανά με αυτόν τον πίνακα και 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
|
|
|