Mas*_*oud 8 c# mysql oledb ms-access odbc
情况:我正在创建一个自动化任务,查询MySQL(通过ODBC)并使用OLEDB将结果集插入MS Access数据库(.mdb).
代码:
OleDbConnection accCon = new OleDbConnection();
OdbcCommand mySQLCon = new OdbcCommand();
try
{
//connect to mysql
Connect();
mySQLCon.Connection = connection;
//connect to access
accCon.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
@"Data source= " + pathToAccess;
accCon.Open();
var cnt = 0;
while (cnt < 5)
{
if (accCon.State == ConnectionState.Open)
break;
cnt++;
System.Threading.Thread.Sleep(50);
}
if (cnt == 5)
{
ToolBox.logThis("Connection to Access DB did not open. Exit Process");
return;
}
} catch (Exception e)
{
ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
}
OleDbCommand accCmn = new OleDbCommand();
accCmn.Connection = accCon;
//access insert query structure
var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
foreach (var table in tblNQuery)
{
try
{
mySQLCon.CommandText = table.Value;
//executed mysql query
using (var dataReader = mySQLCon.ExecuteReader())
{
//variable to hold row data
var rowData = new object[dataReader.FieldCount];
var parameters = "";
//read the result set from mysql query
while (dataReader.Read())
{
//fill rowData with the row values
dataReader.GetValues(rowData);
//build the parameters for insert query
for (var i = 0; i < dataReader.FieldCount; i++)
parameters += "'" + rowData[i] + "',";
parameters = parameters.TrimEnd(',');
//insert to access
accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
try
{
accCmn.ExecuteNonQuery();
}
catch (Exception exc)
{
ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message + "\\n\\tInsert query -> " + accCmn.CommandText );
}
parameters = "";
}
}
}
catch (Exception e)
{
ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
}
}
Disconnect();
accCmn.Dispose();
accCon.Close();
Run Code Online (Sandbox Code Playgroud)
问题:
内存使用率非常高(300MB ++),而MS Access文件大小不会不断变化!似乎插入缓存数据而不是将其保存到磁盘.
这很慢!我知道我的查询会在几秒钟内执行,但插入过程需要很长时间.
我已经尝试在MS Access中使用预准备语句并将值作为参数而不是字符串concat插入以创建插入查询.但是我收到此异常消息:
条件表达式中的数据类型不匹配.
有谁知道如何解决这个问题或者有更好的方法?
您可以创建一个VBA宏,它使用DoCmd.TransferDatabase方法将数据通过ODBC提取到Access数据库中.它可能会更快更简单.
要从外部程序或计划任务运行VBA代码,只需启动Access以使用/ x命令行开关打开文件,它将在启动时运行导入宏.虽然GB数据仍需要一段时间.我发现David Catriel的一篇文章实现了这种方法.
更好的选择是使用不同的数据库引擎后端,如SQL Server Express的免费版本.那么你有更多的选择,它更强大.如果您需要MS Access表单和报表,则可以在使用SQL Server时创建ADP项目文件,也可以使用链接表来获取数据.您甚至可以使用Access作为MySQL数据库的前端,而不是复制所有数据,如果这样可以满足您的要求.
您可以转向SQL Server Integration Services(SSIS),而不是编写代码,并在午餐前完成.它可以作为Visual Studio的扩展,以防您在已经使用SQL Server的计算机上没有它.
使用SSIS,您可以创建可重用的SSIS包,可以从命令行或计划任务触发.本指南介绍了如何将数据从MySQL提取到SQL Server,但SQL Server部分应该很容易用Access替换.
谢谢大家的回答。我刚刚发现我的代码中的主要问题。大量内存使用的原因(问题#1)是 ODBC 正在缓存来自 MySQL 的数据,而不管 C# 方法 (DataReader) 如何。通过选中 DSN 设置中的复选框可以解决该问题Don't cache results of forward-only cursors。这也使得该过程稍微快一些(30%)。然而,更具体的方法仍然是 Brian Pressler 和 Egil Hansen 所建议的。但由于他们需要软件安装和/或迁移计划,最简单的方法是坚持这段代码。
| 归档时间: |
|
| 查看次数: |
701 次 |
| 最近记录: |