In Visual studio 2017, I created a Cross-Platform Mobile App (Xamarin.Forms)
- NETStandard 2.0
- Microsoft.Data.Sqlite.Core 2.2.0
- Microsoft.EntityFrameworkCore 2.2.0
- Microsoft.EntityFrameworkCore.Sqlite 2.2.0
- Microsoft.EntityFrameworkCore.Tools 2.2.0
I did a code first migration to Sqlite with Entity Framework following the advice of Mark Smith. All tables are created successfully. The database was seeded.
When I try to get the ItemsViewModel (see code below), I get the following exception (after 20 seconds) on the line --> List item list1 = await db.Person.ToListAsync();
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 14: 'unable to open database file'. at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db) at Microsoft.Data.Sqlite.SqliteConnection.Open() at System.Data.Common.DbConnection.OpenAsync(CancellationToken cancellationToken)
Strangely enough my test method TestSqLiteDataStoreAsync (see code below) correctly returns the expected list of items without causing an error.
Also the fact that it takes 20 seconds to get the error message indicates that it was able to find the database. When you have a wrong db Name/path the error pops immediately.
Below you find the relevant code. If you need anything more, let me know. Any help on how to continue debugging is also welcome. Or has anyone a basic working UWP code example I can compare mine with ? I have added a solution on Github called 'temp' with the needed database. If one might have the time to try to reproduce the error :) Thx.
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ItemsPage : ContentPage
{
ItemsViewModel viewModel;
public ItemsPage()
{
InitializeComponent();
//1 code starts here
BindingContext = viewModel = new ItemsViewModel();
}
async void OnItemSelected(object sender, SelectedItemChangedEventArgs args)
{
var item = args.SelectedItem as Item;
if (item == null)
return;
await Navigation.PushAsync(new ItemDetailPage(new ItemDetailViewModel(item)));
ItemsListView.SelectedItem = null;
}
async void AddItem_Clicked(object sender, EventArgs e)
{
await Navigation.PushModalAsync(new NavigationPage(new NewItemPage()));
}
//adding 'async' did not solve the problem
protected async override void OnAppearing()
{
base.OnAppearing();
if (viewModel.Items.Count == 0)
//2 code continues here
viewModel.LoadItemsCommand.Execute(null);
}
}
public class ItemsViewModel : BaseViewModel
{
public ObservableCollection<Item> Items { get; set; }
public Command LoadItemsCommand { get; set; }
public ItemsViewModel()
{
Title = "Browse";
Items = new ObservableCollection<Item>();
//3 code continues here
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
}
//My test method
public async Task<List<Item>> TestSqLiteDataStoreAsync()
{
SqLiteDataStore SqLiteDataStore = new SqLiteDataStore();
return await SqLiteDataStore.GetItemsAsync(false);
}
async Task ExecuteLoadItemsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
Items.Clear();
//4 code continues here
var items = await DataStore.GetItemsAsync(true);
foreach (var item in items)
{
Items.Add(item);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
public class SqLiteDataStore : IDataStore<Item>
{
public string dbFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
public string fileName = "TestSqLite.db";
public SqLiteDataStore() { }
public async Task<List<Item>> GetItemsAsync(bool forceRefresh = false)
{
try
{
using (var db = new Models.MyContext(Path.Combine(dbFolder, fileName)))
{
List<Person> list1 = new List<Person>();
List<Item> list2 = new List<Item>();
//5 I get the error here
list1 = await db.Person.ToListAsync();
foreach (Person person in list1)
{
Item item = new Item(person);
list2.Add(item);
}
return list2;
}
}
catch (Exception)
{
throw;
}
}
public async Task<bool> AddItemAsync(Item item)
{
throw new NotImplementedException();
}
public Task<bool> UpdateItemAsync(Item item)
{
throw new NotImplementedException();
}
public Task<bool> DeleteItemAsync(string id)
{
throw new NotImplementedException();
}
public Task<Item> GetItemAsync(string id)
{
throw new NotImplementedException();
}
}


