使用linq和C将xml转换为sql#
我有一个来自外部系统的xml文件,看起来像这样使用linq和C将xml转换为sql#,sql,xml,linq,Sql,Xml,Linq,我有一个来自外部系统的xml文件,看起来像这样 <?xml version="1.0" encoding="UTF-8"?> <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/"> <Body> <Element1> <Element2 day="2009-10-18"> <Elemen
<?xml version="1.0" encoding="UTF-8"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<Element1>
<Element2 day="2009-10-18">
<Element3 name="Joe">
<Element4 time="1">
<Element5 amount="0" price="16.58"/>
</Element4>
</Element3>
<Element3 name="Fred">
<Element4 time="5">
<Element5 amount="0" price="15.41"/>
</Element4>
</Element3>
</Element2>
</Element1>
</Body>
</Envelope>
day, name, time, amount, price
2009-10-18, Joe, 1, 0, 16.58
2009-10-18, Fred, 5, 0, 15.41
读取xml并将其插入数据库的最佳方式是什么?我一直在玩linq,但到目前为止没有太大成功。您需要将其插入SQL Server表吗??如果是:什么版本的SQL Server 您可以使用XQuery在SQL Server中轻松地将其分解,并将数据插入表中。使用类似于:
;WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS ns)
SELECT
@input.value('(/ns:Envelope/ns:Body/ns:Element1/ns:Element2/@day)[1]', 'varchar(50)') AS 'DayElement',
node.el.value('(@name)[1]', 'varchar(50)') AS 'Name',
node.el.value('(ns:Element4/@time)[1]', 'int') AS 'Time',
node.el.value('(ns:Element4/ns:Element5/@amount)[1]', 'decimal(15,2)') AS 'Amount',
node.el.value('(ns:Element4/ns:Element5/@price)[1]', 'decimal(15,2)') AS 'Price'
FROM
@input.nodes('/ns:Envelope/ns:Body/ns:Element1/ns:Element2/ns:Element3') AS node(el)
Day Name Time Amount Price
2009-10-18 Joe 1 0.00 16.58
2009-10-18 Fred 5 0.00 15.41
这将为您提供如下输出:
;WITH XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS ns)
SELECT
@input.value('(/ns:Envelope/ns:Body/ns:Element1/ns:Element2/@day)[1]', 'varchar(50)') AS 'DayElement',
node.el.value('(@name)[1]', 'varchar(50)') AS 'Name',
node.el.value('(ns:Element4/@time)[1]', 'int') AS 'Time',
node.el.value('(ns:Element4/ns:Element5/@amount)[1]', 'decimal(15,2)') AS 'Amount',
node.el.value('(ns:Element4/ns:Element5/@price)[1]', 'decimal(15,2)') AS 'Price'
FROM
@input.nodes('/ns:Envelope/ns:Body/ns:Element1/ns:Element2/ns:Element3') AS node(el)
Day Name Time Amount Price
2009-10-18 Joe 1 0.00 16.58
2009-10-18 Fred 5 0.00 15.41
当然,您可以使用它将数据提供给插入dbo.MyTable()的
语句,…
语句,从而立即将数据存储到表中
为那些可能对类似解决方案感兴趣的人添加更多内容
XDocument doc = XDocument.Load(@"myxml.xml");
DataContext bt = new DataContext();
var docxml = from c in doc.Elements("Envelope").Elements("Body").Elements("Element1").Elements("Element2").Elements("Element3")
select new mytable()
{
MyKey = Guid.NewGuid(),
day = Convert.ToDateTime(c.Parent.Attribute("day").Value),
name = c.FirstAttribute.Value,
time = Convert.ToInt32(c.Element("Element4").FirstAttribute.Value),
price = Convert.ToDecimal(c.Element("Element4").Element("Element5").Attribute("price").Value),
amount = Convert.ToDecimal(c.Element("Element4").Element("Element5").Attribute("amount").Value)
};
bt.mytable.InsertAllOnSubmit(docxml);
bt.SubmitChanges();
我有有用的开源XLinq扩展和其他UTIL,它们简化了xml解析、数据库持久化、文本序列化POCO类等 详情如下:
//source code for this example available at:
//http://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Common/ServiceStack.Common.Tests/Xlinq/XlinqExtensionsTests.cs
public class XmlData : IHasId<int>
{
[AutoIncrement]
public int Id { get; set; }
public string Day { get; set; }
public string Name { get; set; }
public int Time { get; set; }
public int Amount { get; set; }
public decimal Price { get; set; }
}
[Test]
public void Insert_data_from_xml_into_db()
{
//OrmLiteConfig.DialectProvider = SqlServerOrmLiteDialectProvider.Instance;
OrmLiteConfig.DialectProvider = SqliteOrmLiteDialectProvider.Instance;
var element2 = XElement.Parse(xml).AnyElement("Body").AnyElement("Element1").AnyElement("Element2");
using (var db = ":memory:".OpenDbConnection())
using (var dbCmd = db.CreateCommand())
{
dbCmd.CreateTable<XmlData>(true);
foreach (var element3 in element2.AllElements("Element3"))
{
var xmlData = new XmlData {
Day = element2.AnyAttribute("day").Value,
Name = element3.AnyAttribute("name").Value,
Time = int.Parse(element3.FirstElement().AnyAttribute("time").Value),
Amount = int.Parse(element3.FirstElement().FirstElement().AnyAttribute("amount").Value),
Price = decimal.Parse(element3.FirstElement().FirstElement().AnyAttribute("price").Value),
};
dbCmd.Insert(xmlData);
}
dbCmd.Select<XmlData>().ForEach(x => Console.WriteLine(StringSerializer.SerializeToString(x)));
}
}
//Prints out:
//{Id:1,Day:2009-10-18,Name:Joe,Time:1,Amount:0,Price:16.58}
//{Id:2,Day:2009-10-18,Name:Fred,Time:5,Amount:0,Price:15.41}
//此示例的源代码位于:
//http://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Common/ServiceStack.Common.Tests/Xlinq/XlinqExtensionsTests.cs
公共类XmlData:IHasId
{
[自动增量]
公共int Id{get;set;}
公共字符串Day{get;set;}
公共字符串名称{get;set;}
公共整数时间{get;set;}
公共整数金额{get;set;}
公共十进制价格{get;set;}
}
[测试]
public void将\u数据\u从\u xml\u插入到\u db()中
{
//OrmLiteConfig.DialogyProvider=SqlServerOrmLiteDialectProvider.Instance;
OrmLiteConfig.DialogProvider=SqliteOrmLiteDialectProvider.Instance;
var element2=XElement.Parse(xml).AnyElement(“Body”).AnyElement(“Element1”).AnyElement(“element2”);
使用(var db=“:memory:”.OpenDbConnection())
使用(var dbCmd=db.CreateCommand())
{
dbCmd.CreateTable(true);
foreach(var element3 in element2.等位基因(“element3”))
{
var xmlData=新的xmlData{
Day=element2.AnyAttribute(“Day”).Value,
Name=element3.AnyAttribute(“Name”).Value,
Time=int.Parse(element3.FirstElement().AnyAttribute(“Time”).Value),
Amount=int.Parse(element3.FirstElement().FirstElement().AnyAttribute(“Amount”).Value),
Price=decimal.Parse(element3.FirstElement().FirstElement().AnyAttribute(“Price”).Value),
};
dbCmd.Insert(xmlData);
}
dbCmd.Select().ForEach(x=>Console.WriteLine(StringSerializer.SerializeToString(x));
}
}
//打印出:
//{Id:1,日期:2009-10-18,姓名:乔,时间:1,金额:0,价格:16.58}
//{Id:2,日期:2009-10-18,姓名:Fred,时间:5,金额:0,价格:15.41}
答案将在很大程度上取决于您是否需要代码来构建表结构,或者只是将数据插入到预先存在的表中。谢谢Robert,我需要将数据插入到预先存在的表中。很有趣,但我认为我上面添加的解决方案更简单,不需要额外的组件。同意,但是,我认为在处理数据时要用它的强类型、易测试性、便携性(即非供应商专用性)和可重用性等来处理数据,这是一个很好的做法。上述示例仅适用于SQLServer的特定版本(即2005 +)。这是一个完整的工作版本,代码中只有1个附加组件。我把它和错误的答案作了比较。是的,您的代码(很好),但不完整,需要生成Linq2Sql模型、配置、Sql Server中的现有表,等等-我的不需要。