Aleksandar Balnozan
Aleksandar Balnozan

Reputation: 39

Xamarin Forms SQLite instance crash

I'm learning about Xamarin Forms, FreshMVVM and SQLite. I'll give my best to explain the issue.

I'm trying to implement simple Login/Register pages. So far I've followed this Microsoft documentation. I do understand that the problem is when I call await UserDatabase.Instance in LoginPageModel.cs, the application just freeze and I am unable to understand why. But please take a note that when I try to call await UserDatabase.Instance in RegisterPageModel.cs it works as intended. Only when I try to call it in LoginModelPage.cs it crashes

UserDatabase.cs

public class UserDatabase
    {
        private static SQLiteAsyncConnection Database;

        public static readonly AsyncLazy<UserDatabase> Instance = new AsyncLazy<UserDatabase>(async () =>
        {
            var instance = new UserDatabase();
            CreateTableResult result = await Database.CreateTableAsync<User>();
            return instance;
        });

        public UserDatabase()
        {
            Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
        }

        public Task<User> LogInUserAsync(string username, string password)
        {
            return Database.Table<User>().Where(x => x.UserName == username && x.Password == password).FirstOrDefaultAsync();
        }

        public Task<int> SaveUserAsync(User user)
        {
            if (user.UserId != 0)
            {
                return Database.UpdateAsync(user);
            }
            else
            {
                return Database.InsertAsync(user);
            }
        }
}

And I have LoginPage.cs and RegisterPage.cs:

RegisterPageModel.cs

 public class RegisterPageModel : FreshBasePageModel
    {
        public Command RegisterCommand { get; }

        public string UsernameEntry { get; set; }

        public string PasswordEntry { get; set; }

        public string ConfirmPasswordEntry { get; set; }

        public RegisterPageModel()
        {
            RegisterCommand = new Command(() =>
            {
                // if passwords does not match, show alert. Otherwise register user.
                if (PasswordEntry == ConfirmPasswordEntry)
                {
                    User = new User
                    {
                        UserName = UsernameEntry,
                        Password = PasswordEntry
                    };
                    SaveUser(User);

                    CoreMethods.PushPageModel<LoginPageModel>();
                }
                else
                {
                    Application.Current.MainPage.DisplayAlert("Try again", "Passwords does not match!", "Ok");
                }
            });
        }

        private async void SaveUser(User user)
        {
            UserDatabase database = await UserDatabase.Instance;
            await database.SaveUserAsync(user);
        }
}

LoginPageModel.cs

public class LoginPageModel : FreshBasePageModel
    {
        public Command RegisterCommand { get; }

        public string UsernameEntry { get; set; }

        public string PasswordEntry { get; set; }

        public Command LoginCommand { get; set; }

        public LoginPageModel()
        {
            // When we press Register button, redirect us to the register page
            RegisterCommand = new Command(() =>
            {
                CoreMethods.PushPageModel<RegisterPageModel>();
            });

            // When we press on Login button login user and redirect to the main page
            LoginCommand = new Command(() =>
            {
                if (LoginUser().Result)
                {
                    CoreMethods.PushPageModel<MainPageModel>();
                }
                else
                {
                    Application.Current.MainPage.DisplayAlert("Login Failed", "Incorrect Username or Password!", "Ok");
                }

            });
        }

        private async Task<bool> LoginUser()
        {
            UserDatabase database = await UserDatabase.Instance;
            User user = await database.LogInUserAsync(UsernameEntry, PasswordEntry);
            if (user == null)
            {
                // store Userdetails
                Application.Current.Properties["UserDetail"] = JsonConvert.SerializeObject(user);

                // Set it to true 
                Application.Current.Properties["IsLoggedIn"] = bool.TrueString;

                return true;
            }
            else
            {
                return false;
            }
        }
    }

Upvotes: 0

Views: 239

Answers (1)

Aleksandar Balnozan
Aleksandar Balnozan

Reputation: 39

To resolve this issue I needed to change LoginUser Method

From this:

        private async Task<bool> LoginUser()
        {
            UserDatabase database = await UserDatabase.Instance;
            User user = await database.LogInUserAsync(UsernameEntry, PasswordEntry);
            if (user == null)
            {
                // store Userdetails
                Application.Current.Properties["UserDetail"] = JsonConvert.SerializeObject(user);

                // Set it to true 
                Application.Current.Properties["IsLoggedIn"] = bool.TrueString;

                return true;
            }
            else
            {
                return false;
            }
        }

To this:

        private async void LoginUser()
        {
            UserDatabase database = await UserDatabase.Instance;
            User user = await database.LogInUserAsync(UsernameEntry, PasswordEntry);
            if (user == null)
            {
                // store Userdetails
                Application.Current.Properties["UserDetail"] = JsonConvert.SerializeObject(user);

                // Set it to true 
                Application.Current.Properties["IsLoggedIn"] = bool.TrueString;
            }
            else
            {
                await Application.Current.MainPage.DisplayAlert("Login Failed", "Incorrect Username or Password!", "Ok");
            }
        }

Upvotes: 1

Related Questions