Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Как да разрешите невъзможността да се превключи грешката в кодирането при вмъкване на XML в SQL Server

Този въпрос е почти дубликат на други 2 и изненадващо - докато този е най-новия - вярвам, че липсва най-добрият отговор.

Дубликатите и според мен най-добрите им отговори са:

  • Използване на StringWriter за XML сериализация (2009-10-14)
    • https://stackoverflow.com/a/1566154/751158
  • Опитът за съхраняване на XML съдържание в SQL Server 2005 е неуспешен (проблем с кодирането) (2008-12-21)
    • https://stackoverflow.com/a/1091209/751158

В крайна сметка няма значение какво кодиране е декларирано или използвано, стига XmlReader може да го анализира локално в сървъра на приложения.

Както беше потвърдено в Най-ефективният начин за четене на XML в ADO.net от колона тип XML в SQL сървър?, SQL Server съхранява 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/>');

Сега по отношение на въпроса на ОП обектът, който трябва да бъде сериализиран, все още трябва да бъде преобразуван в XML структура от MyMessage обект и 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 за подробности и пример .)

Всичко тук е разработено срещу и тествано с .NET 4.0 и SQL Server 2008 R2.

Моля, не правете отпадъци чрез изпълнение на XML чрез допълнителни преобразувания (де-десериализации и сериализации - към DOM, низове или по друг начин), както е показано в други отговори тук и другаде.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Кои колони обикновено правят добри индекси?

  2. Как да свържете база данни на Access към SQL Server в Access 2016

  3. SQL Server (TSQL) - Възможно ли е паралелно да се изпълняват оператори EXEC?

  4. CTE безкраен цикъл с ОПЦИЯ (макс. рекурсия 0)

  5. Как да прехвърлите DateTime към Time