[英]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.