sql >> データベース >  >> RDS >> Sqlserver

XMLをSQLServerに挿入するときにエンコードエラーを切り替えることができない問題を解決する方法

    この質問は他の2つの質問とほぼ重複していますが、驚くべきことに、これは最新の質問ですが、最良の答えが欠けていると思います。

    重複、およびそれらの最良の答えであると私が信じているものは次のとおりです。

    • XMLシリアル化のためのStringWriterの使用(2009-10-14)
      • https://stackoverflow.com/a/1566154/751158
    • XMLコンテンツをSQLServer2005に保存しようとすると失敗します(エンコードの問題)(2008-12-21)
      • https://stackoverflow.com/a/1091209/751158

    結局、XmlReaderである限り、どのエンコーディングが宣言または使用されているかは問題ではありません。 アプリケーションサーバー内でローカルに解析できます。

    SQL ServerのXMLタイプ列からADO.netのXMLを読み取る最も効率的な方法で確認されたように、SQLServerはXMLを効率的なバイナリ形式で格納します。 SqlXmlを使用する クラス、ADO.netはこのバイナリ形式でSQL Serverと通信でき、データベースサーバーがXMLのシリアル化または逆シリアル化を行う必要はありません。これは、ネットワークを介した転送にも効率的です。

    SqlXmlを使用する 、XMLは事前に解析されてデータベースに送信されるため、DBは文字エンコード(UTF-16など)について何も知る必要がありません。特に、XML宣言は、データの挿入に使用されているメソッドに関係なく、データベース内のデータで永続化されないことに注意してください。

    これに非常によく似た方法については、上記のリンクされた回答を参照してください。ただし、この例は私のものです:

    using System.Data;
    using System.Data.SqlClient;
    using System.Data.SqlTypes;
    using System.IO;
    using System.Xml;
    
    static class XmlDemo {
        static void Main(string[] args) {
            using(SqlConnection conn = new SqlConnection()) {
                conn.ConnectionString = "...";
                conn.Open();
    
                using(SqlCommand cmd = new SqlCommand("Insert Into TestData(Xml) Values (@Xml)", conn)) {
    
                    cmd.Parameters.Add(new SqlParameter("@Xml", SqlDbType.Xml) {
                        // Works.
                        // Value = "<Test/>"
    
                        // Works.  XML Declaration is not persisted!
                        // Value = "<?xml version=\"1.0\"?><Test/>"
    
                        // Works.  XML Declaration is not persisted!
                        // Value = "<?xml version=\"1.0\" encoding=\"UTF-16\"?><Test/>"
    
                        // Error ("unable to switch the encoding" SqlException).
                        // Value = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Test/>"
    
                        // Works.  XML Declaration is not persisted!
                        Value = new SqlXml(XmlReader.Create(new StringReader("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Test/>")))
                    });
    
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
    

    最後の(コメントされていない)例を「本番環境対応」とは見なさないことに注意してください。ただし、簡潔で読みやすいようにそのままにしておきます。適切に行われた場合、両方のStringReader 作成されたXmlReader using内で初期化する必要があります Close()を確実にするステートメント メソッドは完了すると呼び出されます。

    私が見たところ、XML列を使用する場合、XML宣言は永続化されません。たとえば、.NETを使用せず、この直接SQL挿入ステートメントを使用した場合でも、XML宣言はXMLとともにデータベースに保存されません。

    Insert Into TestData(Xml) Values ('<?xml version="1.0" encoding="UTF-8"?><Test/>');
    

    OPの質問に関しては、シリアル化するオブジェクトをMyMessageからXML構造に変換する必要があります。 オブジェクト、およびXmlSerializer これにはまだ必要です。ただし、最悪の場合、文字列にシリアル化する代わりに、メッセージをXmlDocumentにシリアル化することができます。 -これをSqlXmlに渡すことができます 新しいXmlNodeReaderを介して -文字列への逆シリアル化/シリアル化トリップを回避します。 (詳細と例については、http://blogs.msdn.com/b/jongallant/archive/2007/01/30/how-to-convert-xmldocument-to-xmlreader-for-sqlxml-data-type.aspxを参照してください。 。)

    ここにあるものはすべて、.NET4.0およびSQLServer 2008 R2に対して開発され、テストされています。

    無駄にしないでください ここや他の場所で他の回答に示されているように、追加の変換(逆シリアル化とシリアル化-DOM、文字列など)を介してXMLを実行する。



    1. MySQL-SELECT WHEREフィールドIN(サブクエリ)-非常に遅い理由

    2. マイニングプラン:プランキャッシュだけではありません

    3. MariaDBで月末を取得する方法

    4. Ubuntuにsqlcmd&bcpをインストールする方法