Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Bagaimana mengatasi tidak dapat mengganti kesalahan penyandian saat memasukkan XML ke SQL Server

Pertanyaan ini hampir merupakan duplikat dari 2 pertanyaan lainnya, dan yang mengejutkan - meskipun ini adalah yang terbaru - saya yakin ini tidak memiliki jawaban terbaik.

Duplikatnya, dan apa yang saya yakini sebagai jawaban terbaik mereka, adalah:

  • Menggunakan StringWriter untuk Serialisasi XML (2009-10-14)
    • https://stackoverflow.com/a/1566154/751158
  • Mencoba menyimpan konten XML ke SQL Server 2005 gagal (masalah penyandian) (2008-12-21)
    • https://stackoverflow.com/a/1091209/751158

Pada akhirnya, tidak masalah pengkodean apa yang dideklarasikan atau digunakan, selama XmlReader dapat menguraikannya secara lokal di dalam server aplikasi.

Seperti yang telah dikonfirmasi dalam Cara paling efisien untuk membaca XML di ADO.net dari kolom tipe XML di SQL server?, SQL Server menyimpan XML dalam format biner yang efisien. Dengan menggunakan SqlXml kelas, ADO.net dapat berkomunikasi dengan SQL Server dalam format biner ini, dan tidak memerlukan server database untuk melakukan serialisasi atau de-serialisasi XML. Ini juga harus lebih efisien untuk transportasi di seluruh jaringan.

Dengan menggunakan SqlXml , XML akan dikirim pra-parsing ke database, dan kemudian DB tidak perlu tahu apa-apa tentang pengkodean karakter - UTF-16 atau sebaliknya. Secara khusus, perhatikan bahwa deklarasi XML bahkan tidak dipertahankan dengan data dalam database, terlepas dari metode mana yang digunakan untuk menyisipkannya.

Silakan merujuk ke jawaban yang ditautkan di atas untuk metode yang terlihat sangat mirip dengan ini, tetapi contoh ini adalah milik saya:

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();
            }
        }
    }
}

Perhatikan bahwa saya tidak akan menganggap contoh terakhir (tidak dikomentari) sebagai "siap produksi", tetapi membiarkannya apa adanya agar ringkas dan mudah dibaca. Jika dilakukan dengan benar, baik StringReader dan XmlReader yang dibuat harus diinisialisasi dalam using pernyataan untuk memastikan bahwa Close() metode dipanggil setelah selesai.

Dari apa yang saya lihat, deklarasi XML tidak pernah bertahan saat menggunakan kolom XML. Bahkan tanpa menggunakan .NET dan hanya menggunakan pernyataan penyisipan SQL langsung ini, misalnya, deklarasi XML tidak disimpan ke dalam database dengan XML:

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

Sekarang dalam hal pertanyaan OP, objek yang akan diserialisasi masih perlu diubah menjadi struktur XML dari MyMessage objek, dan XmlSerializer masih dibutuhkan untuk ini. Namun, paling buruk, alih-alih membuat serial ke String, pesan malah bisa menjadi serial ke XmlDocument - yang kemudian dapat diteruskan ke SqlXml melalui XmlNodeReader baru - menghindari perjalanan de-serialisasi/seri ke string. (Lihat http://blogs.msdn.com/b/jongallant/archive/2007/01/30/how-to-convert-xmldocument-to-xmlreader-for-sqlxml-data-type.aspx untuk detail dan contoh .)

Semuanya di sini dikembangkan dan diuji dengan .NET 4.0 dan SQL Server 2008 R2.

Tolong jangan buang sampah dengan menjalankan XML melalui konversi ekstra (de-deserialisasi dan serialisasi - ke DOM, string, atau lainnya), seperti yang ditunjukkan dalam jawaban lain di sini dan di tempat lain.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Solusi untuk:Simpan pembaruan, sisipkan, atau hapus pernyataan yang memengaruhi jumlah baris yang tidak terduga (0)

  2. Tambahkan Langkah Pekerjaan ke Pekerjaan Agen Server SQL yang Ada (T-SQL)

  3. Kembalikan Nama Server Lokal di SQL Server dengan @@SERVERNAME

  4. Bagaimana menemukan semua dependensi tabel di sql server

  5. Grup SQL Server berdasarkan Hitungan DateTime Per Jam?