起因

这是在某企内部招聘时遇到的面试题,google了一下发现还是一道基础题。没接触过 c# 还上班一个月没碰过代码的我只好硬着头皮通宵学习。
网上大多都是只负责插入数据,没有读取 Excel 部分。最开始尝试用 COM 中的 Microsoft.Office 包读表,但实在是太慢了,光是读取三列 10w 条数据就花了上万秒甚至还没读取完整。

代码

所需 nuget 包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System;
using System.Collections.Generic;
using System.IO;
using MySqlConnector;
using NPOI.XSSF.UserModel;

class Column
{
public string col1;
public string col2;
}

class insertInfo
{
// 数据库地址与 Excel 文件路径
static string database = "Server=;User ID=;Password=;Database=";
static string file = ".xlsx";

static void Main(string[] args)
{
// 计时器
int startTime = Environment.TickCount;
List<Column> list = new List<Column>();

// NPOI
using (var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
{
/*
* HSSFWorkbook:是操作Excel97-2003版本,扩展名为.xls。
* XSSFWorkbook:是操作Excel2007版本开始,扩展名为.xlsx。
*/
var doc = new XSSFWorkbook(fs);
// 薄
var sheet = doc.GetSheetAt(0);
if (sheet == null)
{
Console.WriteLine("[{0}] 无法打开工作表", DateTime.Now.ToString());
Console.ReadLine();
return;
}

Console.WriteLine("[{0}] 开始读取", DateTime.Now.ToString());
// 循环到该薄内最后一行
for (int i = 0; i < sheet.LastRowNum + 1; i++)
{
var column = sheet.GetRow(i);
// 第1列数据为空时跳过
if (column == null || String.IsNullOrWhiteSpace(column.GetCell(0).StringCellValue))
{
continue;
}

list.Add(new Column
{
// 获取第()列数据并去除空白字符
col1 = column.GetCell(1).StringCellValue.Trim(),
col2 = column.GetCell(2).StringCellValue.Trim()
});
}
Console.WriteLine("[{0}] 读取完毕", DateTime.Now.ToString());
}

// SQL
// 连接数据库
using (var conn = new MySqlConnection(database))
{
conn.Open();
using (var command = new MySqlCommand())
{
command.Connection = conn;
for (int i = 0; i < list.Count;)
{
// 开始事务
var t = conn.BeginTransaction();
command.Transaction = t;
try
{
// 每1000条Sql语句重启事务
for (int j = 0; j < 1000 && i < list.Count - 1; j++, i++)
{
command.Parameters.Clear();
command.CommandText = "INSERT INTO test (col1, col2) VALUES (@val1, @val2);";
command.Parameters.AddWithValue("val1", list[i].col1);
command.Parameters.AddWithValue("val2", list[i].col2);

command.ExecuteNonQuery();
}
t.Commit();
}
catch (System.Data.SqlClient.SqlException E)
{
t.Rollback();
throw new Exception(E.Message);
}
}
}
}
int endTime = Environment.TickCount;
int runTime = endTime - startTime;
Console.WriteLine("写入完毕,用时: [{0}] 秒", runTime / 1000);
}
}

效果

mysql