2010-09-08 173 views
4

我正在构建一个离线的C#应用​​程序,它将数据从电子表格导入并存储在我创建的SQL数据库中(项目内)。通过一些研究,我已经能够使用一些可以导入静态表的代码,将它们放入与工作表中的列完全相同的数据库中从excel导入数据到多个表

我在做的是将特定列转到他们正确的表基于名称这样我有正确的数据库设计,而不是只有一个巨大的表来存储所有内容

下面是我用于将一些静态字段导入到一个表中的代码,我想能够将导入的数据分割成多个

这样做的最佳方法是什么?

public partial class Form1 : Form 
    { 
     string strConnection = ConfigurationManager.ConnectionStrings 
     ["Test3.Properties.Settings.Test3ConnectionString"].ConnectionString; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void button1_Click(object sender, EventArgs e) 
     { 


      //Create connection string to Excel work book 
      string excelConnectionString = 
      @"Provider=Microsoft.Jet.OLEDB.4.0; 
      Data Source=C:\Test.xls; 
      Extended Properties=""Excel 8.0;HDR=YES;"""; 

      //Create Connection to Excel work book 
      OleDbConnection excelConnection = new OleDbConnection(excelConnectionString); 

      //Create OleDbCommand to fetch data from Excel 
      OleDbCommand cmd = new OleDbCommand 
      ("Select [Failure_ID], [Failure_Name], [Failure_Date], [File_Name], [Report_Name], [Report_Description], [Error] from [Failures$]", excelConnection); 

      excelConnection.Open(); 
      OleDbDataReader dReader; 
      dReader = cmd.ExecuteReader(); 

      SqlBulkCopy sqlBulk = new SqlBulkCopy(strConnection); 
      sqlBulk.DestinationTableName = "Failures"; 
      sqlBulk.WriteToServer(dReader); 

     } 

回答

0

如果你正在寻找一个更代码相关的回答,您可以使用以下方法来修改你的代码难以列名/不同的表的工作:

private void button1_Click(object sender, EventArgs e) 
    { 
     //Create connection string to Excel work book 
     string excelConnectionString = 
     @"Provider=Microsoft.Jet.OLEDB.4.0; 
     Data Source=C:\Test.xls; 
     Extended Properties=""Excel 8.0;HDR=YES;"""; 

     //Create Connection to Excel work book 
     OleDbConnection excelConnection = new OleDbConnection(excelConnectionString); 

     //Create OleDbCommand to fetch data from Excel 
     OleDbCommand cmd = new OleDbCommand 
     ("Select [Failure_ID], [Failure_Name], [Failure_Date], [File_Name], [Report_Name], [Report_Description], [Error] from [Failures$]", excelConnection); 

     excelConnection.Open(); 

     DataTable dataTable = new DataTable(); 
     dataTable.Columns.Add("Id", typeof(System.Int32)); 
     dataTable.Columns.Add("Name", typeof(System.String)); 
     // TODO: Complete other table columns 
     using(OleDbDataReader dReader = cmd.ExecuteReader()) 
     { 
      DataRow dataRow = dataTable.NewRow(); 
      dataRow["Id"] = dReader.GetInt32(0); 
      dataRow["Name"] = dReader.GetString(1); 
      // TODO: Complete other table columns 
      dataTable.Rows.Add(dataRow); 
     } 

     SqlBulkCopy sqlBulk = new SqlBulkCopy(strConnection); 
     sqlBulk.DestinationTableName = "Failures"; 
     sqlBulk.WriteToServer(dataTable); 
    } 

现在你可以控制的名字列的数据以及数据被导入到的表格。 SqlBulkCopy适用于插入大量数据。如果你只有少量的行,你最好创建一个标准的数据访问层来插入你的记录。

2

您可以尝试使用ETL(提取,转换,加载)架构:

提取物:一类会在你知道如何一起工作块打开该文件并获取所有数据(通常你需要单列从文件中解析出来,并将其数据解析为一个POCO对象,其中包含保存相关数据的字段),然后将这些数据放入其他工作进程可以从中获取的队列中。在这种情况下,您可能首先要做的事情是让Excel打开文件并将其重新保存为CSV文件,以便将其重新打开为流程中的基本文本并高效地将其切断。你也可以读取列名并建立一个“映射字典”;这个列被命名,所以它转到数据对象的这个属性。这个过程应该尽可能快地发生,它失败的唯一原因是因为行的格式与给定文件结构的内容不匹配。

变换:一旦文件的内容被提取到基本行的实例中,执行任何验证,计算或其他业务规则来将文件中的行变成符合您的领域模型的一组领域对象。这个过程可以像你需要的那样复杂,但是它也应该如你所愿,在遵守你的需求中给出的所有业务规则的同时,也应该如此简单。加载:现在,您已经在自己的域对象中获得了一个对象图,您可以使用您调用的用于处理以其他方式创建的域对象的相同持久性框架。这可以是基本的ADO,像NHibernate或MSEF这样的ORM,或者对象知道如何坚持自己的Active Record模式。它不是批量加载,但它可以节省您不得不实施完全不同的持久性模型,以便将基于文件的数据存入数据库。

ETL工作流可以帮助您将重复性任务分解为简单的工作单元,并且从那里您可以识别花费大量时间并考虑并行流程的任务。

或者,您可以在调用批量插入例程来处理数据之前,通过检测要使用的列并将它们排列成与批量输入规范相匹配的格式来获取文件并按其格式。这个文件处理程序可以做你想做的任何事情,包括将数据分成几个文件。但是,这是一个能够同时处理整个文件的大流程,并且优化或并行处理的机会有限。但是,如果您的加载机制很慢,或者您拥有大量易于消化的数据,则它可能比设计良好的ETL更快。

在任何情况下,我都会尽快离开Office格式并转换为纯文本(或XML)格式,并且我会毫不犹豫地避免必须在服务器上安装Office。如果有任何方式,您可以要求文件在加载之前以CSV等一些易于解析的格式存储,那么效果会更好。在服务器上安装Office是一件非常糟糕的事情,而在服务器应用程序中的OLE操作并不会好得多。该应用程序将非常脆弱,任何Office想告诉你的东西都会导致应用程序挂起,直到登录到服务器并清除对话框。

+0

优秀的答案。 – 2010-09-08 18:57:26

+0

@KeithS:我正在考虑这种方法,在一张表中有多个表的excel。你有什么建议吗? – 2012-04-26 09:13:53

0

如果您只对文本感兴趣(而不是格式化等),或者您可以将excel文件保存为CSV文件,然后解析CSV文件,这很简单。

0

根据程序的生命周期,我会推荐两种选择之一。

  1. 如果程序被短暂使用,或通常是“扔掉”的项目,我会建议一系列的分析程序和输入数据到使用标准的SQL一些字符串另一套表根据需要处理。

  2. 如果该计划将坚持更长的时间和/或在日常工作中发现更多用途,我会建议实施类似于@KeithS推荐的解决方案。通过一系列处理数据的明确步骤,可以获得很大的灵活性。更具体地说,.NET Entity Framework可能非常适合。作为奖励,如果您还不熟悉这方面的内容,您可能会发现在第一次使用ORM进行第一次操作时,您会发现在边界(xls - > sql - >等)之间处理数据的很多事情,例如EF。