如何使用Linq to SQL和Linq to XML查询数据库列中的XML数据?

时间:2011-06-14 12:30:59

标签: linq-to-sql linq-to-xml

XML:

<root>
    <item>
        <href>http://myurl</href>
    </item>
    <item>
        <href>http://myurl2</href>
    </item>
</root>

XML数据存储在数据库表中。

我可以构建一个Linq查询来选择行,提取XML然后,例如,提取所有 href 标签吗?最终结果将是所有选定行的所有URL的列表。

这是我的尝试,但它没有给我我想要的东西 - 这将是所有选定用户的所有href的列表。我只是得到一个空的IEnumerations列表。

var all = from bm in MYTABLE
        select new { name=bm.SPP_USER_ID, xml=(string) bm.SPP_BOOKMARKS_XML};

var docs = from x in all
        select XDocument.Parse(x.xml);
var href = from h in docs
        select h.Descendants("href");

<小时/> 的解决方案

有2个问题。

- 我想只有在实际需要结果时才会执行查询。随着我从SQL进展到XML查询,生成的查询变成了SQL和XML的混合,因此是不可执行的。我的解决方案是通过将SQL查询转换为结果列表来强制执行结果。这将linq-sql与linq-xml分开。

var docs = from x in all
        select XDocument.Parse(x.xml);
var docs2 = docs.ToList();  // force result

- 第二个问题是我忘了将命名空间添加到我的XML查询中。一旦我这样做,我得到了所需的结果

XNamespace ns = "http://acme/bookmarks";
var href = from h in docs2
    select h.Descendants(ns + "href");

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

以下是我尝试过的几件事。

  1. 设置:我使用表MYTABLE创建了一个包含2列的数据库。第1列(SPP_USER_ID)是varchar(255),第2列(SPP_BOOKMARKS_XML)是xml数据类型。我添加了2行,镜像了mellamokb使用的那些。我创建了一个LINQ to SQL设计表面并在此表中拖动。我的应用程序只是一个控制台应用程序,它加载LINQ to SQL数据上下文,然后调用您的命令。
  2. 我直接查询数据表,如下所示:

            var all = from bm in context.MYTABLEs
                      select new { name = bm.SPP_USER_ID, xml = (string)bm.SPP_BOOKMARKS_XML };
    
            var docs = from x in all
                       select XDocument.Parse(x.xml);
    
            var href = from h in docs
                       select h.Descendants("href");
    

    结果是IEnumerables的集合。即对于数据库中的每一行,我得到一个包含所有“href”后代的IEnumerable。所以在这种情况下,我得到了两个结果;第一个结果是包含2个元素的IEnumerable,第二个结果是包含1个元素的IEnumerable。从你的描述来看,这似乎至少接近你想要的。但是,由于查询的结构方式,您可能没有看到您的期望。

    请注意,有时候让Visual Studio实际显示这样的查询结果是相当困难的。我发现在经常发布结果枚举之前,我经常需要两次“观察”该项目。

  3. 我尝试复制OP中编写的代码,如下所示:

            var MYTABLE = (from bm in context.MYTABLEs select bm).ToList();
    
            var all = from bm in MYTABLE
                      select new { name = bm.SPP_USER_ID, xml = (string)bm.SPP_BOOKMARKS_XML };
    
            var docs = from x in all
                       select XDocument.Parse(x.xml);
    
            var href = from h in docs
                       select h.Descendants("href");
    

    当我这样做时,它导致“xml”值被删除,因为它已经是一个XDocument(?),因此将其转换为字符串会导致所有标记被删除。因此,接下来的两个语句因XML分析异常而失败。

答案 1 :(得分:1)

以下是使用您的代码和MYTABLE的硬编码内容的代码段,它完美无缺(通过LinqPad验证)。也许您的数据库表或MYTABLE不包含您的想法?你能查看all的结果吗?

var MYTABLE = new  [] {
    new {
        SPP_USER_ID = "XML-SNIPPET-1",
        SPP_BOOKMARKS_XML = @"
        <root>
            <item>
                <href>http://myurl</href>
            </item>
            <item>
                <href>http://myurl2</href>
            </item>
        </root>
        ",
    },
    new {
        SPP_USER_ID = "XML-SNIPPET-2",
        SPP_BOOKMARKS_XML = @"
        <root>
            <item>
                <href>http://google.com</href>
            </item>
        </root>
        ",
    }
};

var all = from bm in MYTABLE
        select new { name=bm.SPP_USER_ID, xml=(string) bm.SPP_BOOKMARKS_XML};

var docs = from x in all
        select XDocument.Parse(x.xml);
var href = from h in docs
        select h.Descendants("href");

foreach (var h in href.SelectMany(h => h))
{
    Console.WriteLine(h);
}

输出:

<href>http://myurl</href>
<href>http://myurl2</href>
<href>http://google.com</href>

希望这有帮助!