簡體   English   中英

從不一致的xml C#/ SQL中提取數據的最佳方法

[英]Best way to extract data from inconsistent xml C#/SQL

我在SQL Server 2016中有一個臨時表,其中有許多XML數據。 我需要獲取每個XML,從中讀取數據以輸入另一個表,然后從臨時表中刪除數據。 但是,我有兩個問題。 一種是XML的架構不一致。 對於某些節點可能會有額外的節點,而對於另一些節點則不會存在。 同樣對於每種XML,我必須循環處理多條消息才能為主表創建多行。 其次,我已經嘗試使用“ CROSS APPLY”(我可能已經錯過了一些聯接,但是無論如何數據都來了),結果是每20秒接收1條消息,嘗試了SSIS(再次缺少1-2個聯接,但是數據即將來臨)無論如何),結果是每8秒收到1條消息。 最后,我創建了C#控制台代碼,以將消息存儲在數據表中,將其轉換為XML文檔,檢查節點是否存在,根據需要進行循環,最后再次將其插入數據庫中,每秒大約接收3-4條消息。

現在我的問題是,我想使其更快(最好是每分鍾1000條消息)。 誰能提出更好的方法來實現這一目標?

編輯:(XML如下所示)

<Step1>
  <MetaData>
    <Node1>Value</Node1>
    <Node2>Value</Node2>
  </MetaData>
  <ActualData>
    <MainNode>
      <Child1>
        <NodeA>Value</NodeA>
      </Child1>
      <Child2>
        <Numbers>
          <Child a="b">LoopValue</Child>
          <Optional a="b">AdditionalLoopValue</Optional>
        </Numbers>
        <Alphabets>
          <Child a="b">
            <Child1>
              <Sub1>Value</Sub1>
              <Sub2>Value</Sub2>
            </Child1>
            <Child2>
              <Sub1>Value</Sub1>
              <Sub2>Value</Sub2>
            </Child2>
          </Child>
          <Optional a="b">
            <Child1>
              <Sub1>Value</Sub1>
              <Sub2>Value</Sub2>
            </Child1>
            <Child2>
              <Sub1>Value</Sub1>
              <Sub2>Value</Sub2>
            </Child2>
          </Optional>
        </Alphabets>
      </Child2>
      <Child3>
        <Loop1>
          <Child1>Value</Child1>
          <Child2>
            <Sub1>Value</Sub1>
          </Child2>
          <Child3>
            <Sub1>Value</Sub1>
            <Sub2>Value</Sub2>
          </Child3>
          <Child4>Value</Child4>
        </Loop1>
        <Loop2>
          <Child1>Value</Child1>
          <Child2>
            <Sub1>Value</Sub1>
          </Child2>
          <Child3>
            <Sub1>Value</Sub1>
            <Sub2>Value</Sub2>
          </Child3>
          <Child4>Value</Child4>
          <Optional1>
            <Sub1>Value</Sub1>
            <Sub2>Value</Sub2>
          </Optional1>
        </Loop2>
      </Child3>
    </MainNode>
  </ActualData>
</Step1>

編輯2 :(代碼如下所示)

string a,b,c;
DataTable dt;
foreach on DataTable.Rows
{    foreach node on nodelist
     {   if Node1.ChildNode !=null
            {a=Node1.ChildNode["NodeName"]}
        if Node1.ChildNode !=null
            {b=Node1.ChildNode["NodeName"]}
        for loop on b
            {if Node1.ChildNode != null
                {c=Node1.ChildNode["NodeName"]}
            dt.Rows.Add(a,b,c);}}
    delete from temp table based on id.
    add records from dt to main table
    dt.Rows.Clear();}
public string str { get; private set; }

private void RecursiveSearchInXmlWithString(XmlNode xmlnode, string nametofind)
    {
        // check if node has children, if so then it recursively search the children too
        if (xmlnode.HasChildNodes)
        {
            for (int i = 0; i < xmlnode.ChildNodes.Count; i++)
            {
                RecursiveSearchInXmlWithString(xmlnode.ChildNodes[i], nametofind);
            }
        }
        // here is the element that we are searching for 
        if (xmlnode.Name == nametofind)
        {
            str = xmlnode.InnerText;
        }
    }

我對此類具有遞歸函數和公共全局變量。 str只能捕獲正確的值,調用后可以使用str。 在每個節點之后,您必須捕獲str。 您可以在此之后找出答案。

您還需要使用if語句處理所有可能的情況。

如果這些XML很大並且您有很多XML,則需要大量時間才能將數據轉移到C#應用程序中並創建XML文檔才能讀取。 如果該列是本機XML列,則在SQL Server中完成此工作將更快。

您的XML是深層嵌套的。 我希望您可以在任何情況下都可以依賴某些結構。

僅提示您如何進行:

SELECT @xml.value(N'(/Step1/MetaData/Node1/text())[1]',N'nvarchar(max)') AS Meta1
      ,@xml.value(N'(/Step1/MetaData/Node2/text())[1]',N'nvarchar(max)') AS Meta2
      ,childNode.value(N'local-name(.)','nvarchar(max)') AS ChildNode

      ,lvl2Numbers.value(N'(Child/@a)[1]',N'nvarchar(max)') AS NumberChildA
      ,lvl2Numbers.value(N'(Child/text())[1]',N'nvarchar(max)') AS NumberChildText
      ,lvl2Numbers.value(N'(Optional/@a)[1]',N'nvarchar(max)') AS NumberOptionalA
      ,lvl2Numbers.value(N'(Optional/text())[1]',N'nvarchar(max)') AS NumberOptionalText

      ,lvl2Alpha.query(N'.') AS lvl2Alpha
      --add further levels here

      ,lvl2Loop.query(N'.') AS lvl2Loop
      --add further levels here
FROM @xml.nodes(N'/Step1/ActualData/MainNode/*') AS A(childNode)

OUTER APPLY childNode.nodes(N'*[local-name()="Numbers"]') AS B1(lvl2Numbers)

OUTER APPLY childNode.nodes(N'*[local-name()="Alphabets"]') AS B2(lvl2Alpha)
OUTER APPLY lvl2Alpha.nodes(N'Child') AS B2a(ChildrenOfAlpha)
OUTER APPLY ChildrenOfAlpha.nodes(N'*') AS B2aa(SubChildrenOfAlpha)
OUTER APPLY SubChildrenOfAlpha.nodes(N'*') AS B2ab(SubsInSubChildrenOfAlpha)
OUTER APPLY lvl2Alpha.nodes(N'Optional') AS B2b(OptionalOfAlpha)
OUTER APPLY OptionalOfAlpha.nodes(N'*') AS B2ba(SubOptionalOfAlpha)
OUTER APPLY SubOptionalOfAlpha.nodes(N'*') AS B2bb(SubsInSubOptionalOfAlpha)

OUTER APPLY childNode.nodes(N'*[substring(local-name(),1,4)="Loop"]') AS B3(lvl2Loop)
--and so on

使用這樣的查詢,您可以降低層次結構,並在非規范化的廣義表中獲取全部內容 但這不會很快...

我將為每種數據結構創建一個查詢,並使用T-SQL進行邏輯處理,或者使用.query()調用並將此結果加載到C#中以處理那里的一個小片段。

暗示

如果此XML的結構在您的控制之下,請嘗試避免使用帶名稱編號的元素( <Child1>, <Child2> ... )。如果需要,請將其更改為<Child nr="1">, <Child nr="2"> ...更好,更快地閱讀...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM