在App中我們通常不會實時獲取服務器數據,會在用戶手機中保存歷史數據,這個時候就需要用到數據庫SQLite,由於微軟的封裝,在Xamarin中操作SQLite非常簡單,類似EF的操作。
1、我們需要在共享項目的nuget中引用 sqlite-net-pcl 和 SQLitePCLRaw.core

2、由於Android和IOS的SQLite數據庫存放位置不一樣,所以我們需要在共享項目中抽象一個接口ISQLite,然后分別在Android和IOS項目中實現接口,初始化數據庫連接
共享項目代碼如下:
public interface ISQLite { SQLiteAsyncConnection GetAsyncConnection(); }
Android項目代碼如下:
[assembly: Xamarin.Forms.Dependency(typeof(SQLiteAndroid))]//注入SQLiteAndroid namespace Mobile.Droid.Helpers { public class SQLiteAndroid : ISQLite { private static string path; private static SQLiteAsyncConnection connectionAsync; private static readonly object locker = new object(); private static readonly object pathLocker = new object(); private static string GetDatabasePath() { lock (pathLocker) { if (path == null) { string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // Documents folder path = Path.Combine(documentsPath, GlobalSetting.SqliteFilename); } } return path; } public SQLiteAsyncConnection GetAsyncConnection() { lock (locker) { if (connectionAsync == null) { var dbPath = GetDatabasePath(); connectionAsync = new SQLiteAsyncConnection(dbPath); } } return connectionAsync; } } }
IOS項目代碼如下:
[assembly: Xamarin.Forms.Dependency(typeof(SQLiteIOS))] namespace Mobile.iOS.Helpers { public class SQLiteIOS : ISQLite { private static string path; private static SQLiteAsyncConnection connectionAsync; private static readonly object locker = new object(); private static readonly object pathLocker = new object(); private static string GetDatabasePath() { lock (pathLocker) { if (path == null) { var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder var libraryPath = Path.Combine(documentsPath, "..", "Library"); // Library folder path = Path.Combine(libraryPath, GlobalSetting.SqliteFilename); } } return path; } public SQLiteAsyncConnection GetAsyncConnection() { lock (locker) { if (connectionAsync == null) { var dbPath = GetDatabasePath(); connectionAsync = new SQLiteAsyncConnection(dbPath); } } return connectionAsync; } } }
3、在共享項目中創建SqliteHelper
using Microsoft.AppCenter.Crashes; using Mobile.Interfaces; using SQLite; using System; using Xamarin.Essentials; using Xamarin.Forms; namespace Mobile.Helpers { public class SqliteHelper { static SqliteHelper baseSqlite; public static SqliteHelper Current { get { return baseSqlite ?? (baseSqlite = new SqliteHelper()); } } public SQLiteAsyncConnection db; public SqliteHelper() { if (db == null) db = DependencyService.Get<ISQLite>().GetAsyncConnection(); } /// <summary> /// 創建或者更新Sqlite數據庫表 /// 在App啟動的時候執行該方法,sqlite-net-pcl會根據實體類創建對應的表,如果實體類有更新,表結構也會更新,如果表結構沒變,則不進行操作,sqlite-net-pcl會自動判斷 /// </summary> public async void CreateOrUpdateAllTablesAsync() { await db.CreateTablesAsync<TestTable, UserInfo>(); } } }
4、Sqlite的增刪改查操作
public async Task<Model.News> QueryNew(int id) { return await db.Table<Model.News>().Where(a => a.Id == id).FirstOrDefaultAsync(); } public async Task<List<Model.News>> QueryNews(int pageSize) { return await db.Table<Model.News>().OrderByDescending(a => a.DateAdded).Skip(0).Take(pageSize).ToListAsync(); } public async Task<List<Model.News>> QueryNewsByRecommend(int pageSize) { return await db.Table<Model.News>().Where(a => a.IsRecommend).OrderByDescending(a => a.DateAdded).Skip(0).Take(pageSize).ToListAsync(); } public async Task<List<Model.News>> QueryNewsByWorkHot(int pageSize, DateTime startdate) { return await db.Table<Model.News>().Where(a => a.IsHot && a.DateAdded > startdate).OrderByDescending(a => a.DateAdded).Skip(0).Take(pageSize).ToListAsync(); } public async Task UpdateNews(List<Model.News> lists) { foreach (var item in lists) { await QueryNew(item.Id).ContinueWith(async (results) => { if (results.Result == null) { try { await db.InsertAsync(item); } catch (Exception ex) { Crashes.TrackError(ex); } } else { await UpdateNew(item); } }); } } public async Task UpdateNew(Model.News model) { try { await db.UpdateAsync(model); } catch (Exception ex) { Crashes.TrackError(ex); } }
參考代碼: https://github.com/JoesWeek/XamCnblogs
