To pytanie jest prawie duplikatem 2 innych i co zaskakujące – chociaż to jest najnowsze – uważam, że brakuje mu najlepszej odpowiedzi.
Duplikaty i to, co uważam za ich najlepsze odpowiedzi, to:
- Używanie StringWriter do serializacji XML (2009-10-14)
- https://stackoverflow.com/a/1566154/751158
- Próba przechowywania zawartości XML w SQL Server 2005 kończy się niepowodzeniem (problem z kodowaniem) (2008-12-21)
- https://stackoverflow.com/a/1091209/751158
W końcu nie ma znaczenia, jakie kodowanie jest zadeklarowane lub użyte, o ile XmlReader
może analizować je lokalnie na serwerze aplikacji.
Jak zostało potwierdzone w Najbardziej efektywny sposób odczytywania XML w ADO.net z kolumny typu XML w serwerze SQL?, SQL Server przechowuje XML w wydajnym formacie binarnym. Używając SqlXml
klasy, ADO.net może komunikować się z SQL Server w tym formacie binarnym i nie wymaga od serwera bazy danych wykonywania jakiejkolwiek serializacji lub deserializacji XML. Powinno to być również bardziej wydajne w przypadku transportu w sieci.
Używając SqlXml
, XML zostanie przesłany do bazy danych wstępnie przeanalizowany, a następnie DB nie musi nic wiedzieć o kodowaniu znaków - UTF-16 lub innym. W szczególności zauważ, że deklaracje XML nie są nawet utrwalane z danymi w bazie danych, niezależnie od metody użytej do ich wstawienia.
Proszę odnieść się do powyższych odpowiedzi dla metod, które wyglądają bardzo podobnie do tego, ale ten przykład jest mój:
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();
}
}
}
}
Zauważ, że nie uważam ostatniego (nie komentowanego) przykładu za „gotowy do produkcji”, ale zostawiłem go tak, aby był zwięzły i czytelny. Jeśli zrobisz to poprawnie, oba StringReader
i utworzony XmlReader
powinien być zainicjowany w using
instrukcji, aby upewnić się, że ich Close()
metody są wywoływane po zakończeniu.
Z tego, co widziałem, deklaracje XML nigdy nie są utrwalane podczas korzystania z kolumny XML. Nawet bez użycia .NET i tylko przy użyciu tej bezpośredniej instrukcji wstawiania SQL, na przykład, deklaracja XML nie jest zapisywana w bazie danych z XML:
Insert Into TestData(Xml) Values ('<?xml version="1.0" encoding="UTF-8"?><Test/>');
Teraz, jeśli chodzi o pytanie OP, obiekt do serializacji nadal musi zostać przekonwertowany na strukturę XML z MyMessage
obiekt i XmlSerializer
jest do tego jeszcze potrzebny. Jednak w najgorszym przypadku zamiast serializacji do ciągu, wiadomość może zamiast tego zostać zserializowana do XmlDocument
- który można następnie przekazać do SqlXml
przez nowy XmlNodeReader
- unikanie podróży deserializacji/serializacji do ciągu. (Zobacz http://blogs.msdn.com/b/jongallant/archive/2007/01/30/how-to-convert-xmldocument-to-xmlreader-for-sqlxml-data-type.aspx , aby uzyskać szczegółowe informacje i przykład .)
Wszystko tutaj zostało opracowane i przetestowane z .NET 4.0 i SQL Server 2008 R2.
Proszę nie marnować uruchamiając XML poprzez dodatkowe konwersje (de-deserializacje i serializacje - do DOM, stringów lub w inny sposób), jak pokazano w innych odpowiedziach tutaj i gdzie indziej.