Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 有什么方法可以加快excel导入的速度吗?_C#_Excel_Import_Parallel Processing - Fatal编程技术网

C# 有什么方法可以加快excel导入的速度吗?

C# 有什么方法可以加快excel导入的速度吗?,c#,excel,import,parallel-processing,C#,Excel,Import,Parallel Processing,我有一个Excel文档,它有大约250000行,需要永远导入。我已经做了许多不同的导入,但是有一些要求: -需要验证每个单元格中的数据 -必须检查数据库中是否存在重复项 -如果存在重复项,请更新条目 -如果不存在条目,请插入新条目 我已经尽可能多地使用了并行化,但是我确信一定有办法让这个导入运行得更快。任何帮助或想法都将不胜感激 请注意,该数据库位于LAN上,是的,我知道我还没有使用参数化sql命令 公共字符串BulkUserInsertAndUpdate() { DateTime startT

我有一个Excel文档,它有大约250000行,需要永远导入。我已经做了许多不同的导入,但是有一些要求: -需要验证每个单元格中的数据 -必须检查数据库中是否存在重复项 -如果存在重复项,请更新条目 -如果不存在条目,请插入新条目

我已经尽可能多地使用了并行化,但是我确信一定有办法让这个导入运行得更快。任何帮助或想法都将不胜感激

请注意,该数据库位于LAN上,是的,我知道我还没有使用参数化sql命令

公共字符串BulkUserInsertAndUpdate()
{
DateTime startTime=DateTime.Now;
尝试
{
进程并行();
WriteLine(“花费的时间:”+(DateTime.Now-startTime));
}
捕获(例外情况除外)
{
返回ex.消息;
}
返回“”;
}
私有IEnumerable可读文档()
{
使用(SpreadsheetDocument SpreadsheetDocument=SpreadsheetDocument.Open(_fileName,false))
{
WorkbookPart WorkbookPart=电子表格文档.WorkbookPart;
工作表ss=workbookPart.Workbook.Subjections().SingleOrDefault(s=>s.Name==“用户”);
if(ss==null)
抛出新异常(“尝试导入文件时出现问题。请确保工作表的名称为:User”);
工作表部件工作表部件=(工作表部件)workbookPart.GetPartById(ss.Id);
OpenXmlReader=OpenXmlReader.Create(工作表部分);
StringTablePart=workbookPart.SharedStringTablePart;
while(reader.Read())
{
if(reader.ElementType==typeof(行))
{
做
{
if(reader.HasAttributes)
{
var rowNum=int.Parse(reader.Attributes.First(a=>a.LocalName==“r”).Value);
如果(rowNum==1)
继续;
var row=(row)reader.LoadCurrentElement();
收益返回行;
}
}while(reader.ReadNextSibling());//跳到下一行
break;//我们只是在所有行中循环,因此无需继续阅读工作表
}
}
}
}
私有void进程并行()
{
//使用ConcurrentQueue启用多线程的安全排队。
var exceptions=新的ConcurrentQueue();
Parallel.ForEach(ReadDocument(),(行,循环状态)=>
{
列表单元格=行。子体().ToList();
if(string.IsNullOrEmpty(GetCellValue(单元格[0],StringTablePart)))
返回;
//验证代码在这里。。。。
尝试
{
使用(SqlConnection connection=newsqlconnection(“用户id=sa;密码=D3vAdm!n@;服务器=196.30.181.143;数据库=TheUnlimitedUSSD;MultipleActiveResultSets=True”))
{
connection.Open();
SqlCommand command=new SqlCommand(“从dbo。[User]中选择计数(*),其中MobileNumber='“+MobileNumber+””,连接);
var userCount=(int)command.ExecuteScalar();
如果(用户计数>0)
{
//更新
command=new SqlCommand(“更新[用户]设置新菜单=“+(newMenuIndicator?”1):“0”)+”,PolicyNumber='“+PolicyNumber+”,Status='“+Status+”,其中MobileNumber='“+MobileNumber+”,连接);
command.ExecuteScalar();
Debug.WriteLine(“updatecmd”);
}
其他的
{
//插入
command=new SqlCommand(“插入dbo.[User](MobileNumber,状态,策略编号,新菜单)值(“+MobileNumber+”,“+Status+”,“+PolicyNumber+”,“+(newMenuIndicator?:“0”)+”,连接);
command.ExecuteScalar();
Debug.WriteLine(“Insert cmd”);
}
}
}
捕获(例外情况除外)
{
例外情况。排队(ex);
Debug.WriteLine(例如消息);
loopState.Break();
}
});
//循环完成后在此处抛出异常。
如果(异常数>0)
抛出新的AggregateException(异常);
}

我建议您检查并行性是否最佳。由于您的瓶颈可能是Excel文件上的磁盘IO和Sql server上的IO,因此我建议可能不是这样。您已经并行化了这两个进程(因此每个进程的速度都降低到最慢的速度);您的并行线程将为数据库而争斗,并可能相互减慢速度。如果你的硬盘跟不上八个线程,那么拥有八个线程是没有意义的——这只会增加开销

我有两个建议。首先:去掉所有的并行性,看看它是否真的有帮助。如果以单线程方式将整个文件解析为内存中的单个队列,那么
        public string BulkUserInsertAndUpdate()
        {
            DateTime startTime = DateTime.Now;
            try
            {
                ProcessInParallel();
                Debug.WriteLine("Time taken: " + (DateTime.Now - startTime));
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            return "";
        }


       private IEnumerable<Row> ReadDocument()
        {
            using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(_fileName, false))
            {
                WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;

                Sheet ss = workbookPart.Workbook.Descendants<Sheet>().SingleOrDefault(s => s.Name == "User");

                if (ss == null)
                    throw new Exception("There was a problem trying to import the file. Please insure that the Sheet's name is: User");

                WorksheetPart worksheetPart = (WorksheetPart)workbookPart.GetPartById(ss.Id);

                OpenXmlReader reader = OpenXmlReader.Create(worksheetPart);
                StringTablePart = workbookPart.SharedStringTablePart;

                while (reader.Read())
                {
                    if (reader.ElementType == typeof(Row))
                    {
                        do
                        {
                            if (reader.HasAttributes)
                            {
                                var rowNum = int.Parse(reader.Attributes.First(a => a.LocalName == "r").Value);

                                if (rowNum == 1)
                                    continue;

                                var row = (Row)reader.LoadCurrentElement();
                                yield return row;
                            }

                        } while (reader.ReadNextSibling()); // Skip to the next row
                        break; // We just looped through all the rows so no need to continue reading the worksheet
                    }
                }
            }
        }

 private void ProcessInParallel()
        {
            // Use ConcurrentQueue to enable safe enqueueing from multiple threads. 
            var exceptions = new ConcurrentQueue<Exception>();


            Parallel.ForEach(ReadDocument(), (row, loopState) =>
                {

                    List<Cell> cells = row.Descendants<Cell>().ToList();

                    if (string.IsNullOrEmpty(GetCellValue(cells[0], StringTablePart)))
                        return;

                    // validation code goes here....


                    try
                    {
                        using (SqlConnection connection = new SqlConnection("user id=sa;password=D3vAdm!n@;server=196.30.181.143;database=TheUnlimitedUSSD;MultipleActiveResultSets=True"))
                        {
                            connection.Open();
                            SqlCommand command = new SqlCommand("SELECT count(*) FROM dbo.[User] WHERE MobileNumber = '" + mobileNumber + "'", connection);
                            var userCount = (int) command.ExecuteScalar();
                            if (userCount > 0)
                            {
                                // update
                                command = new SqlCommand("UPDATE [user] SET NewMenu = " + (newMenuIndicator ? "1" : "0") + ", PolicyNumber = '" + policyNumber + "', Status = '" + status + "' WHERE MobileNumber = '" + mobileNumber + "'", connection);
                                command.ExecuteScalar();
                                Debug.WriteLine("Update cmd");
                            }
                            else
                            {
                                // insert
                                command = new SqlCommand("INSERT INTO dbo.[User] ( MobileNumber , Status , PolicyNumber ,  NewMenu ) VALUES  ( '" + mobileNumber + "' , '" + status + "' ,  '" + policyNumber + "' ,  " + (newMenuIndicator ? "1" : "0") + " )", connection);
                                command.ExecuteScalar();
                                Debug.WriteLine("Insert cmd");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        exceptions.Enqueue(ex);
                        Debug.WriteLine(ex.Message);
                        loopState.Break();
                    }
                });

            // Throw the exceptions here after the loop completes. 
            if (exceptions.Count > 0)
                throw new AggregateException(exceptions);

        }