Xamarin Forms(Android)中EF Core创建SQLite遇Disk I/O Error 10(266)求助
我之前在搭建Xamarin Forms Android应用时也碰到过一模一样的SQLite I/O错误,结合你已经排查过的点,给你几个针对性的解决方案,应该能帮你搞定:
1. 修复SQLitePCL的初始化流程
你当前只设置了SQLite provider,但缺少关键的初始化步骤。SQLitePCL需要先初始化底层依赖才能正常工作,修改MainActivity里的代码:
// 先初始化SQLitePCL依赖 SQLitePCL.Batteries_V2.Init(); // 再设置provider(部分新版本可能不需要这行,先保留) SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_e_sqlite3()); string databasePath = Application.ApplicationContext.GetDatabasePath("target.db").AbsolutePath;
之前的应用可能因为使用的SQLitePCL版本不需要显式初始化,但新版本必须加上这一步。
2. 调整DbContext的生命周期注册
你当前把TargetContext注册成了SingleInstance,但DbContext是轻量级、设计为短生命周期的对象,单例会导致数据库连接长期被持有,很容易引发I/O冲突。修改Autofac的注册代码:
// 把SingleInstance改成InstancePerLifetimeScope,确保每个作用域有独立的DbContext实例 containerBuilder.RegisterType<TargetContext>() .As<ITargetContext>() .WithParameter("databasePath", _databasePath) .InstancePerLifetimeScope();
3. 确保数据库目录存在且可写
虽然GetDatabasePath理论上会自动创建目录,但偶尔会因为系统权限或初始化时机问题导致目录不存在。在获取路径后手动检查并创建目录:
string databasePath = Application.ApplicationContext.GetDatabasePath("target.db").AbsolutePath; var dbDir = Path.GetDirectoryName(databasePath); if (!Directory.Exists(dbDir)) { Directory.CreateDirectory(dbDir); }
4. 延迟数据库初始化的时机
你当前在App.xaml.cs的早期阶段执行EnsureCreated,这时候Android应用的文件系统可能还没完全准备好。把初始化逻辑移到App的OnStart方法,或者MainActivity的OnResume方法里:
// 在App.xaml.cs的OnStart中执行 protected override void OnStart() { base.OnStart(); using var scope = AppContainer.Container.BeginLifetimeScope(); var context = scope.Resolve<ITargetContext>(); context.Initialize(); }
5. 排除EF Core之外的SQLite连接问题
先跳过EF Core,直接用原生SqliteConnection测试路径是否可访问,这样能快速定位是EF的问题还是SQLite本身的问题:
// 在MainActivity里添加测试代码 try { using var conn = new Microsoft.Data.Sqlite.SqliteConnection($"Filename={databasePath}"); conn.Open(); Log.Debug("SQLiteTest", "连接成功!"); conn.Close(); } catch (Exception ex) { Log.Error("SQLiteTest", $"连接失败:{ex.Message}"); }
如果这个测试也报错,那问题就出在SQLite的配置或系统权限上,和EF Core无关。
6. 检查NuGet包版本兼容性
确保所有EF Core和SQLite相关的NuGet包版本完全一致,比如:
Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore.SqliteSQLitePCLRaw.bundle_green(或你使用的SQLitePCL包)
版本不匹配是这类I/O错误的常见诱因,尤其是升级了部分包但没同步升级其他依赖的时候。
按照上面的步骤逐一排查,应该能解决你遇到的Disk I/O Error 10问题。我之前就是因为DbContext单例和SQLitePCL初始化不全导致的这个错误,调整后就正常了。
内容的提问来源于stack exchange,提问作者Nick77

