2013-09-23 57 views
1

我有以下的C#类SQL服务器读取XML值作为空字符串

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应该是空字符串。

我该如何调整以确保空值保留为空值,空字符串保留为空字符串?

由于

+0

如果你说:“RAD的XML”你的意思是“读XML”? –

+0

为什么你需要将它转换为XML传递给存储过程,只是将它从XML中分离出来,返回到离散的字段中?只需将离散值传递到存储过程即可。 –

+0

最大,对于“rad”,读取“读取”。这条消息中的XML非常简单,我的实际XML更加复杂,并且允许我将一批对象传递给我的sproc,然后可以遍历它们。 – DrGriff

回答

0

的XElement构造可处理NULL和空不同,但XML规范认为< X />和< X> </X>是相同的。 SQL服务器XQuery也一样对待它们。

如果您希望SQL服务器区分空的&空元素,则需要在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); 
+0

您的xml节点选择器不使用“text()”方法,因此可能会在有子元素时返回预期结果,例如,当@x = ' ABC D1 D2'。所以当你使用text()方法(例如“nref.value('(B/text())[1]','varchar(10)')[B]”)时,B和C的值都是返回为NULL。 – DrGriff

+1

@DGGriff你是对的,我没有考虑过。尽管我试图做的主要观点是< X />和< X>< /X> *在每个XML规范中的含义*是相同的。所以你需要实际排除元素(当你在你的C#代码中构造XML时)来表示NULL和空。无论如何,我编辑答案提供一个基于EXIST方法的可能解决方案。希望能帮助到你。 –

+0

不知道为什么这一个是downvoted,这是我的upvote :)这不是很优雅的方式来做到这一点,但它应该工作 –