【问题标题】:Grouping results within XML element with inner joins使用内部连接对 XML 元素内的结果进行分组
【发布时间】:2013-03-07 15:34:56
【问题描述】:

我正在尝试了解如何组合 LINQ-to-XML 和 LINQ-to-SQL 查询并执行连接。

具体来说,我有一个包含城市、县和州信息的 SQL 表,我可以使用 LINQ to SQL 查询它,但是在同一个查询中,我想加入具有相同状态的 SQL 行和/或县,并生成一个 XML 作为输出的一部分。

这大概是我的桌子的样子:

╔═════╦══════════════╦════════════════╦═══════╗
║ IDX ║     CITY     ║   COUNTY       ║ STATE ║ 
╠═════╬══════════════╬════════════════╬═══════╣
║  1  ║ YAKUTAT      ║ ALEUTIANS EAST ║ AK    ║
║  2  ║ city-1       ║ ALEUTIANS EAST ║ AK    ║
║  3  ║ city-2       ║ ALEUTIANS EAST ║ AK    ║
║  4  ║ city-3       ║ ALEUTIANS WEST ║ AK    ║
║  5  ║ city-4       ║ ALEUTIANS WEST ║ AK    ║
║  6  ║ city-5       ║ ALEUTIANS WEST ║ AK    ║
║  7  ║ xyz          ║ ANCHORAGE      ║ AK    ║
║  8  ║ abc          ║ BETHEL         ║ AK    ║
║  9  ║ lmnop        ║ WYOMING        ║ NY    ║
║  10 ║ pqrst        ║ WARSAW         ║ NY    ║
║  11 ║ defg         ║ WARSAW         ║ NY    ║
╚═════╩══════════════╩════════════════╩═══════╝

这就是我希望我的 XML 输出的样子。我希望加入将所有具有相同县的城市分组为同一县节点下的节点,然后将一个州的所有县分组为该州节点的子节点。

<State>AK</State>
  <County>ALEUTIANS EAST</County>
    <City>YAKUTAT</City>
    <City>city-1</City>
    <City>city-2</City>
  <County>ALEUTIANS WEST</County>
    <City>city-3</City>
    <City>city-4</City>
    <City>city-5</City>   
  <County>ANCHORAGE</County>
    <City>xyz</City>
  <County>BETHEL</County>
    <City>abc</City>
<State>NY</State>
  <County>WYOMING</County>
    <City>lmnop</City>
  <County>WARSAW</County>
    <City>pqrst</City>
    <City>defg</City>

我确实有这部分工作,我能够成功地从我的数据库中选择行,并且我能够将输出编写为 XML,但我无法将城市和县数据嵌套为州的子节点,并且我缺少连接部分,不清楚如何执行此操作。

XDocument xDoc = new XDocument(new XElement("States",
   (from states in state.Database 
    select new XElement(new XElement("State",states.State),
           new XElelment("County",states.County),
           new XElelment("City",state.City))));

xDoc.Save("C:\\states.xml")

这就是我得到的输出。如您所见,我在我的数据库中获得了所有城市、州和县的完整列表,没有层次结构。

<State>AK</State>
<County>ALEUTIANS EAST</County>
<City>YAKUTAT</City>
<State>AK</State>
<County>ALEUTIANS EAST</County>
<City>city-1</City>
<State>AK</State>
<County>ALEUTIANS EAST</County>
<City>city-2</City>
<State>AK</State>
<County>ALEUTIANS WEST</County>
<City>city-3</City>
<State>AK</State>
<County>ALEUTIANS WEST</County>
<City>city-4</City>
....and so on..

【问题讨论】:

  • 好的,我想知道为什么版主关闭了这个问题,你认为我会浪费我的时间在注册后问一个反问......我使用了来自不同帖子的数据,这只是因为与我的项目有关的数据有个人详细信息....
  • @user2141957 关闭您的问题的不是版主,而是社区的 5 位成员。它被关闭的最可能原因是因为你真的没有问问题,或者至少你写问题的方式,很难弄清楚你在问什么。我认为您的问题可能是可以挽救的,但您需要提供一些说明。具体来说,state 是什么?是收藏吗?您引用了一个 SQL,但没有迹象表明它是如何发挥作用的。
  • @user2141957 我提出的一个建议是阅读此博客条目:Writing the perfect question。这是一篇非常好的文章,由我们排名最高的成员之一撰写,内容是关于如何写一个好问题来获得好的答案。很有帮助
  • @psubsee2003:我试图将数据以表格形式放置,但格式化标签不受限制,因此它看起来像一个段落而不是一个表格,我尝试了 HTML,我一定是浪费了30 分钟试图找出在这里输入我的问题的最佳方式,最后 5 个人关闭了我的帖子,认为我在这里浪费了我的时间。ugggghhhh
  • @psubsee2003 但要回答您的问题,状态是表格中的列。所以是县和市。

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


【解决方案1】:

您确实有几个单独的问题,首先是您无法生成分层 XML 文件(假设我在编辑您的问题之前了解您的初衷)。事实上,您的示例 XML 甚至不是分层的,因为您在将预期的子标签嵌套在它下面之前关闭标签。像你一样缩进不是创建任何类型的子节点,只是让它看起来像。

这就是我认为您希望您的 XML 看起来像的样子:

<State>AK
  <County>ALEUTIANS EAST
    <City>YAKUTAT</city>
    <City>city-1</city>
  </County>
</State>

但是将字符串等简单类型与同一节点中的其他节点等复杂类型混合起来可能会非常混乱。我可以建议修改结构以使用属性,从而消除一些令人困惑的层次结构。像这样的结构更容易被接受:

<State name = "AK">
  <County name = "ALEUTIANS EAST">
    <City>YAKUTAT</city>
    <City>city-1</city>
  </County>
</State>

生成嵌套 XML 只需将 XElement 对象排列在彼此内部即可

XElement stateElement = new XElement("State", new XAttribute("name", "AK"), 
                            new XElement("County", new XAttribute("name", "ALEUTIANS EAST"), 
                                new XElement("City", "YAKUTAT"), 
                                new XElement("City", "city-1")));

将生成一个具有我上面建议的结构的 XML。

您缺少的第二部分是连接。由于所有内容都在同一个表中,因此您实际上是在寻找组查询,因为您想将子元素组合在一个共同的父元素下。

我不是 LINQ-to-SQL 的期望,而且不同风格之间可能存在字幕差异这一事实,我不能 100% 确定语法会完全正确,但希望,如果它关闭,它仍然会为您指明正确的方向。

请注意,仅仅因为您正在创建一个 XML 文件,这不是 LINQ-to-XML,LINQ 是关于查询源,而不是输出,因为您正在查询您的数据库,所以这是 LINQ-to -SQL

var query = from states in state.Database 
            group states by new { states.State, states.County } into countyGroup
            group countyGroup by countyGroup.Key.State into stateGroup
            select new XElement("State", new XAttribute("name", stateGroup.Key),
                       stateGroup.Select(st => new XElement("County", new XAttribute("name", st.Key.County),
                       st.Select(city => new XElement("City", city.City)))));

var xdoc = new XDocument(new XDeclaration("1.0", "UTF-8", null),
                         new XElement("States", query.ToArray()));

第一个 group 语句将根据共同的县和州将所有数据库行分组(必须包括州,就像您排除它一样,佛罗里达州奥兰治和加利福尼亚州奥兰治内的城市将被分组在一起。然后,第二个 group 语句会将您的数据库行进一步分组到常见状态。您最终会得到一个分组(称为stateGroup,它由同一县的城市集合和同一城市中分组的县组成。

将分组分解为适当的 XML 节点的 select 语句变得非常混乱,但它有效地写出了每个分组,以便到达我认为您想去的地方。

(您在问题中创建XDocument 时也错过了 XML 声明,因此我在此处添加了该声明)。

【讨论】:

  • 感谢一群新手给一个如此详细的解释,你不仅澄清了我对 linq-xml 的困惑,而且你更好地重新构建了我原来的问题。
  • @user2141957 但现在您可以看到一个框架良好的问题可以做的不同...在我完成初始编辑后 5 分钟重新打开了该问题。你抱怨在这个问题上花了 30 分钟……但老实说,我通常至少会花那么多时间在网站上写我自己的问题。得到一个好问题需要很长时间。
  • @user2141957 我通常不会在我自己的答案上这样做,但如果你觉得它有帮助不要忘记点赞,如果它解决了问题,请检查答案标记。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-20
  • 1970-01-01
相关资源
最近更新 更多