【问题标题】:EF Core JET: AccessViolationException when 'updating' changed objects in MS AccessEF Core JET:在 MS Access 中“更新”更改的对象时出现 AccessViolationException
【发布时间】:2020-01-31 23:31:52
【问题描述】:

我正在使用EF Core 2.2.xEntityFrameworkCore.Jet 构建一个.NET Core 3 控制台应用程序,以对访问数据库(mdb) 执行一些通用读写操作。正如文档所说,我正在为x86 编译。目标是将丢失的大量数据从旧系统迁移到新系统(同步数据)。

我已经搭建了数据库,我可以完美地读取数据库,但是一旦我去更新一个实体,我就会遇到访问冲突异常:

代码示例(缩写):

public void SetSynced(int id)
{
    var item = _db.Products.Where(x => x.Id == id).Single();
    item.NeedsSyncing = false;
    _db.SaveChanges();
}

当这个代码被命中时,会出现以下异常(没有内部异常)

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

我不明白为什么会这样,因为我可以完美地读取数据库,它只在写入时这样做。

我尝试使用以下连接字符串(驱动程序),但两者的最终结果相同:

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\database.mdb;Jet OLEDB:Database Password = password;`
Provider=Microsoft.jet.oledb.4.0;Data Source=C:\\database.mdb;Jet OLEDB:Database Password = password;

x64 上运行时,阅读工作正常,但出现以下异常:

System.Data.OleDb.OleDbException (0x80004002): No error message available, result code: E_NOINTERFACE(0x80004002).

我在这里迷路了,在黑暗中寻找。有没有人对我在哪里看有经验/想法?

2020 年 2 月 2 日更新: 我尝试使用 OleDb 手动连接并运行查询以查看它带给我的位置。下面的代码有效。当我用上面的代码切换它时,它又失败了。

db = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\\database.mdb;Jet OLEDB:Database Password = password");
db.Open();
var command = new OleDbCommand($"UPDATE Products SET NeedsSyncing = 0 WHERE Id= 1", db);
var res = command.ExecuteNonQuery();

设置JetConfiguration.ShowSqlStatements = true 后,我得到了以下堆栈跟踪:

ExecuteDbDataReader==========
UPDATE [Products] SET [PictureName] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;


@p1(Int32) = 1
@p0(String) = 'notfound.jpg'
Fatal error. 0xC0000005
   at System.Data.Common.UnsafeNativeMethods+ICommandWithParameters.SetParameterInfo(IntPtr, IntPtr[], System.Data.OleDb.tagDBPARAMBINDINFO[])
   at System.Data.OleDb.OleDbCommand.ApplyParameterBindings(ICommandWithParameters, System.Data.OleDb.tagDBPARAMBINDINFO[])
   at System.Data.OleDb.OleDbCommand.CreateAccessor()
   at System.Data.OleDb.OleDbCommand.InitializeCommand(System.Data.CommandBehavior, Boolean)
   at System.Data.OleDb.OleDbCommand.ExecuteCommand(System.Data.CommandBehavior, System.Object ByRef)
   at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(System.Data.CommandBehavior, System.String)
   at System.Data.OleDb.OleDbCommand.ExecuteReader(System.Data.CommandBehavior)
   at System.Data.OleDb.OleDbCommand.ExecuteDbDataReader(System.Data.CommandBehavior)
   at System.Data.Common.DbCommand.ExecuteReader(System.Data.CommandBehavior)
   at System.Data.Jet.JetCommand.InternalExecuteDbDataReader(System.String, System.Data.CommandBehavior)
   at System.Data.Jet.JetCommand.ExecuteDbDataReader(System.Data.CommandBehavior)
   at System.Data.Common.DbCommand.ExecuteReader()
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.Execute(Microsoft.EntityFrameworkCore.Storage.IRelationalConnection, Microsoft.EntityFrameworkCore.Diagnostics.DbCommandMethod, System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.Object>)
   at Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteReader(Microsoft.EntityFrameworkCore.Storage.IRelationalConnection, System.Collections.Generic.IReadOnlyDictionary`2<System.String,System.Object>)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(Microsoft.EntityFrameworkCore.Storage.IRelationalConnection)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(Microsoft.EntityFrameworkCore.DbContext, System.ValueTuple`2<System.Collections.Generic.IEnumerable`1<Microsoft.EntityFrameworkCore.Update.ModificationCommandBatch>,Microsoft.EntityFrameworkCore.Storage.IRelationalConnection>)
   at Microsoft.EntityFrameworkCore.Storage.Internal.NoopExecutionStrategy.Execute[[System.ValueTuple`2[[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.ValueTuple`2<System.__Canon,System.__Canon>, System.Func`3<Microsoft.EntityFrameworkCore.DbContext,System.ValueTuple`2<System.__Canon,System.__Canon>,Int32>, System.Func`3<Microsoft.EntityFrameworkCore.DbContext,System.ValueTuple`2<System.__Canon,System.__Canon>,Microsoft.EntityFrameworkCore.Storage.ExecutionResult`1<Int32>>)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(System.Collections.Generic.IEnumerable`1<Microsoft.EntityFrameworkCore.Update.ModificationCommandBatch>, Microsoft.EntityFrameworkCore.Storage.IRelationalConnection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(System.Collections.Generic.IReadOnlyList`1<Microsoft.EntityFrameworkCore.Update.IUpdateEntry>)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(System.Collections.Generic.IReadOnlyList`1<Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry>)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at Cashmaster.BackgroundWorker.Services.CashMasterService.Crash()

Nuget 包 + 版本(与 Jet 相关):

Microsoft.EntityFrameworkCore 2.2.6
EntityFrameworkCore.Jet 2.2.0
System.Data.OleDb 4.7.0

.NET Core 3.1 上运行这一切。

【问题讨论】:

  • 关于访问冲突异常这是一个 jet oledb 提供程序错误。不时发生。您可以尝试压缩数据库。您还可以尝试使用其他版本的 jet oledb 提供程序或使用 x64 版本。有时与多线程有关。也尝试在 system.data.jet 中禁用或启用连接池
  • @bubi 我已经尝试在连接字符串中使用OLE DB Services=1 以及-10,但没有任何变化。虽然我使用了很多异步方法,但是将所有内容都转移到同步工作方式并不能解决我的问题。我已经启用和禁用了连接池(当使用JetConfiguration.UseConnectionPooling 参数将 dbcontext 添加到 di 容器时),但这没有任何变化。有没有一种简单的方法可以在 x86 和 x64 上安装 jetdriver v14?
  • 额外信息:我还安装了 access 2016 数据工具(因此升级到 Microsoft.ACE.OLEDB.16.0,但这在 x86 上引发了同样的异常(x64 不适用于读取)。跨度>
  • @bubi 我已经验证了常规的旧 oledbconnection 可以解决问题,因此它可能确实与多线程有关。我正在使用 MFT 提供的“简单”DI,例如ASP.NET。如何进一步调试此问题?
  • 您是指旧的 OLEDB 提供程序还是使用旧的 .Net 框架并使用旧的 OleDbConnection?

标签: ef-core-2.2 jet-ef-provider


【解决方案1】:

Migrate the x86 specific structures to AnyCPU for System.Data.OleDb #32509 在 GitHub 上跟踪了该问题,并由社区成员通过Fix x86 packing issues in System.Data.OleDb #33899 修复。

要解决项目中的问题,请将最新版本的 EF Core 3.1.x(当前为 3.1.10)与最新版本的 EntityFrameworkCore.Jet(当前预发布 3.1.0-alpha.4)一起使用与System.Data.OleDb 发布5.0.0

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    相关资源
    最近更新 更多