从Xamarin Android迁移SQLite数据库至.NET Maui应用的问题
计划将现有Xamarin Android应用升级为.NET Maui版本,需保留用户已有的SQLite数据库。Xamarin应用使用SQLiteOpenHelper,读取到的user_version为8;但在Maui应用中执行相同查询PRAGMA user_version时,返回的user_version为0。两个应用使用相同的连接字符串:Data Source=/data/user/0/<my app id>/databases/my_database.db。
Xamarin 相关代码
public partial class BaseHandler : Android.Database.Sqlite.SQLiteOpenHelper { private const string DB_NAME = "my_database.db"; Android.Content.Context _context; private Android.Database.Sqlite.SQLiteDatabase _db = null; public BaseHandler (IContext context) : base (context.AppContext, DB_NAME, null, DB_VERSION) { _context = context.AppContext; _db = WritableDatabase; var version = ExecuteScalar(@"PRAGMA user_version"); } public override void OnCreate (Android.Database.Sqlite.SQLiteDatabase db) { var sqls = this.CreateDatabaseSql(); this.DoSql(db, sqls); var version = ExecuteScalar(@"PRAGMA user_version"); } }
Maui 相关代码(使用sqlite-net-pcl包)
public async Task<IEnumerable<MyItem>> GetAllItems() { var sql = "SELECT * FROM MY_ITEMS;"; try { await using var cnn = GetCnn(); return await cnn.QueryAsync<MyItem>(sql); } catch (Exception ex) { throw ex; } }
确认
user_version的查询方式是否正确
你提供的Maui代码仅展示了查询表数据的逻辑,未包含获取user_version的代码。如果用QueryAsync执行PRAGMA user_version,会因为该查询返回单个值而非结果集,导致无法正确解析,最终得到默认值0。正确的做法是使用ExecuteScalarAsync获取单值结果:await using var cnn = GetCnn(); var userVersion = await cnn.ExecuteScalarAsync<long>("PRAGMA user_version");检查应用包名与签名一致性
Android应用的沙箱权限由包名和签名共同决定,如果Maui应用的包名或签名与原Xamarin应用不一致,会无法访问原数据库所在的沙箱目录。即使连接字符串路径相同,实际访问的也会是Maui应用沙箱内的新数据库(此时user_version自然为0)。必须确保Maui应用的包名、签名与原Xamarin应用完全一致。注意SQLite库的版本与行为差异
Xamarin的SQLiteOpenHelper依赖Android系统自带的SQLite库,而sqlite-net-pcl通常绑定独立的SQLite版本。两者对数据库版本的处理逻辑有差异:SQLiteOpenHelper会在构造时自动将DB_VERSION赋值给user_version,而sqlite-net-pcl不会自动处理版本同步。如果数据库确实存在,可尝试手动读取并验证版本,必要时通过PRAGMA user_version = 8手动设置(需确保数据库结构匹配)。验证数据库连接的权限与模式
确保sqlite-net-pcl的连接使用读写模式,可在连接字符串中显式指定:Data Source=/data/user/0/<my app id>/databases/my_database.db;Mode=ReadWrite同时检查数据库文件的权限,确保Maui应用拥有读写该文件的权限(包名一致的情况下通常无需额外配置)。
内容的提问来源于stack exchange,提问作者Cliffhanger

