因为项目上的一个小需求,需要将SQLite数据库中的数据导入到Access数据库。最近两天查了一些资料,用C# winform实现这个功能。本文记录实现的流程。
开发环境(C# winform):
1. visual studio 2019
2. .net framework 4.7.2
3. SQLite数据库(test.db)
4. access 2007数据库(data.accdb)
5. SQLite数据表tn_member,表结构内容如下图:
实现流程:
1. 连接SQLite数据库,读取表 tn_member 的表结构
有关读取SQLite表结构,可以参考这篇文章“C#对SQLite数据表的操作(创建、删除、查看表结构)”,此处不再多说。
2. 根据 tn_member 表结构,生成对应的Access数据表结构,然后连接Access数据库,创建 tn_member表
根据上一步读取的SQLite表结构,读取每个字段的字段名、字段类型等信息,生成对应的Access表结构sql语句,此处需要注意的是要对照好SQLite和Access的字段类型即可,代码片段如下:
private bool createAccessTableBySqliteTable(string tableName)
{
// 读取sqlite数据表结构
SqliteHelper sqliteHelper = new SqliteHelper(this.sqliteFilename, this.sqlitePassword);
DataTable table = sqliteHelper.TableSchema(tableName);
// 拼接access创建表sql
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append($"create table {tableName} (");
foreach (DataRow r in table.Rows)
{
sqlBuilder.Append($"{r["name"]}");
sqlBuilder.Append($" ");
switch (r["type"].ToString().ToLower())
{
case "integer":
sqlBuilder.Append($"Integer");
break;
case "real":
sqlBuilder.Append($"Double");
break;
case "text":
sqlBuilder.Append($"Text");
break;
case "DATETIME":
sqlBuilder.Append($"DateTime");
break;
default:
sqlBuilder.Append($"Text");
break;
}
sqlBuilder.Append($",");
}
sqlBuilder.Remove(sqlBuilder.Length - 1, 1);
sqlBuilder.Append(")");
string createSql = sqlBuilder.ToString();
try
{
string connStr = getAccessConnStr(this.accessFilename);
OleDbConnection oldDbConn = new OleDbConnection(connStr);
oldDbConn.Open();
OleDbCommand cmd = new OleDbCommand(createSql, oldDbConn);
cmd.ExecuteNonQuery();
cmd.Dispose();
oldDbConn.Close();
oldDbConn.Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "提示");
return false;
}
return true;
}
3. 逐条读取SQLite表数据,生成Access插入语句,将数据插入Access表中
创建好Access表结构后,插入数据就比较简单。只需要逐条读取SQLite表数据,再对照Access的数据类型,将值进行转换,然后插入Access数据库。代码片段如下:
/// <summary>
/// 将SQLite的表数据转存到access数据库对应的表中
/// </summary>
/// <param name="in_table">sqlite表</param>
/// <param name="accessFileName">access数据库文件名</param>
/// <param name="accessTableName">access数据库表名</param>
/// <param name="accessPassword">access数据库密码</param>
/// <returns></returns>
private bool transSqliteData2AccdbTable(DataTable in_table, string accessFileName, string accessTableName, string accessPassword = "")
{
string connStr = getAccessConnStr(accessFileName, accessPassword);
using (OleDbConnection oldDbConn = new OleDbConnection(connStr))
{
oldDbConn.Open();
for (int n = 0; n < in_table.Rows.Count; n++)
{
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.Append($"INSERT INTO {accessTableName}(");
StringBuilder colBuilder = new StringBuilder();
StringBuilder valBuilder = new StringBuilder();
for (int m = 0; m < in_table.Columns.Count; m++)
{
if (!string.IsNullOrEmpty(in_table.Rows[n][m].ToString()))
{
colBuilder.Append(in_table.Columns[m].ColumnName).Append(",");
string val = "";
switch (in_table.Columns[m].DataType.ToString())
{
case "System.Int64":
case "System.Int32":
case "System.Double":
val = in_table.Rows[n][m].ToString();
break;
case "System.DateTime":
case "System.String":
val = "'" + in_table.Rows[n][m].ToString() + "'";
break;
default:
val = "'" + in_table.Rows[n][m].ToString() + "'";
break;
}
valBuilder.Append(val).Append(",");
}
}
colBuilder.Remove(colBuilder.Length - 1, 1);
valBuilder.Remove(valBuilder.Length - 1, 1);
sqlBuilder.Append(colBuilder.ToString()).Append(") VALUES ( ");
sqlBuilder.Append(valBuilder.ToString()).Append(")");
OleDbCommand inst = new OleDbCommand(sqlBuilder.ToString(), oldDbConn);
inst.ExecuteNonQuery();
}
oldDbConn.Close();
}
return true;
}
因为要实现自动同步,因此本人的代码中又将每次读取的id进行保存,以便关闭程序后下次自动续传。