Câu hỏi này gần như trùng lặp với 2 câu hỏi khác và thật ngạc nhiên - trong khi câu hỏi này là câu hỏi gần đây nhất - tôi tin rằng nó thiếu câu trả lời tốt nhất.
Các bản sao và những gì tôi tin là câu trả lời tốt nhất của họ, là:
- Sử dụng StringWriter để tuần tự hóa XML (2009-10-14)
- https://stackoverflow.com/a/1566154/751158
- Cố gắng lưu trữ nội dung XML vào SQL Server 2005 không thành công (sự cố mã hóa) (2008-12-21)
- https://stackoverflow.com/a/1091209/751158
Cuối cùng, không có vấn đề gì về mã hóa được khai báo hoặc sử dụng, miễn là XmlReader
có thể phân tích cú pháp cục bộ trong máy chủ ứng dụng.
Như đã được xác nhận trong Cách hiệu quả nhất để đọc XML trong ADO.net từ cột kiểu XML trong máy chủ SQL ?, Máy chủ SQL lưu trữ XML ở định dạng nhị phân hiệu quả. Bằng cách sử dụng SqlXml
lớp, ADO.net có thể giao tiếp với SQL Server ở định dạng nhị phân này và không yêu cầu máy chủ cơ sở dữ liệu thực hiện bất kỳ tuần tự hóa hoặc hủy tuần tự hóa nào của XML. Điều này cũng sẽ hiệu quả hơn cho việc vận chuyển trên mạng.
Bằng cách sử dụng SqlXml
, XML sẽ được gửi trước phân tích cú pháp đến cơ sở dữ liệu và sau đó DB không cần biết bất kỳ điều gì về mã hóa ký tự - UTF-16 hoặc cách khác. Đặc biệt, lưu ý rằng các khai báo XML thậm chí không được duy trì với dữ liệu trong cơ sở dữ liệu, bất kể phương pháp nào được sử dụng để chèn nó.
Vui lòng tham khảo các câu trả lời được liên kết ở trên để biết các phương pháp trông rất giống với phương pháp này, nhưng ví dụ này là của tôi:
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();
}
}
}
}
Lưu ý rằng tôi sẽ không coi ví dụ cuối cùng (không được bình luận) là "sẵn sàng sản xuất", nhưng để nguyên như vậy để ngắn gọn và dễ đọc. Nếu được thực hiện đúng cách, cả StringReader
và XmlReader
đã tạo nên được khởi tạo trong using
các câu lệnh để đảm bảo rằng Close()
của chúng các phương thức được gọi khi hoàn tất.
Từ những gì tôi đã thấy, các khai báo XML không bao giờ tồn tại khi sử dụng một cột XML. Ví dụ:ngay cả khi không sử dụng .NET và chỉ sử dụng câu lệnh chèn SQL trực tiếp này, khai báo XML không được lưu vào cơ sở dữ liệu với XML:
Insert Into TestData(Xml) Values ('<?xml version="1.0" encoding="UTF-8"?><Test/>');
Bây giờ theo câu hỏi của OP, đối tượng được tuần tự hóa vẫn cần được chuyển đổi thành cấu trúc XML từ MyMessage
đối tượng và XmlSerializer
vẫn cần thiết cho việc này. Tuy nhiên, tệ nhất là thay vì tuần tự hóa thành một chuỗi, thư thay vào đó có thể được tuần tự hóa thành một XmlDocument
- sau đó có thể được chuyển tới SqlXml
thông qua XmlNodeReader
mới - tránh một chuyến đi hủy tuần tự hóa / tuần tự hóa thành một chuỗi. (Xem http://blogs.msdn.com/b/jongallant/archive/2007/01/30/how-to-convert-xmldocument-to-xmlreader-for-sqlxml-data-type.aspx để biết thêm chi tiết và ví dụ .)
Mọi thứ ở đây đều được phát triển và thử nghiệm với .NET 4.0 và SQL Server 2008 R2.
Xin đừng lãng phí bằng cách chạy XML thông qua các chuyển đổi bổ sung (de-deserializations và serializations - thành DOM, chuỗi hoặc cách khác), như được hiển thị trong các câu trả lời khác ở đây và ở những nơi khác.