2

假设我有以下 xml。

<?xml version="1.0" encoding="utf-8"?>
<importing>
    <table name="Product">
        <records>
            <record>
                <field name="Id" value="1"/>
                <field name="Description" value="iPhone"/>
            </record>
            <record>
                <field name="Id" value="2"/>
                <field name="Description" value="iPad"/>
            </record>
        </records>
    </table>
    <table name="Car">
        <records>
            <record>
                <field name="Id" value="1"/>
                <field name="Name" value="Freelander"/>
                <field name="Brand" value="Land rover"/>
            </record>
            <record>
                <field name="Id" value="2"/>
                <field name="Name" value="Evoque"/>
                <field name="Brand" value="Land Rover"/>
            </record>
        </records>
    </table>
</importing>

我正在尝试实施 3 小时尝试通过此 xml 插入数据库但未成功。通过下面的代码,我得到了代码中注释的结果。

var filePath = "C:\\xml.xml";
XElement xml = XElement.Load(filePath);

foreach (var t in xml.Descendants("table"))
{
    var tableName = t.Attribute("name").Value;  

    var columns = t.Descendants("field").Select(c=>c.Attribute("name").Value).Distinct();

    var values = t.Descendants("field").Select(c=>c.Attribute("value").Value);

    var command = String.Format("insert into {0} ({1}) values ('{2}')",
                            tableName,
                            String.Join(",",columns),
                            String.Join(",",values));


    Console.WriteLine(command);
    //First pass: insert into Product (Id,Description) values ('1,iPhone,2,iPad')
    //Second pass: insert into Car (Id,Name,Brand) values ('1,Freelander,Land rover,2,Evoque,Land Rover')
}

如果这是一个愚蠢的帖子,我很抱歉,但我无法打破这个......我该如何构建propper命令?

提前致谢。

4

2 回答 2

3

您希望SelectManyrecord节点上执行 a (从语义上讲,您希望在 eachrecord中找到 each table,不管有多少)。就是这样:

var commands = (from table in xml.Descendants("table")
                from record in table.Descendants("record")
                let tableName = (string)table.Attribute("name")
                let fields = record.Descendants("field")
                let fieldNames = string.Join(", ", fields.Attributes("name").Select(n => n.Value).ToArray())
                let fieldValues = string.Join(", ", fields.Attributes("value").Select(v => string.Format("'{0}'", v.Value.Replace("'", "''"))).ToArray())
                select string.Format("INSERT INTO {0} ({1}) VALUES ({2})", tableName, fieldNames, fieldValues));

结果值为commands

INSERT INTO Product (Id, Description) VALUES ('1', 'iPhone') 
INSERT INTO Product (Id, Description) VALUES ('2', 'iPad') 
INSERT INTO Car (Id, Name, Brand) VALUES ('1', 'Freelander', 'Land rover') 
INSERT INTO Car (Id, Name, Brand) VALUES ('2', 'Evoque', 'Land Rover') 
于 2012-06-06T06:27:33.357 回答
0

您正在处理的问题是每个表有多个记录,您应该使用union all在一个语句中插入多个记录。下面的代码有点笨拙,但它会做你想做的事。

var doc = XElement.Load(@"C:\xml.xml");
var commands = doc.Descendants("table")
.Select(t=>
{
    var tableName = t.Attribute("name").Value;
    var columns = t.Descendants("field")
                    .Select(e => e.Attribute("name").Value)
                    .Distinct()
                    .ToArray();
    var records = t.Descendants("record")
        .Select(r => r.Descendants("field")
                    .Select(e => e.Attribute("value").Value));
    var recordValues = records.Select(x => String.Join(", ", x.Select(y=>String.Format("'{0}'", y)).ToArray()));
    var selects = recordValues.Select(rv => String.Format("select {0}",rv)).ToArray();
    return String.Format("insert into {0} ({1}) {2}", tableName, 
                        String.Join(", ", columns), 
                        String.Join(" union all ", selects.ToArray()));
});

(格式化的)输出是:

insert into Product (Id, Description) 
select '1', 'iPhone' 
union all 
select '2', 'iPad' 

insert into Car (Id, Name, Brand) 
select '1', 'Freelander', 'Land rover' 
union all 
select '2', 'Evoque', 'Land Rover' 
于 2012-06-06T06:36:34.553 回答