fix crash of sqlite in release mode

This commit is contained in:
gaoyuan
2022-03-12 01:08:17 +08:00
parent 51ac42b9fc
commit c43bfb51be
7 changed files with 118 additions and 103 deletions

View File

@@ -30,7 +30,6 @@ namespace Billing
InitResources();
MainPage = new MainShell();
//Shell.Current.GoToAsync("//Splash");
}
protected override void OnStart()
@@ -39,12 +38,13 @@ namespace Billing
Helper.Debug($"cache folder: {StoreHelper.CacheFolder}");
}
internal static async Task InitializeData()
public static async Task InitializeData()
{
var instance = await StoreHelper.Instance;
await Task.WhenAll(
Task.Run(async () => accounts = await StoreHelper.GetAccountsAsync()),
Task.Run(async () => categories = await StoreHelper.GetCategoriesAsync()),
Task.Run(async () => bills = await StoreHelper.GetBillsAsync()));
Task.Run(async () => accounts = await instance.GetListAsync<Account>()),
Task.Run(async () => categories = await instance.GetListAsync<Category>()),
Task.Run(async () => bills = await instance.GetListAsync<Bill>()));
}
protected override void OnResume()

View File

@@ -39,6 +39,7 @@ namespace Billing
public static void Error(string category, Exception ex)
{
MainThread.BeginInvokeOnMainThread(async () => await Shell.Current.DisplayAlert(category, ex.ToString(), "Ok"));
}
public static void Error(string category, string message)
@@ -139,15 +140,10 @@ namespace Billing
public delegate void PropertyValueChanged<TResult, TOwner>(TOwner obj, TResult old, TResult @new);
}
internal class AsyncLazy<T>
public class AsyncLazy<T>
{
private readonly Lazy<Task<T>> instance;
public AsyncLazy(Func<T> factory)
{
instance = new Lazy<Task<T>>(() => Task.Run(factory));
}
public AsyncLazy(Func<Task<T>> factory)
{
instance = new Lazy<Task<T>>(() => Task.Run(factory));

View File

@@ -28,68 +28,97 @@ namespace Billing.Store
{
return false;
}
if (database != null)
try
{
await database.CloseAsync();
if (database != null)
{
await database.CloseAsync();
}
}
catch (Exception ex)
{
Helper.Error("database.close", ex);
}
try
{
File.Copy(file, path, true);
}
catch (Exception ex)
{
Helper.Error("file.import", ex);
}
try
{
database = new SQLiteAsyncConnection(path,
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
}
catch (Exception ex)
{
Helper.Error("database.connect", ex);
}
File.Copy(file, path, true);
database = new SQLiteAsyncConnection(path,
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
return true;
}
private static readonly AsyncLazy<StoreHelper> Instance = new(async () =>
public static readonly AsyncLazy<StoreHelper> Instance = new(async () =>
{
var instance = new StoreHelper();
await database.CreateTablesAsync<Category, Account, Bill>();
var count = await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Category]");
if (count <= 0)
try
{
// init categories
await database.InsertAllAsync(new List<Category>
await database.CreateTablesAsync<Category, Account, Bill>();
} catch (Exception ex)
{
Helper.Error("database.init.table", ex);
}
try
{
var count = await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Category]");
if (count <= 0)
{
// sample categories
new() { Name = Resource.Clothing, Icon = "clothes" },
new() { Name = Resource.Food, Icon = "food" },
new() { Name = Resource.Daily, Icon = "daily" },
new() { Name = Resource.Trans, Icon = "trans" },
new() { Name = Resource.Entertainment, Icon = "face" },
new() { Name = Resource.Learn, Icon = "learn" },
new() { Name = Resource.Medical, Icon = "medical" },
new() { Name = Resource.OtherSpending, Icon = "plus" },
// init categories
await database.InsertAllAsync(new List<Category>
{
// sample categories
new() { Name = Resource.Clothing, Icon = "clothes" },
new() { Name = Resource.Food, Icon = "food" },
new() { Name = Resource.Daily, Icon = "daily" },
new() { Name = Resource.Trans, Icon = "trans" },
new() { Name = Resource.Entertainment, Icon = "face" },
new() { Name = Resource.Learn, Icon = "learn" },
new() { Name = Resource.Medical, Icon = "medical" },
new() { Name = Resource.OtherSpending, Icon = "plus" },
new() { Type = CategoryType.Income, Name = Resource.Earnings, Icon = "#brand#btc" },
new() { Type = CategoryType.Income, Name = Resource.OtherIncome, Icon = "plus" },
new() { Type = CategoryType.Income, Name = Resource.Earnings, Icon = "#brand#btc" },
new() { Type = CategoryType.Income, Name = Resource.OtherIncome, Icon = "plus" },
// sub-categories
new() { ParentId = 1, Name = Resource.Jewellery, Icon = "gem" },
new() { ParentId = 1, Name = Resource.Cosmetics, Icon = "makeup" },
new() { ParentId = 2, Name = Resource.Brunch, Icon = "brunch" },
new() { ParentId = 2, Name = Resource.Dinner, Icon = "dinner" },
new() { ParentId = 2, Name = Resource.Drinks, Icon = "drink" },
new() { ParentId = 2, Name = Resource.Fruit, Icon = "fruit" },
new() { ParentId = 3, Name = Resource.UtilityBill, Icon = "bill" },
new() { ParentId = 3, Name = Resource.PropertyFee, Icon = "fee" },
new() { ParentId = 3, Name = Resource.Rent, Icon = "rent" },
new() { ParentId = 3, Name = Resource.Maintenance, Icon = "maintenance" },
new() { ParentId = 4, Name = Resource.LightRail, Icon = "rail" },
new() { ParentId = 4, Name = Resource.Taxi, Icon = "taxi" },
new() { ParentId = 5, Name = Resource.Fitness, Icon = "fitness" },
new() { ParentId = 5, Name = Resource.Party, Icon = "party" },
new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Salary, Icon = "#brand#buffer" },
new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Bonus, Icon = "dollar" },
});
// sub-categories
new() { ParentId = 1, Name = Resource.Jewellery, Icon = "gem" },
new() { ParentId = 1, Name = Resource.Cosmetics, Icon = "makeup" },
new() { ParentId = 2, Name = Resource.Brunch, Icon = "brunch" },
new() { ParentId = 2, Name = Resource.Dinner, Icon = "dinner" },
new() { ParentId = 2, Name = Resource.Drinks, Icon = "drink" },
new() { ParentId = 2, Name = Resource.Fruit, Icon = "fruit" },
new() { ParentId = 3, Name = Resource.UtilityBill, Icon = "bill" },
new() { ParentId = 3, Name = Resource.PropertyFee, Icon = "fee" },
new() { ParentId = 3, Name = Resource.Rent, Icon = "rent" },
new() { ParentId = 3, Name = Resource.Maintenance, Icon = "maintenance" },
new() { ParentId = 4, Name = Resource.LightRail, Icon = "rail" },
new() { ParentId = 4, Name = Resource.Taxi, Icon = "taxi" },
new() { ParentId = 5, Name = Resource.Fitness, Icon = "fitness" },
new() { ParentId = 5, Name = Resource.Party, Icon = "party" },
new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Salary, Icon = "#brand#buffer" },
new() { ParentId = 9, Type = CategoryType.Income, Name = Resource.Bonus, Icon = "dollar" },
});
}
}
catch (Exception ex)
{
Helper.Error("database.init.category", ex);
}
return instance;
});
public static async Task<List<Account>> GetAccountsAsync()
{
var instance = await Instance;
return await instance.GetListAsync<Account>();
}
public static async Task<int> SaveAccountItemAsync(Account account)
{
var instance = await Instance;
@@ -101,11 +130,6 @@ namespace Billing.Store
return await instance.DeleteItemAsync(account);
}
public static async Task<List<Bill>> GetBillsAsync()
{
var instance = await Instance;
return await instance.GetListAsync<Bill>();
}
public static async Task<int> SaveBillItemAsync(Bill bill)
{
var instance = await Instance;
@@ -117,11 +141,6 @@ namespace Billing.Store
return await instance.DeleteItemAsync(bill);
}
public static async Task<List<Category>> GetCategoriesAsync()
{
var instance = await Instance;
return await instance.GetListAsync<Category>();
}
public static async Task<int> SaveCategoryItemAsync(Category category)
{
var instance = await Instance;
@@ -137,10 +156,17 @@ namespace Billing.Store
{
if (database == null)
{
database = new SQLiteAsyncConnection(DatabasePath,
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
try
{
database = new SQLiteAsyncConnection(DatabasePath,
SQLiteOpenFlags.ReadWrite |
SQLiteOpenFlags.Create |
SQLiteOpenFlags.SharedCache);
}
catch (Exception ex)
{
Helper.Error("database.ctor.connect", ex);
}
}
}
@@ -178,7 +204,7 @@ namespace Billing.Store
#region Helper
private Task<List<T>> GetListAsync<T>() where T : new()
public Task<List<T>> GetListAsync<T>() where T : new()
{
try
{
@@ -191,7 +217,7 @@ namespace Billing.Store
return default;
}
private Task<int> SaveItemAsync<T>(T item) where T : IIdItem
public Task<int> SaveItemAsync<T>(T item) where T : IIdItem
{
try
{
@@ -211,7 +237,7 @@ namespace Billing.Store
return Task.FromResult(0);
}
private Task<int> DeleteItemAsync<T>(T item) where T : IIdItem
public Task<int> DeleteItemAsync<T>(T item) where T : IIdItem
{
try
{