XML Serialization के लिए StringWriter का उपयोग करना


99

मैं वर्तमान में वस्तुओं को क्रमबद्ध करने का एक आसान तरीका खोज रहा हूं (C # 3 में)।

मैंने कुछ उदाहरणों को जाना और कुछ के साथ आया:

MemoryStream memoryStream = new MemoryStream ( );
XmlSerializer xs = new XmlSerializer ( typeof ( MyObject) );
XmlTextWriter xmlTextWriter = new XmlTextWriter ( memoryStream, Encoding.UTF8 );
xs.Serialize ( xmlTextWriter, myObject);
string result = Encoding.UTF8.GetString(memoryStream .ToArray());

इस सवाल को पढ़ने के बाद मैंने खुद से पूछा, क्यों न स्ट्रिंगर का इस्तेमाल किया जाए? यह बहुत आसान लगता है।

XmlSerializer ser = new XmlSerializer(typeof(MyObject));
StringWriter writer = new StringWriter();
ser.Serialize(writer, myObject);
serializedValue = writer.ToString();

एक और समस्या यह थी, कि पहला उदाहरण एक्सएमएल जेनरेट मैं सिर्फ SQL सर्वर 2005 DB के एक XML कॉलम में नहीं लिख सकता था।

पहला सवाल यह है: क्या एक कारण है कि मैं किसी वस्तु को क्रमबद्ध करने के लिए स्ट्रिंगराइटर का उपयोग नहीं करूं, जब मुझे बाद में इसे स्ट्रिंग के रूप में आवश्यकता हो? गोलगप्पे खाते समय मुझे StringWriter का उपयोग करने का परिणाम कभी नहीं मिला।

दूसरा, निश्चित रूप से: यदि आपको इसे स्ट्रिंगराइटर के साथ नहीं करना चाहिए (जो भी कारणों से), जो एक अच्छा और सही तरीका होगा?


इसके अलावा:

जैसा कि यह पहले से ही दोनों उत्तरों से उल्लेखित था, मैं आगे XML में DB समस्या पर जाऊंगा।

डेटाबेस में लिखते समय मुझे निम्नलिखित अपवाद मिला:

System.Data.SqlClient.SqlException: XML पार्सिंग: पंक्ति 1, वर्ण 38, एन्कोडिंग को स्विच करने में असमर्थ

स्ट्रिंग के लिए

<?xml version="1.0" encoding="utf-8"?><test/>

मैंने XmlTextWriter से बनाए गए स्ट्रिंग को लिया और बस xml के रूप में वहाँ रखा। यह काम नहीं किया (न ही डीबी में मैनुअल प्रविष्टि के साथ)।

बाद में मैंने एन्कोडिंग = "utf-16" के साथ मैनुअल प्रविष्टि (सिर्फ INSERT INTO ...) लिखने की कोशिश की, जो भी विफल रही। पूरी तरह से काम किया एन्कोडिंग को हटाने के बाद। उस परिणाम के बाद मैंने स्ट्रिंगरिटर कोड और वॉइला में वापस स्विच किया - यह काम किया।

समस्या: मैं वास्तव में क्यों नहीं समझता।

क्रिश्चियन हेटर पर: उन परीक्षणों के साथ मुझे यकीन नहीं है कि मुझे DB-लिखने के लिए utf-16 का उपयोग करना होगा। तब UTF-16 (xml टैग में) को एन्कोडिंग सेट नहीं किया जाएगा?


1
मैं व्यक्तिगत अनुभव पर जा रहा हूं। SQL सर्वर केवल UTF-16 को स्वीकार करता है, और यदि आप इसे और कुछ भी पास करते हैं, तो आप SQL सर्वर XML पार्सर की दया पर हैं और डेटा को परिवर्तित करने का प्रयास करते हैं। इसे बेवकूफ बनाने का एक तरीका खोजने की कोशिश करने के बजाय, मैं इसे सीधे यूटीएफ -16 पास करता हूं, जो हमेशा काम करेगा।
क्रिश्चियन हैटर

आप इसे डेटाबेस में कैसे लिख रहे हैं? क्या आप इसे एक स्ट्रिंग, या बाइट्स की एक सरणी, या एक स्ट्रीम में लिख रहे हैं? यदि यह या तो बाद के दो रूपों में से है, तो आपको यह सुनिश्चित करने की आवश्यकता है कि आपका घोषित एन्कोडिंग आपके बाइनरी डेटा के वास्तविक एन्कोडिंग से मेल खाता है।
जॉन स्कीट

ओफ़्फ़। मैनुअल प्रयास मैंने MS SQL प्रबंधन स्टूडियो में क्वेरी के रूप में किया। "कोडित" कोशिशों को एक स्ट्रिंग के लिए लिखा गया था, जिसे बाद में एक ओ / आर मैपर में पारित किया गया था जो एक स्ट्रिंग के रूप में लिखते हैं (जहां तक ​​मैं पालन कर सकता था)। वास्तव में मैं इसे उस स्ट्रिंग से गुजार रहा हूं जो मेरे प्रश्न में दिए गए दो उदाहरणों में बनाई गई थी।
स्टैम्पडेक्स वीवी

FYI करें पाठकों के पास - डुप्लिकेट के पास: stackoverflow.com/questions/384974/… और stackoverflow.com/questions/3760788/…
zememer

1
मैं अपना स्वीकृत उत्तर बदल रहा हूं क्योंकि मेरा मानना ​​है कि यह वास्तव में मेरे प्रश्न का उत्तर देता है। भले ही अन्य उत्तर मुझे अपना काम जारी रखने में मदद कर रहे थे, लेकिन स्टाकेवरफ्लो के उद्देश्य से मुझे लगता है कि सुलैमान के उत्तर से दूसरों को बेहतर तरीके से समझने में मदद मिलेगी। [अस्वीकरण]: मुझे वास्तव में उत्तर को सत्यापित करने का समय नहीं मिला।
स्टैम्पडेक्स

जवाबों:


1

<TL; DR> समस्या वास्तव में सरल है, वास्तव में: आप इनपुट पैरामीटर के डेटाटाइप के साथ घोषित एन्कोडिंग (XML घोषणा में) का मिलान नहीं कर रहे हैं। यदि आपने मैन्युअल रूप <?xml version="1.0" encoding="utf-8"?><test/>से स्ट्रिंग में जोड़ा है, तो SqlParameterप्रकार की घोषणा करना SqlDbType.Xmlया SqlDbType.NVarCharआपको "एन्कोडिंग को स्विच करने में असमर्थ" त्रुटि देगा। तब, जब आप टी-एसक्यूएल के माध्यम से मैन्युअल रूप से सम्मिलित करते हैं, चूंकि आपने घोषित एन्कोडिंग को स्विच किया था utf-16, तो आप स्पष्ट रूप से एक VARCHARस्ट्रिंग डाल रहे थे (ऊपरी-मामले "एन" के साथ उपसर्ग नहीं किया गया था, इसलिए 8-बिट एन्कोडिंग, जैसे कि यूटीएफ -8) और नहीं एNVARCHAR स्ट्रिंग (एक ऊपरी-केस "एन" के साथ उपसर्ग किया गया, इसलिए 16-बिट UTF-16 LE एन्कोडिंग)।

यह फिक्स जितना सरल होना चाहिए था:

  1. पहले मामले में, जब घोषणा को बताते हुए कहते हैं encoding="utf-8": बस XML घोषणा को न जोड़ें।
  2. दूसरे मामले में, जब घोषणा को बताते हुए कहा encoding="utf-16": या तो
    1. बस एक्सएमएल घोषणा को जोड़ नहीं है, या
    2. बस इनपुट पैरामीटर प्रकार में एक "एन" जोड़ें: SqlDbType.NVarCharबजाय SqlDbType.VarChar:-) (या संभवतः भी उपयोग करने के लिए स्विच SqlDbType.Xml)

(विस्तृत प्रतिक्रिया नीचे है)


यहां सभी उत्तर अति-जटिल और अनावश्यक हैं (ईसाई और जॉन के जवाबों के लिए क्रमशः 121 और 184 वोटों की परवाह किए बिना)। वे कार्य कोड प्रदान कर सकते हैं, लेकिन उनमें से कोई भी वास्तव में सवाल का जवाब नहीं देता है। मुद्दा यह है कि कोई भी वास्तव में प्रश्न को नहीं समझ पाया है, जो कि आखिरकार SQL सर्वर में XML डेटाटाइप कैसे काम करता है। उन दो स्पष्ट रूप से बुद्धिमान लोगों के खिलाफ कुछ भी नहीं है, लेकिन इस सवाल का एक्सएमएल को क्रमबद्ध करने से कोई लेना-देना नहीं है। XML डेटा को SQL सर्वर में सहेजना यहाँ पर निहित होने की तुलना में बहुत आसान है।

यह वास्तव में कोई फर्क नहीं पड़ता कि जब तक आप SQL सर्वर में XML डेटा बनाने के नियमों का पालन करते हैं तब तक XML का उत्पादन कैसे किया जाता है। इस प्रश्न पर एक उत्तर में मेरे पास अधिक गहन स्पष्टीकरण है (नीचे उल्लिखित बिंदुओं को चित्रित करने के लिए कार्य उदाहरण कोड सहित): XML सर्वर को SQL सर्वर में सम्मिलित करते समय "एन्कोडिंग को स्विच करने में असमर्थ" त्रुटि को कैसे हल करें , लेकिन मूल बातें हैं:

  1. एक्सएमएल घोषणा वैकल्पिक है
  2. XML डेटाटाइप हमेशा UCS-2 / UTF-16 LE के रूप में तार संग्रहीत करता है
  3. यदि आपका XML UCS-2 / UTF-16 LE है, तो आप:
    1. NVARCHAR(MAX)या तो डेटा के रूप में पास करें या XML/ SqlDbType.NVarChar(अधिकतम = -1) या SqlDbType.Xml, या यदि एक स्ट्रिंग शाब्दिक का उपयोग कर रहे हैं तो इसे ऊपरी-मामले "एन" के साथ उपसर्ग करना होगा।
    2. यदि XML घोषणा को निर्दिष्ट किया जाता है, तो यह "UCS-2" या "UTF-16" होना चाहिए (यहां कोई वास्तविक अंतर नहीं है)
  4. यदि आपका XML 8-बिट एनकोडेड है (जैसे "UTF-8" / "iso-8859-1" / "Windows-1252"), तो आप:
    1. XML घोषणा को निर्दिष्ट करने की आवश्यकता है यदि एन्कोडिंग डेटाबेस के डिफ़ॉल्ट Collation द्वारा निर्दिष्ट कोड पृष्ठ से अलग है
    2. आपको डेटा को VARCHAR(MAX)/ SqlDbType.VarChar(अधिकतम -१ =) के रूप में पास करना होगा , या यदि एक स्ट्रिंग शाब्दिक का उपयोग करना है, तो इसे ऊपरी-केस "एन" के साथ उपसर्ग नहीं करना चाहिए ।
    3. जो भी 8-बिट एन्कोडिंग का उपयोग किया जाता है, एक्सएमएल घोषणा में उल्लेखित "एन्कोडिंग" बाइट्स के वास्तविक एन्कोडिंग से मेल खाना चाहिए।
    4. 8-बिट एन्कोडिंग को XML डेटाटाइप द्वारा UTF-16 LE में परिवर्तित किया जाएगा

मन में ऊपर उल्लिखित बिंदुओं के साथ, और .NET में तार हमेशा UTF-16 LE / UCS-2 LE होते हैं (एन्कोडिंग के संदर्भ में उन लोगों के बीच कोई अंतर नहीं है), हम आपके सवालों का जवाब दे सकते हैं:

वहाँ एक कारण है कि मैं एक वस्तु को क्रमबद्ध करने के लिए स्ट्रिंगराइटर का उपयोग नहीं करना चाहिए जब मुझे बाद में स्ट्रिंग के रूप में इसकी आवश्यकता होती है?

नहीं, आपका StringWriterकोड ठीक प्रतीत होता है (कम से कम मुझे सवाल से 2 कोड ब्लॉक का उपयोग करके अपने सीमित परीक्षण में कोई समस्या नहीं दिखती है)।

तब UTF-16 (xml टैग में) को एन्कोडिंग सेट नहीं किया जाएगा?

XML घोषणा प्रदान करना आवश्यक नहीं है। यदि यह अनुपलब्ध है, तो एन्कोडिंग को UTF-16 LE माना जाता है यदि आप स्ट्रिंग को SQL सर्वर में NVARCHAR(जैसे SqlDbType.NVarChar) या XML(यानी SqlDbType.Xml) पास करते हैं। एन्कोडिंग को डिफ़ॉल्ट 8-बिट कोड पृष्ठ माना जाता है यदि वह VARCHAR(यानी SqlDbType.VarChar) में गुजर रहा है । यदि आपके पास कोई गैर-मानक-एएससीआईआई अक्षर हैं (अर्थात मान 128 और उससे अधिक) और जैसे-जैसे गुजर रहे हैं VARCHAR, तो आप "" की संभावना करेंगे? BMP वर्ण और "??" के लिए SQL सर्वर के रूप में पूरक वर्णों के लिए UTF-16 / UCS-2 में वापस परिवर्तित करने से पहले SQL सर्वर UTF-16 स्ट्रिंग को .NET से वर्तमान डेटाबेस के कोड पेज के 8-बिट स्ट्रिंग में बदल देगा। लेकिन आपको कोई त्रुटि नहीं मिलनी चाहिए।

दूसरी ओर, यदि आप एक्सएमएल घोषणा को निर्दिष्ट करते हैं, तो आपको 8-बिट या 16-बिट डेटाटाइप का उपयोग करके SQL सर्वर में पास होना चाहिए । इसलिए यदि आपके पास यह घोषणा है कि एन्कोडिंग यूसीएस -2 या यूटीएफ -16 है, तो आपको या में पास होना चाहिए । या, यदि आप एक घोषणा करते हुए कहा कि एन्कोडिंग 8 बिट विकल्पों में से एक (यानी है अगर , , , आदि) है, तो आप चाहिए के रूप में में पारित । उचित 8 या 16-बिट एसक्यूएल सर्वर डेटाटाइप के साथ घोषित एन्कोडिंग से मेल करने में विफलता के परिणामस्वरूप "एन्कोडिंग को स्विच करने में असमर्थ" त्रुटि होगी जो आपको मिल रही थी।SqlDbType.NVarCharSqlDbType.XmlUTF-8Windows-1252iso-8859-1SqlDbType.VarChar

उदाहरण के लिए, आपके- StringWriterआधारित सीरियल कोड का उपयोग करते हुए , मैंने बस XML के परिणामी स्ट्रिंग को प्रिंट किया और SSMS में इसका उपयोग किया। आप नीचे देख सकते हैं, XML घोषणा शामिल है (क्योंकि StringWriterके लिए एक विकल्प नहीं है OmitXmlDeclarationकी तरह XmlWriterहै, जो इतने लंबे समय के रूप में आप सही एसक्यूएल सर्वर डेटाप्रकार के रूप में स्ट्रिंग पारित नहीं समस्या बन गया है करता है):

-- Upper-case "N" prefix == NVARCHAR, hence no error:
DECLARE @Xml XML = N'<?xml version="1.0" encoding="utf-16"?>
<string>Test ሴ😸</string>';
SELECT @Xml;
-- <string>Test ሴ😸</string>

जैसा कि आप देख सकते हैं, यह मानक ASCII से परे वर्णों को भी संभालता है, यह देखते हुए कि BMP कोड प्वाइंट U + 1234 है, और 😸पूरक चरित्र कोड प्वाइंट U + 1F638 है। हालांकि, निम्नलिखित:

-- No upper-case "N" prefix on the string literal, hence VARCHAR:
DECLARE @Xml XML = '<?xml version="1.0" encoding="utf-16"?>
<string>Test ሴ😸</string>';

निम्नलिखित त्रुटि के परिणाम:

Msg 9402, Level 16, State 1, Line XXXXX
XML parsing: line 1, character 39, unable to switch the encoding

एर्गो, उस स्पष्टीकरण के सभी एक तरफ, आपके मूल प्रश्न का पूर्ण समाधान है:

आप स्पष्ट रूप से स्ट्रिंग को पास कर रहे थे SqlDbType.VarChar। स्विच करें SqlDbType.NVarCharऔर यह XML घोषणा को हटाने के अतिरिक्त चरण के माध्यम से जाने की आवश्यकता के बिना काम करेगा। यह SqlDbType.VarCharXML घोषणा को रखने और हटाने से अधिक पसंद किया जाता है क्योंकि यह समाधान डेटा हानि को रोक देगा जब XML में गैर-मानक-ASCII वर्ण शामिल होते हैं। उदाहरण के लिए:

-- No upper-case "N" prefix on the string literal == VARCHAR, and no XML declaration:
DECLARE @Xml2 XML = '<string>Test ሴ😸</string>';
SELECT @Xml2;
-- <string>Test ???</string>

जैसा कि आप देख सकते हैं, इस बार कोई त्रुटि नहीं है, लेकिन अब डेटा-लॉस है।


मुझे लगता है कि मैं इस अतिरंजित उत्तरों का कारण था, क्योंकि मूल रूप से एक में दो प्रश्न थे। मैं वास्तव में आपके संक्षिप्त उत्तर को पसंद करता हूं और अगली बार यह कोशिश करूंगा कि मुझे XML को DB में स्टोर करना होगा। इसलिए अगर मुझे यह अधिकार दिखाई देता है: आपने XML को DB में संग्रहीत करने के साथ चुनौतियों को समझाया। एक्सएम (यूटीएफ -16 को छोड़कर) और क्रिश्चियन हेटर के साथ काम करने के दौरान जॉन स्केटर ने स्टिंगरव्यूटर का उपयोग करने के साथ समरइज़्ड मुद्दों को प्रस्तुत किया और इसके साथ काम करने का एक अच्छा तरीका प्रदान किया।
स्टैम्पडेक्स

@StampedeXV मैंने अपना उत्तर (स्पष्टता के लिए कुछ बदलाव + नए सामान को बेहतर ढंग से बताने के लिए कुछ बिंदुओं) को अपडेट किया। उम्मीद है कि अब यह स्पष्ट हो गया है कि जबकि वे दोनों उत्तर अपने आप में अच्छे हैं, वे आपके प्रश्न का उत्तर देने के लिए किसी भी तरह से आवश्यक नहीं हैं। वे C # / .NET में XML क्रमांकन के साथ सौदा करते हैं, लेकिन यह सवाल वास्तव में XML को SQL सर्वर में सहेजने के बारे में है। वे जानकारी प्रदान करते हैं जो जानना अच्छा है, और मूल रूप से आपके द्वारा प्रदान किए गए कोड से बेहतर हो सकता है, लेकिन उनमें से कोई भी (और यहां कोई भी नहीं) सही मायने में विषय है। लेकिन यह अच्छी तरह से प्रलेखित सामान नहीं है, इसलिए भ्रम है।
सोलोमन रटज़की

@StampedeXV क्या मेरे संशोधन समझ में आए? मैंने अभी शीर्ष पर एक सारांश अनुभाग जोड़ा है जो स्पष्ट हो सकता है। लंबी कहानी छोटी: जब तक कुछ और चल रहा था, जिसमें आपने प्रश्न का विवरण शामिल नहीं किया था, तब ऐसा लगता है कि आपका कोड 99% सही था, और संभवत: एक एकल ऊपरी मामले के अतिरिक्त के साथ तय किया जा सकता था " एन "। कोई विशेष एन्कोडिंग सामान की आवश्यकता नहीं है, और ईसाई का कोड अच्छा है, लेकिन मेरे परीक्षण से पता चलता है कि यह क्रमबद्धता आपके 2 कोड ब्लॉक के समान है, सिवाय आपके एक्सएमएल घोषणा के बाद आपका सीआरएलएफ डालता है। मुझे यकीन है कि आप बदल गए SqlDbType.NVarCharया Xml
सोलोमन रटज़की ने

अभी भी खुद को जांचने का समय खोजने की कोशिश कर रहा है। यह निश्चित रूप से अच्छा और तार्किक लगता है, लेकिन सुनिश्चित नहीं है कि एक स्वीकृत उत्तर को बदलने के लिए पर्याप्त होगा।
स्टैम्पडेक्स

216

इसके साथ एक समस्या यहStringWriter है कि डिफ़ॉल्ट रूप से यह आपको एन्कोडिंग सेट नहीं करने देता है जो इसे विज्ञापित करता है - इसलिए आप एक XML दस्तावेज़ के साथ इसकी एन्कोडिंग को UTF-16 के रूप में विज्ञापन कर सकते हैं, जिसका अर्थ है कि आपको इसे UTF-16 के रूप में एन्कोड करना होगा यदि आप इसे एक फ़ाइल में लिखें। मेरे पास हालांकि इसके साथ मदद करने के लिए एक छोटा वर्ग है:

public sealed class StringWriterWithEncoding : StringWriter
{
    public override Encoding Encoding { get; }

    public StringWriterWithEncoding (Encoding encoding)
    {
        Encoding = encoding;
    }    
}

या अगर आपको केवल UTF-8 की आवश्यकता है (जो कि मुझे अक्सर चाहिए):

public sealed class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding => Encoding.UTF8;
}

जैसे आप डेटाबेस के लिए अपने XML को क्यों नहीं बचा सके - आपको हमें इस बारे में अधिक जानकारी देनी होगी कि आपने क्या किया, यदि आप चाहते हैं कि हम इसका निदान / निर्धारण कर सकें।


मैं अब डेटाबेस समस्या के लिए और अधिक विस्तार में चला गया। प्रश्न देखें।
स्टैम्पडेक्स वीवी

4
सैड StringWriterएन्कोडिंग को ध्यान में नहीं रखता है, लेकिन कभी भी कम नहीं होता है, एक निफ्टी के लिए धन्यवाद थोड़ा सा तरीका :)
चौ

2
और "XML पार्सिंग: लाइन 1, चरित्र 38, एन्कोडिंग को स्विच करने में असमर्थ" को "settings.Indent = false; settings.OmitXmlDeclaration = false;" द्वारा हल किया जा सकता है।
MGE

मैं आमतौर पर सही एन्कोडिंग के साथ MemoryStreamऔर ए का उपयोग करके इसके चारों ओर मिलता हूं StreamWriterStreamWriter है एक TextWriter(प्रकार है जो XmlWriter.Createउम्मीद है) अनुकूलन एन्कोडिंग के साथ, सब के बाद।
Nyerguds

2
@ नायरगुड्स: तो इस तरह की चीज़ के साथ एक नगेट पैकेज बनाएं, फिर इसे प्राप्त करना हमेशा आसान होता है। मैं इसके बजाय कोड की पठनीयता से समझौता करना चाहता हूं जो कि मूलभूत रूप से किसी अन्य आवश्यकता के बारे में है।
जॉन स्कीट

126

.NET डॉक्यूमेंट में XML डॉक्यूमेंट को क्रमबद्ध करते समय, एन्कोडिंग को UTF-16 पर सेट किया जाना चाहिए। आंतरिक रूप से स्ट्रिंग्स को UTF-16 के रूप में संग्रहीत किया जाता है, इसलिए यह एकमात्र एन्कोडिंग है जो समझ में आता है। यदि आप डेटा को एक अलग एन्कोडिंग में संग्रहीत करना चाहते हैं, तो आप इसके बजाय एक बाइट सरणी का उपयोग करते हैं।

SQL सर्वर एक समान सिद्धांत पर काम करता है; किसी भी तार को एक xmlकॉलम में पारित किया जाना चाहिए जिसे UTF-16 के रूप में एन्कोड किया जाना चाहिए। SQL सर्वर किसी भी स्ट्रिंग को अस्वीकार कर देगा जहां XML घोषणा UTF-16 निर्दिष्ट नहीं करती है। यदि एक्सएमएल घोषणा मौजूद नहीं है, तो एक्सएमएल मानक की आवश्यकता होती है कि यह यूटीएफ -8 के लिए डिफ़ॉल्ट है, इसलिए एसक्यूएल सर्वर भी इसे अस्वीकार कर देगा।

इसे ध्यान में रखते हुए, रूपांतरण करने के लिए यहाँ कुछ उपयोगिता विधियाँ दी गई हैं।

public static string Serialize<T>(T value) {

    if(value == null) {
        return null;
    }

    XmlSerializer serializer = new XmlSerializer(typeof(T));

    XmlWriterSettings settings = new XmlWriterSettings()
    {
        Encoding = new UnicodeEncoding(false, false), // no BOM in a .NET string
        Indent = false,
        OmitXmlDeclaration = false
    };

    using(StringWriter textWriter = new StringWriter()) {
        using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
            serializer.Serialize(xmlWriter, value);
        }
        return textWriter.ToString();
    }
}

public static T Deserialize<T>(string xml) {

    if(string.IsNullOrEmpty(xml)) {
        return default(T);
    }

    XmlSerializer serializer = new XmlSerializer(typeof(T));

    XmlReaderSettings settings = new XmlReaderSettings();
    // No settings need modifying here

    using(StringReader textReader = new StringReader(xml)) {
        using(XmlReader xmlReader = XmlReader.Create(textReader, settings)) {
            return (T) serializer.Deserialize(xmlReader);
        }
    }
}

प्रश्न जोड़ देखें मुझे अपने परीक्षा परिणामों की समझ नहीं है, यह आपके कथन का खंडन करता प्रतीत होता है कि DB हमेशा UTF-16 चाहता / लेता है / चाहता है।
स्टैम्पडेक्स वीवी

9
आपको UTF-16 के रूप में सांकेतिक शब्दों में बदलना नहीं है - लेकिन आपको यह सुनिश्चित करना होगा कि आपके द्वारा उपयोग की जाने वाली एन्कोडिंग क्या StringWriterअपेक्षाओं से मेल खाती है। मेरा जवाब देखिए। आंतरिक भंडारण प्रारूप यहाँ अप्रासंगिक है।
जॉन स्कीट

ठीक है कि मैं समझता हूँ मेरे नए उदाहरण में: एन्कोडिंग को पूरी तरह से छोड़ने से डीबी ने खुद तय किया कि कौन सा एन्कोडिंग इस्तेमाल किया गया था - यही कारण है कि यह काम किया। क्या मैं इसे अभी ठीक से समझता हूं?
स्टैम्पडेक्स वी

1
@SteveC: क्षमा करें, मेरी गलती है। मैंने VB से कोड को हाथ से परिवर्तित किया है, जिसमें Nothingकिसी भी प्रकार से स्पष्ट रूप से परिवर्तनीय है। मैंने Deserializeकोड सही कर दिया है । Serializeचेतावनी एक Resharper-केवल एक चीज है, अपने स्वयं के आपत्ति नहीं है पर संकलक होना चाहिए और यह करने के लिए कानूनी है।
क्रिश्चियन हैटर

1
जॉन स्कीट की टिप्पणी पर विस्तार से, नहीं, यूटीएफ -16 की आवश्यकता नहीं है। इसे प्रदर्शित करने वाले एक ठोस उदाहरण के लिए कृपया stackoverflow.com/a/8998183/751158 देखें ।
zememer

20

सबसे पहले, पुराने उदाहरण खोजने से सावधान रहें। आपने एक का उपयोग किया है XmlTextWriter, जिसे .NET 2.0 के रूप में दर्शाया गया है। XmlWriter.Createइसके बजाय उपयोग किया जाना चाहिए।

यहाँ एक वस्तु को XML स्तंभ में क्रमबद्ध करने का एक उदाहरण दिया गया है:

public void SerializeToXmlColumn(object obj)
{
    using (var outputStream = new MemoryStream())
    {
        using (var writer = XmlWriter.Create(outputStream))
        {
            var serializer = new XmlSerializer(obj.GetType());
            serializer.Serialize(writer, obj);
        }

        outputStream.Position = 0;
        using (var conn = new SqlConnection(Settings.Default.ConnectionString))
        {
            conn.Open();

            const string INSERT_COMMAND = @"INSERT INTO XmlStore (Data) VALUES (@Data)";
            using (var cmd = new SqlCommand(INSERT_COMMAND, conn))
            {
                using (var reader = XmlReader.Create(outputStream))
                {
                    var xml = new SqlXml(reader);

                    cmd.Parameters.Clear();
                    cmd.Parameters.AddWithValue("@Data", xml);
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
}

2
मैं इसे केवल एक बार वोट कर सकता हूं, लेकिन यह यहां शीर्ष उत्तर देने के योग्य है। अंत में, इससे कोई फर्क नहीं पड़ता कि एन्कोडिंग घोषित है या इसका उपयोग किया जाता है, जब तक कि XmlReaderइसे पार्स कर सकते हैं। इसे डेटाबेस में प्री-पार्स भेजा जाएगा, और फिर DB को चरित्र एनकोडिंग - UTF-16 या अन्यथा के बारे में कुछ भी जानने की आवश्यकता नहीं है। विशेष रूप से, ध्यान दें कि XML घोषणाएँ डेटाबेस में डेटा के साथ भी बनी नहीं हैं, भले ही इसे डालने के लिए किस पद्धति का उपयोग किया जाता है। कृपया अतिरिक्त रूपांतरणों के माध्यम से XML चलाकर बर्बाद न करें, जैसा कि अन्य उत्तरों में दिखाया गया है।
ज़ेसेमर २५'१२ को ४:५०

1
public static T DeserializeFromXml<T>(string xml)
{
    T result;
    XmlSerializerFactory serializerFactory = new XmlSerializerFactory();
    XmlSerializer serializer =serializerFactory.CreateSerializer(typeof(T));

    using (StringReader sr3 = new StringReader(xml))
    {
        XmlReaderSettings settings = new XmlReaderSettings()
        {
            CheckCharacters = false // default value is true;
        };

        using (XmlReader xr3 = XmlTextReader.Create(sr3, settings))
        {
            result = (T)serializer.Deserialize(xr3);
        }
    }

    return result;
}

-1

यह कहीं और कवर किया गया हो सकता है, लेकिन XML स्रोत की एन्कोडिंग लाइन को 'utf-16' में बदलने से XML को SQL सर्वर 'xml'data' प्रकार में डाला जा सकता है।

using (DataSetTableAdapters.SQSTableAdapter tbl_SQS = new DataSetTableAdapters.SQSTableAdapter())
{
    try
    {
        bodyXML = @"<?xml version="1.0" encoding="UTF-8" standalone="yes"?><test></test>";
        bodyXMLutf16 = bodyXML.Replace("UTF-8", "UTF-16");
        tbl_SQS.Insert(messageID, receiptHandle, md5OfBody, bodyXMLutf16, sourceType);
    }
    catch (System.Data.SqlClient.SqlException ex)
    {
        Console.WriteLine(ex.Message);
        Console.ReadLine();
    }
}

परिणाम सभी XML पाठ में 'xml' डेटा प्रकार फ़ील्ड में डाला जाता है, लेकिन 'हेडर' लाइन हटा दी जाती है। परिणामी रिकॉर्ड में आप जो देख रहे हैं वह सिर्फ है

<test></test>

"आंसर की" प्रविष्टि में वर्णित धारावाहिक पद्धति का उपयोग करना लक्ष्य फ़ील्ड में मूल शीर्षलेख शामिल करने का एक तरीका है, लेकिन इसका परिणाम यह है कि शेष XML पाठ एक XML <string></string>टैग में संलग्न है ।

कोड में टेबल एडेप्टर विजुअल स्टूडियो 2013 का उपयोग करके स्वचालित रूप से बनाया गया एक वर्ग है "नया डेटा स्रोत जोड़ें: विज़ार्ड। SQL सर्वर तालिका में फ़ील्ड के लिए सम्मिलित करने के लिए पाँच पैरामीटर मैप करें।


2
बदलने के? यह उल्लासपूर्ण है।
mgilberties

2
गंभीरता से - यह मत करो। कभी। क्या होगा अगर मैं अपने xml में कुछ गद्य को शामिल करना चाहता था जिसमें "UTF-8" का उल्लेख किया गया था - आपने अभी-अभी मेरा डेटा कुछ ऐसा कहा है जो मैंने नहीं कहा था!
टिम एबेल

2
कोड में एक गलती को इंगित करने के लिए धन्यवाद। BodyXML.Replace ("UTF-8", "UTF-16") के बजाय ऐसा कोड होना चाहिए जो XML हेडर को UTF-8 से UTF-16 में बदलने पर केंद्रित हो। क्या मैं वास्तव में इंगित करने की कोशिश कर रहा था स्रोत एक्सएमएल के हेडर में यह बदलाव करके, फिर एक्सएमएल के शरीर को एक्सएमएल डेटा टाइप फ़ील्ड का उपयोग करके SQL टेबल रिकॉर्ड में डाला जा सकता है और हेडर को छीन लिया जाता है। जिन कारणों से मुझे अब याद नहीं है (चार साल पहले!) परिणाम उस समय कुछ उपयोगी था। और हाँ, 'बदलें' का उपयोग करते हुए गूंगा गलती। होता है।
DLG
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.