使用存储过程 For XML Path 直接读入绑定到 DataGridView 的 DataSet?

Posted

技术标签:

【中文标题】使用存储过程 For XML Path 直接读入绑定到 DataGridView 的 DataSet?【英文标题】:Using stored procedure For XML Path read directly into DataSet bound to DataGridView? 【发布时间】:2019-03-19 06:27:29 【问题描述】:

我有以下存储过程:

CREATE Procedure [dbo].[usp_GetMyAlbumData]  
AS
    SELECT * 
    FROM [dbo].[tblAlbumDetails]  
    FOR XML PATH('AlbumDetail'), ROOT('AlbumDetails'), TYPE

我需要弄清楚如何使用usp_ReportGetMyAlbumData 生成的XML 在datagridview 中显示数据。

例如,我的数据库中有一条记录。当我在 SQL Server 2012 中运行 usp_ReportGetMyAlbumData 存储过程时,我得到以下结果:

<AlbumDetails>
  <AlbumDetail>
    <MusicID>1</MusicID>
    <AlbumDesc>Jones</AlbumDesc>
    <AlbumDate>2018-10-13T15:55:49.843</AlbumDate>
    <AlbumPrice>4.0000</AlbumPrice>
  </AlbumDetail>
</AlbumDetails>

我想使用 C# 将此 XML 结果(或usp_ReportGetMyAlbumData 生成的任何其他 XML 结果)写入 DataSet,以便我可以将其绑定到 DataGridView。

我知道如何write XML files to a Dataset,但存储过程返回 XML,而不是 XML 文件

我需要编写什么代码来使用存储过程生成的 XML 中的数据填充数据集?

【问题讨论】:

您使用的是哪个 dbms? @jarlh Microsoft SQL Server 2012 这有帮助吗:***.com/questions/8468566/… ? @lex87 对不起,我仍然很困惑。我正在查看链接中的答案,它说绑定 xml 源与绑定到数据库源没有太大区别,但它完全不同,因为 xml 输出是一个字符串,而数据集是一个不同的结构。 amelvin 在他的回答中提供的链接转发到另一个链接已过期的问题,以及一个指向使用 vb 代码的按需网络研讨会的链接。 【参考方案1】:

xml 将是来自数据库的字符串。所以我会使用 xml linq 解析方法将字符串放入数据表中。然后将数据表作为 DGV 的来源。见下面的代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace WindowsFormsApplication1

    public partial class Form1 : Form
    
        const string FILENAME = @"c:\temp\test.xml";
        public Form1()
        
            InitializeComponent();

            //data will be from the database a string
            //I'm reading fron a file for testing
            string xml = File.ReadAllText(FILENAME);

            DataTable dt = new DataTable();
            dt.Columns.Add("MusicID", typeof(int));
            dt.Columns.Add("AlbumDesc", typeof(string));
            dt.Columns.Add("AlbumDate", typeof(DateTime));
            dt.Columns.Add("AlbumPrice", typeof(decimal));

            XDocument doc = XDocument.Parse(xml);

            foreach(XElement album in doc.Descendants("AlbumDetail"))
            
                dt.Rows.Add(new object[] 
                    (int)album.Element("MusicID"),
                    (string)album.Element("AlbumDesc"),
                    (DateTime)album.Element("AlbumDate"),
                    (decimal)album.Element("AlbumPrice")
                );
            

            dataGridView1.DataSource = dt;

        
    

【讨论】:

当我使用您发布的代码时,DataGridView 上没有行或行标题。当我进入调试模式并检查 DataTable 时,它​​有 4 列和 1 行。 DataTable中的数据在设置为DataGridView的数据源之前是正确的,但是什么都没有出现。唯一的区别是,我没有使用文件,而是在每个结束标记后使用带有 \n 的字符串来分隔行。 在设置为 dt 之前尝试将 DataSource 设置为 null。当您更改数据源时,不会自动调用 DGV 重绘方法。所以诀窍是设置为 null 以便更新 DGV。很常见的问题。 Xml 忽略空格,因此 '\n' 是可选的。没有理由在调用我的代码之前必须格式化 DGV。代码将自动创建列并使数据类型与数据表匹配。 dgvMusic.DataSource = null; dgvMusic.DataSource = dt;也没有用。 创建一个新的数据网格视图成功了!我不明白为什么它有效,但它确实有效。什么可能导致了问题? 空白 DGV 将自动完成所有工作。现有的可能与数据表的设置不兼容。【参考方案2】:
string xml = "your xml here";
var ds = new DataSet();

using (var reader = new StringReader(xml))

    ds.ReadXml(reader);


dataGridView.DataSource = ds.Tables[0];

【讨论】:

不幸的是,这也不会在 DataGridView 中产生任何内容。我确实喜欢它的简单性。 虽然此代码可能会回答问题,但提供有关它如何和/或为什么解决问题的额外上下文将提高​​答案的长期价值。 @ArmorCode - 这保证有效(与其他答案一样)。确保将数据绑定到正确的 DataGridView。 这也像其他答案一样现在有效。正如jdweng所说,我只需要删除并重新创建datagridview。

以上是关于使用存储过程 For XML Path 直接读入绑定到 DataGridView 的 DataSet?的主要内容,如果未能解决你的问题,请参考以下文章

如何从“for xml path”获取结果?

sqlserver - FOR XML PATH

灵活运用 SQL SERVER FOR XML PATH

SQL SERVER FOR XML PATH

Sql Server FOR XML PATH

灵活运用 SQL SERVER FOR XML PATH