1

我有以下 c# 类

public class Data
{
    public string A {get;set;}
    public string B {get;set;}
    public string C {get;set;}
}

我在我的代码中创建了一个实例:

var d = new Data { A = "abc", B = string.Empty, C = null};

我需要将其转换为 XML 并将其传递给 SQL Server 2008 中的存储过程。

我这样做使用:

var xml = new XElement("Data",
    new XElement("A", d.A),
    new XElement("B", d.B),
    new XElement("C", d.C));

存储过程中生成的 XML 是:

<Data>
    <A>abc</A>
    <B></B>
    <C />
</Data>

因此,空字符串和空值之间存在差异。

然后在 SQL 中,我使用以下语法来读取 XML:

INSERT INTO #myTable
SELECT 
  nref.value('(A/text())[1]', 'uniqueidentifier') [A],
  nref.value('(B/text())[1]', 'uniqueidentifier') [B],
  nref.value('(C/text())[1]', 'uniqueidentifier') [C],
FROM @DataXml.nodes('/Data') AS R(nref);

但这为我提供了 B 和 C 都为 NULL,其中 B 应该是空字符串。

我该如何调整它以确保空值保持为空值而空字符串保持为空字符串?

谢谢

4

1 回答 1

2

XElement 构造函数可能会以不同的方式处理 NULL 和空,但 XML 规范认为 < X /> 和 < X>< /X> 是相同的。SQL server XQuery 也同样对待它们。

如果希望 SQL Server 区分空元素和空元素,则需要在 C# 代码中构造 XML 时完全排除空元素。例如,下面将元素 B 视为空,将元素 C 视为 NULL,因为它丢失了:

declare @x xml = 
'<Data><A>abc</A><B></B></Data>'

SELECT 
  nref.value('(A/text())[1]', 'varchar') [A],
  isnull(nref.value('(B/text())[1]', 'varchar'), case when nref.exist('./B') = 1 then '' end) [B],
  isnull(nref.value('(C/text())[1]', 'varchar'), case when nref.exist('./C') = 1 then '' end) [C]
FROM @x.nodes('/Data') AS R(nref);
于 2013-09-23T14:01:22.787 回答