2012-06-06 3 views
2

Предположим, у меня есть следующий xml.Linq to 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') 
} 

Я сожалею, если это тупой пост, но я не мог разорвать этот ... Как я могу построить команду Проппер?

Заранее спасибо.

+0

Где проблема? Вызывается ли какое-либо исключение? Что не работает, импорт xml или вход в базу данных? – webber2k6

ответ

3

Вы хотите сделать SelectMany на record узле (семантический, вы хотите, чтобы каждые record найденных в каждом 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') 
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'