我有一个非常复杂的XML需要使用C#应用程序加载到MS SQL Server DB中。我使用.NET标准SQLXMLBulkLoad库来执行此操作。 XML如下所示。
<HouseInfo>
<HouseNumber>1</HouseNumber>
<HouseLog>
<RoomInfo>
<RoomNumber>1</RoomNumber>
<Timestamp>2017-12-29T12:16:51</Timestamp>
<Furnitures>
<Table>
<Color>Blue</Color>
<Height>23</Height>
</Table>
</Furnitures>
<ToolCounts>
<Scope>1</Scope>
</ToolCounts>
</RoomInfo>
<RoomInfo>
<RoomNumber>2</RoomNumber>
<Timestamp>2017-12-29T15:43:23</Timestamp>
<Furnitures>
<Table>
<Color>Black</Color>
<Height>35.2</Height>
</Table>
</Furnitures>
<ToolCounts>
<Scope>1</Scope>
</ToolCounts>
<Bathroom>
<Code>1234</Code>
<Faucets>3></Faucets>
</Bathroom>
</RoomInfo>
<RoomInfo>
<RoomNumber>2</RoomNumber>
<Timestamp>2017-12-29T15:45:48</Timestamp>
<Furnitures>
<Table>
<Color>Red</Color>
<Height>98.56</Height>
</Table>
</Furnitures>
<ToolCounts>
<Scope>1</Scope>
</ToolCounts>
<Bathroom>
<Code>1234</Code>
<Faucets>2></Faucets>
</Bathroom>
</RoomInfo>
</HouseLog>
</HouseInfo>
我创建了一个XSD(架构)文件并传递了XML&amp; XSD到lib的执行功能。
在DB中创建一个表来添加所有数据标记,如下所示。
CREATE TABLE HOUSEINFO (House Number INT,
RoomNumber INT,
TimeStamp DateTime,
Color VARCHAR(25),
Height VARCHAR(25),
Scope INT,
Code INT,
Faucet INT);
此处的目标是让每一行都包含 HouseNumber , RoomNumber &amp; TimeStamp 作为前三列。列的其余部分将包含 RoomInfo 中其余标记的数据。
我自己尝试过,但无法找到确保前三列是上述列的方法。我认为这是SQLXMLBulkLoad库的限制。即,一旦XML&amp; XSD被传递到这个库中,由它自行决定如何将数据加载到数据库,我们无法控制。这个陈述是否正确?
我可以采用另一种方法来实现这一目标吗?即,将每个 RoomInfo 标记内的所有数据放在一行中,前三列将是 HouseNumber , RoomNumber &amp;的时间戳
这些是前三列的原因是因为这样可以很容易地编写查询来提取数据。如您所见 HouseNumber 对整个XML都是唯一的。 RoomNumber &amp; 时间戳对于每个 RoomInfo 都是唯一的。 XML中可以有N个 RoomInfo 标记。
XSD&amp; amp;数据库编程,真的在这里挣扎。感谢您的帮助!
答案 0 :(得分:1)
我不知道SQLXMLBulkLoad如何根据您的要求为您完成工作。这是另一种选择。您可以使用Cinchoo ETL和SqlBulkCopy将xml导入数据库。这是工作样本
static void BulkLoad1()
{
string connectionstring = /* your db connection string */
int houseNo = 0;
using (var xr = new ChoXmlReader("your.xml").WithXPath("/HouseInfo")
.WithField("HouseNumber", fieldType: typeof(int))
)
{
houseNo = xr.First().HouseNumber;
}
using (var xr = new ChoXmlReader("your.xml").WithXPath("/HouseInfo/HouseLog/RoomInfo")
.WithField("HouseNumber", fieldType: typeof(int), valueConverter: (o) => houseNo)
.WithField("RoomNumber", fieldType: typeof(int))
.WithField("Timestamp", fieldType: typeof(DateTime))
.WithField("Color", xPath: "Furnitures/Table/Color", fieldType: typeof(string))
.WithField("Height", xPath: "Furnitures/Table/Height", fieldType: typeof(string))
.WithField("Scope", xPath: "ToolCounts/Scope", fieldType: typeof(int))
.WithField("Code", xPath: "Bathroom/Code", fieldType: typeof(int))
.WithField("Faucet", xPath: "Bathroom/Faucets", fieldType: typeof(int))
)
{
using (SqlBulkCopy bcp = new SqlBulkCopy(connectionstring))
{
bcp.DestinationTableName = "dbo.HOUSEINFO";
bcp.EnableStreaming = true;
bcp.BatchSize = 10000;
bcp.BulkCopyTimeout = 0;
bcp.NotifyAfter = 10;
bcp.SqlRowsCopied += delegate (object sender, SqlRowsCopiedEventArgs e)
{
Console.WriteLine(e.RowsCopied.ToString("#,##0") + " rows copied.");
};
bcp.WriteToServer(xr.AsDataReader());
}
}
希望这有帮助。