Linq杂谈之 — Linq导入Excel

     今天接到一个需求,实现一个小功能—导入Excel,想想诸位活跃于.NET平台上的兄弟们,其中应该有相当一部分是从事如信息系统类开发的,所以小弟在这里姑且臭屁一下导入Excel的几种实现方法,如有错误之处,烦请大虾指正。

      第一步呢当然是将Excel中的数据导入进DataTable里面,这一步是很简单的,贴下Code。之后开始讨论如何将DataTable中的这些数据放进数据库里面:

ExpandedBlockStart.gif 代码
//  读取Excel
     public   static  DataTable GetExcelFileData( string  filePath)
    {
        OleDbDataAdapter oleAdp 
=   new  OleDbDataAdapter();
        OleDbConnection oleCon 
=   new  OleDbConnection();
        
string  strCon  =   " Provider=Microsoft.Jet.oleDb.4.0;data source= "   +  filePath  +   " ;Extended Properties='Excel 8.0;HDR=Yes;IMEX=1' " ;
        
try
        {
            DataTable dt 
=   new  DataTable();
            oleCon.ConnectionString 
=  strCon;
            oleCon.Open();
            DataTable table 
=  oleCon.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,  null );
            
string  sheetName  =  table.Rows[ 0 ][ 2 ].ToString();
            
string  sqlStr  =   " Select * From [ "   +  sheetName  +   " ] " ;
            oleAdp 
=   new  OleDbDataAdapter(sqlStr, oleCon);
            oleAdp.Fill(dt);
            oleCon.Close();
            
return  dt;
        }
        
catch  (Exception ex)
        {
            
throw  ex;
        }
        
finally
        {
            oleAdp 
=   null ;
            oleCon 
=   null ;
        }
    }

 

      将DataTable中的数据放到到数据库大概有如下几种实现方法:

1、 Excel导入 — 循环执行插入操作

      这种方法问题颇多,而且效率很低,需要一次次在循环里面执行插入操作,我以往做法是先定义一个Insert语句,然后在循环里面不断的改变Insert 语句中参数的值,执行插入操作,当然这里是使用了Microsoft 提供的SqLHelper的ExecuteNonQuery执行Insert语句。这样做的问题是每一个Insert语句都要执行一次数据库的连接,而这种连接系统维护了一个对象池,每一个连接都先从对象池中取出,如果对象池中没有将创建新对象,并加入对象池。而对象池中的无用对象需要一定的时间后才能释放。所以如果你在短时间内使用的连接很多的话,就有可能造成对象池满员。你再需要连接的话就需要等待释放,而你等待的时间远比释放的时间短,这时系统就会告诉你连接超时,系统抛出异常了,但是即便不抛出异常,这样反复的打开关闭数据的连接,也极大的影响了系统的性能。

      当然也有很多朋友没有使用SqLHelper 去处理这样的数据导入操作,而是将数据库连接放在了循环的方面,等循环里面的Insert语句执行完了,再释放连接,这样做的效率虽比上面的方法效率高些,但同样的问题就是为插入的每个记录执行一次与数据库服务器的往返,如果数据量大的话,对系统的性能同样是一个挑战。

 

2、 Excel导入 — 使用SqlBulkCopy的WriteToServer方法,批量导入数据

      这种做法的缺点是要求EXCEL的格式必须与要导入的Table完全一致而且还要删除多余的Sheet,但是他在性能上优于上面的方法,它可以通过让DataSet或是DataReader中大量的数据通过数据流直接进行装载,然后可以将这些记录添加到指定的数据表中。

      使用方法:

      WriteToServer(DataTable)写入数据表

      WriteToServer(DataRow)批次写入数据行

      WriteToServer(DataTable,DataRowState)按行状态写入数据库表

      WriteToServer(DataReader)写入DataReader对象

     同时SqlBulkCopy对象有个BatchSize这两个属性,BatchSize属性是非常重要的,程序性能如何主要就依靠着它。 BatchSize的意思就是同每一批次中的行数,在每一批次结束时,就将该批次中的行发送到数据库。譬如将BatchSize属性设置成了500,其意思就是每读出500行数据就将他们发送到数据库从而执行批量复制的操作。 BatchSize的默认值是“1”,其意思就是把每一行作为一个批次发送到数据库

     这种做法,也是网上大多数朋友所推荐的的数据移植方法。

3、 Excel导入 — 使用Linq提供的InsertAllOnSubmit方法(这里将详细介绍这种方法)

      InsertAllOnSubmit方法是将一个实体集合添加到datacontext对象中,并在SubmitChange()的时候执行更改,这里我还没来的及做性能测试,有空一定补上,先贴上Code:

ExpandedBlockStart.gif 代码
public   static   void  excelInsertDataForInsert(DataTable dtExcel, string  UserName)
    {
        
using  (MAUCPODataContext db  =   new  MAUCPODataContext())
        {
            Dictionary
< string string >  listPN_Lavel = getPN_Lave();
            var query 
=  from q  in  dtExcel.AsEnumerable()
                        
where   ! string .IsNullOrEmpty(q[ " POPGI_T " ].ToString().Trim())  &&
                              
! string .IsNullOrEmpty(q[ " PONo " ].ToString().Trim())  &&
                              
! string .IsNullOrEmpty(q[ " PN " ].ToString().Trim())  &&
                              
! string .IsNullOrEmpty(q[ " QTY " ].ToString().Trim())  &&
                              
! string .IsNullOrEmpty(q[ " Price " ].ToString().Trim())
                        select 
new
                        {
                            POPGI_T 
=  q[ " POPGI_T " ].ToString().Trim(),
                            PONo 
=  q[ " PONo " ].ToString().Trim(),
                            PN 
=  q[ " PN " ].ToString().Trim(),
                            QTY 
=  q[ " QTY " ].ToString().Trim(),
                            Price 
=  q[ " Price " ].ToString().Trim()
                        };
            List
< MAUCPO >  listEntity  =   new  List < MAUCPO > ();
            
foreach  (var q  in  query)
            {
                MAUCPO Entity 
=   new  MAUCPO();
                Entity.CREATE_t 
=  DateTime.Now;
                Entity.CreateBy 
=  UserName;
                Entity.PN 
=  q.PN;
                Entity.PONo 
=  q.PONo;
                Entity.POPGI_T 
=  DateTime.Parse(q.POPGI_T);
                Entity.Price 
=   decimal .Parse(q.Price);
                Entity.Priority 
=   int .Parse(listPN_Lavel[q.PN]);
                Entity.ProcessFlag 
=   ' N ' ;
                Entity.QTY 
=   int .Parse(q.QTY);
                listEntity.Add(Entity);
            }
            db.MAUCPO.InsertAllOnSubmit(listEntity);
            db.SubmitChanges();
        }
    }

 

      首先需要将你传入的DataTable转换成Enumerable类型,这样才能执行Linq查询,这里where的条件是为了过滤掉DataTable中的空行,select中的内容是取出DataTable中对应列的数据,最后将查询出来的数据转换成泛型类型listEntity,然后调用InsertAllOnSubmit(listEntity)方法,执行批量插入操作。

       至于InsertAllOnSubmit的效率问题,网上也没有搜到太详细的介绍,有时间一定用要测下大数据量下的InsertAllOnSubmit方法效率如何。

 

转载于:https://www.cnblogs.com/yangtongnet/archive/2010/05/24/1742853.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
我们读取和写入Excel 经常使用NPOI工具,如果我们的需求只是需要读取Excel,可以考虑使用LinqToExcel这个组件。这个组件用起来简单、实用、操作方便,而且结合了Linq的查询特性,excel版本不仅支持2003,而且连wps表格都支持(后缀名为.et),csv文件更不在话下了。项目地址:https://github.com/paulyoder/LinqToExcel在使用之前:1.添加引用,通过Nuget 来添加是最方便的了,这里要注意的32/64问题。LinqToExcel.dll Remotion.Data.Linq.dll2.添加命名空间using LinqToExcel;//取得数据,只需要一行代码var execelfile = new ExcelQueryFactory(sample.xls);  如何取到相应的表呢?//紧接楼上var tsheet = excelfile.Worksheet(0);  此时得到是没有进行相应映射的(row)行列集合.一个简单的查询:var excelfile = new ExcelQueryFactory("1.xls"); var tsheet = excelfile.Worksheet(0);<br> //查询30岁以上的人的名字 var query = from p in tsheet where p["Age"].Cast<int>() > 30 select p; foreach (var item in query) { Console.WriteLine("Name is {0}",item[0].Value.ToString()); } Console.Read();    那如何转成相应的实体集合呢? LinqToExcel还具有Mapping 功能,如果类的属性名和Excel里的表头名字如果是英文,(区分大小写)必须与属性名保持一致,支持中文属性名和表头。接着就是一个常遇到的需求,虽然说 Excel 的字段定义是英文,但是读出来的时候必须要是更有意义的字词,这时候就可以利用 LinqToExcel 的 AddMapping 功能来达到。 github:https://github.com/paulyoder/LinqToExcelnuget: https://www.nuget.org/packages/LinqToExcel/ 和 https://www.nuget.org/packages/LinqToExcel_x64/  标签:LinqToExcel

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值