0

I'm working on a Xamarin mobile app using .NET Framework, and SQLite.NET-PCL. My XAML Form uses MVVM architecture, on my main form I am attempting to display all movies in a ListView, first I made sure the view itself works correctly, and now I am attempting to connect it to my DB service. When the DB service initializes and attempts to create any table using CreateTableAsyc() the program gets stuck in that function even after appearing to succeed.

Initially, I thought it was due to using created classes as properties, which SQLite does not support, so I corrected that. Next, I checked if it was due to not using Hardware Acceleration so I enabled it. I then attempted to debug using ContinueWith() and printed the result to the debug console, it says 'Migrated' but never exits the function. Xamarin XAML Hot Reload then times out. What could be causing this?

Example of one of the Types:

using SQLite;

public class Movie
{
    public Movie() {}

    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime Length { get; set; }
}

DBService

using Xamarin.Essentials;

public static class DBService
{
    private static SQLiteAsyncConnection dbConn;

    public static async Task Init()
    {
        if (dbConn != null)
        {
            return;
        }

        string databasePath = Path.Combine(FileSystem.AppDataDirectory, "Movies.db");
        dbConn = new SQLiteAsyncConnection(databasePath, false);

        await dbConn.CreateTableAsync<Movie>().ContinueWith(results =>
        {
            Debug.WriteLine(results.Result.ToString()); // This prints migrated
        });
        Debug.WriteLine("After table created"); // This never prints
    }

    public static async Task<IEnumerable<Movie>> GetMovies()
    {
        await Init();
        return await dbConn.Table<Movie>().ToListAsync();
    }
}

MovieViewModel (View Model for main view)

public class MovieViewModel
{
    public List<Movie> Movies { get; set; }
    
    public MovieViewModel ()
    {
        Movies = (List<Movie>)DBService.GetMovies().Result;
    }
}
1
  • 1
    don't call an async method in the VM constructor Commented Oct 26, 2022 at 20:29

1 Answer 1

1

Wrap awaitable in something that runs after constructor returns:

MainThread.BeginInvoke(async () => Movies = (await DBService.GetMovies()).ToList() );

Optional:
GetMovies could return a List, to match Movies declaration. Then would not need .ToList(), or (List<Movie>) cast:

public static async Task<List<Movie>> GetMovies() { ... }
MainThread.BeginInvoke(async () => Movies = await DBService.GetMovies() );
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the solution, and the optional suggestion, I ended up switching to an ObservableCollection to capture events when it's updated, so it doesn't cast I'm using the constructor with the IEnumerable argument.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.