Linq2SQL, хранящий XElement в базе данных SQL Server, удаляет пробелы
Могу ли я заставить System.Data.Linq.DataContext
сохранить XML в столбце XML таблицы SQL Server, сохраняя пробелы или есть какой-либо другой способ?
Мой тестовый код выглядит следующим образом:
Guid MyNewQid = Guid.NewGuid();
using (DataClassesDataContext context = DataClassesDataContext.CreateDataContext())
{
Guid myQID = Guid.Parse("{28da4eca-2c1a-4647-xxx-b398d1xxx013}");
FromSwiftBck t2sData = context.GetTable<FromSwiftBck>().FirstOrDefault(o => o.QID == myQID);
string messageLoaded = t2sData.CompleteMessage;
int appHeaderLenght = messageLoaded.IndexOf("</AppHdr>") + 9;
string strMsgHeader = messageLoaded.Substring(0, appHeaderLenght);
string strMsgDocument = messageLoaded.Substring(appHeaderLenght);
XElement serv = XElement.Parse(strMsgDocument, LoadOptions.PreserveWhitespace);
SwiftOut swOut = new SwiftOut();
swOut.QID = MyNewQid;
swOut.InsertTime = DateTime.Now;
swOut.Message = serv;
swOut.Status = -100;
swOut.Namespace = swOut.Message.GetDefaultNamespace().NamespaceName;
swOut.MessageName = swOut.Message.Descendants().First().Name.LocalName;
context.SwiftOuts.InsertOnSubmit(swOut);
context.SubmitChanges();
}
using (DataClassesDataContext context = DataClassesDataContext.CreateDataContext())
{
SwiftOut swOutStored = context.GetTable<SwiftOut>().FirstOrDefault(o => o.QID == MyNewQid);
XElement storedXdoc = swOutStored.Message;
MessageBox.Show(storedXdoc.ToString());
context.SwiftOuts.DeleteOnSubmit(swOutStored);
context.SubmitChanges();
}
}
Когда я читаю данные из нового контекста, я получаю XML с удаленными пробелами.
2 ответа
Тип данных XML НЕ сохраняет точное текстовое представление XML - он анализирует и маркирует XML для более оптимального хранения.
SQL Server не гарантирует, что возвращаемый XML-файл точно такой же (с точки зрения форматирования, пробелов и т. Д.), Что и входные данные.
Насколько мне известно, нет никаких опций или настроек конфигурации, чтобы изменить это поведение.
Смотрите здесь для более подробной информации:
Собственное хранилище как тип данных xml
Данные хранятся во внутреннем представлении, которое сохраняет XML-содержимое данных...... Содержимое InfoSet может не быть идентичной копией текстового XML, поскольку не сохраняется следующая информация: незначительные пробелы, порядок атрибутов, префиксы пространств имен и объявление XML.
(акцент был добавлен мной)
Укороченная версия
Вам нужно добавить xml:space
приписывать. LoadOptions.PreserveWhitespace
влияет только на анализ строки. Это не добавляет атрибут. Вы должны добавить:
serv.SetAttributeValue(XNamespace.Xml + "space", "preserve");
Длинная версия
SQL Server уважает xml:space
приписывать. Этот запрос:
create table #xmltest (field xml);
insert into #xmltest
values
('<elem> </elem>'),
('<elem xml:space="preserve"> </elem>');
select * from #xmltest;
Возвращает:
<elem />
<elem xml:space="preserve"> </elem>
Код вопроса не определяет это, хотя. Он разбирает строку в XElement с помощью PreserveWhitespace
но не добавляет этот атрибут. Если исходная строка не содержит этого атрибута, XElement также не будет содержать его.
Код вставляет эквивалент первого значения, которое не требует сохранения пробелов.
Например:
XElement.Parse("<elem> </elem>",LoadOptions.PreserveWhitespace).ToString();
Производит <elem> </elem>
который не указывает, что пробел должен быть сохранен. PreserveWhitespace
в этом случае переопределяет поведение по умолчанию, которое игнорирует пробелы.
Без PreserveWhitespace
Parse игнорирует пробелы и возвращает <elem></elem>
,
С другой стороны:
XElement.Parse("<elem xml:space='preserve'> </elem>").ToString()
Производит <elem xml:space="preserve"> </elem>
, Там нет необходимости использовать PreserveWhitespace
флаг, сам XElement распознает и уважает этот флаг.
Если исходная строка XML содержит пробелы, но не содержит xml:space
атрибут, его нужно добавить, чтобы другие классы и приложения, такие как SQL Server, знали, что они должны сохранять пробелы. Следующий код:
var serv=XElement.Parse("<elem> </elem>",LoadOptions.PreserveWhitespace);
serv.SetAttributeValue(XNamespace.Xml + "space", "preserve");
serv.ToString();
Вернусь <elem xml:space="preserve"> </elem>
который будет распознаваться SQL Server.
Собирая все это вместе
Этот код LINQ to SQL:
var serv=XElement.Parse("<elem> </elem>",LoadOptions.PreserveWhitespace);
serv.SetAttributeValue(XNamespace.Xml + "space", "preserve");
Xmltests.InsertOnSubmit(new Xmltest{Field=serv});
Вставит:
<elem xml:space="preserve"> </elem>
В базу данных