使用 c#ExecuteNonQuery 插入后 MS Access 表未正确刷新

Posted

技术标签:

【中文标题】使用 c#ExecuteNonQuery 插入后 MS Access 表未正确刷新【英文标题】:MS Access table not refreshing correctly after inserting with c# ExecuteNonQuery 【发布时间】:2016-03-07 13:42:37 【问题描述】:

使用外部 c# 应用程序在空的 MS Access 表中插入记录时出现奇怪的行为

我的流程是:

    在 Access 内部,我使用 WshShell 对象执行 c# 控制台应用程序,并带有“waitOnReturn”,因此访问会一直等到 shell 结束。 c#只是连接数据库,执行非查询oledbCommand 当 shell 结束后 Access 恢复时,我尝试读取新记录,但出现错误:没有记录!。但是,如果我手动打开更新的表,记录就在那里!

所以,问题是插入后表格没有更新

这是我在 Access 中的代码

Dim wsh As Object
Dim waitOnReturn As Boolean
Dim errorCode As Integer

Set wsh = CreateObject("WScript.Shell")
waitOnReturn = True
errorCode = wsh.Run("UpdateTable.exe", vbMaximizedFocus, waitOnReturn)

If errorCode <> 0 Then GoTo Error:

Dim dbf As DAO.Database
Dim UpdatedTable As DAO.Recordset

Set dbf = CurrentDb
Set UpdatedTable = dbf.OpenRecordset("MyTable", dbOpenTable)
UpdatedTable.MoveFirst   'ERROR! No records found

但是记录已经插入!他们在那里!事实上,当我收到错误时,Access 会停止并进入调试模式。此时我手动打开“MyTable”并看到数据。然后,我关闭表,并恢复(继续)执行 Access 代码,现在找到记录并且代码运行顺利。

插入记录(本例中只有一条记录)的c#代码是这样的:

string connectionString = "Provider=Microsoft.JET.OLEDB.4.0;data source=" + pathToMyDB;
using (OleDbConnection connection = new OleDbConnection(connectionString))

    connection.Open();
    OleDbCommand command = connection.CreateCommand();
    command.CommandText = "INSERT INTO MyTable ([Field1], [Field2])" + " VALUES (@Param1, @Param2)";
    command.Parameters.Add("@Param1", OleDbType.WChar, 35);
    command.Parameters.Add("@Param2", OleDbType.Date);
    command.Parameters["@Param1"].Value = "my string";
    command.Parameters["@Param2"].Value = DateTime.Now;
    int insertedRowsCount = 0;
    using (OleDbTransaction transaction = connection.BeginTransaction())
    
        command.Transaction = transaction;
        try
        
            insertedRowsCount = command.ExecuteNonQuery();
        
        catch (InvalidOperationException queryExecutionException)
        
            transaction.Rollback();
            ProcessQueryExecutionExceptions(queryExecutionException);
        
        if (insertedRowsCount == 1)
        
            transaction.Commit();
        
        else
        
            transaction.Rollback();
        
    
    command.Parameters.Clear();
    connection.Close();

在 Access 中,可能是什么问题?有没有办法在读取表格之前强制访问刷新或更新表格?我曾尝试在 movefirst 之前关闭并重新打开表,在 shell 执行后插入 DoEvents... 没有任何效果:(

在c#中,代码有问题吗?我是否必须更改连接字符串、命令或事务中的某些内容才能强制更新表?

【问题讨论】:

也许在 Set dbf = ...之后尝试 dbf.TableDefs.Refresh,但不确定... 行:"INSERT INTO MyTable ([Field1], [Field2])" + "VALUES (@Param1, @Param2)";本质上等同于:“INSERT INTO MyTable ([Field1], [Field2]) VALUES (@Param1, @Param2)”;你确定语法是正确的吗?最好的问候, 你为什么只为一个插入命令使用 Transaction?这两个操作的准确时间是什么——一个在 C# 中,另一个在 Access 中?最好的问候, 【参考方案1】:

这个问题并不是真正的 C# 代码问题。只是 Access 会话还不知道由外部进程添加的新记录。来自any 外部进程的INSERT 也会发生同样的事情。我用替代UpdateTable.exe 的VBScript 文件重现了这个问题

此 Access VBA 代码在 UpdatedTable.MoveFirst 处触发错误 3021,“无当前记录” ...

Dim dbf As DAO.Database
Dim UpdatedTable As DAO.Recordset
Dim wsh As Object
Dim waitOnReturn As Boolean
Dim errorCode As Integer

Set wsh = CreateObject("WScript.Shell")
waitOnReturn = True
errorCode = wsh.Run("C:\Windows\SysWOW64\cscript.exe C:\share\Access\vbscript\AdoInsert.vbs", vbMaximizedFocus, waitOnReturn)

'CreateObject("JRO.JetEngine").RefreshCache CurrentProject.Connection
Set dbf = CurrentDb
Set UpdatedTable = dbf.OpenRecordset("tblKaikus", dbOpenTable)
UpdatedTable.MoveFirst ' without RefreshCache -> ERROR 3021, "No current record."

启用CreateObject("JRO.JetEngine").RefreshCache 行使新添加的记录在当前Access 会话中立即可用,因此记录集MoveFirst 方法不会触发错误。

【讨论】:

哇!我忘了将您的完美解决方案标记为答案...对不起:(

以上是关于使用 c#ExecuteNonQuery 插入后 MS Access 表未正确刷新的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ExecuteNonQuery 在 VARCHAR(MAX) 列中插入超过 8000 个字符?

SQLite .NET 插入 ExecuteNonQuery 返回 1

c#: ExecuteNonQuery() 返回 -1

VB.NET SQL Server 插入 - ExecuteNonQuery:连接属性尚未初始化

返回标识值时的 ExecuteScalar 与 ExecuteNonQuery

确定 ExecuteNonQuery 成功执行 [重复]