0

I am very new to all of this (coding in general, C#, .NET MAUI, MVVM practices, SQLite) so excuse me if my inexperience shows.

The context

I have an app that has a database with a table Cars.

To make it easier for the user, I want to create page where they can create records for said table. One of the options would be to choose a brand for the car type they're trying to add. I wish to accomplish this by giving them a dropdown (which is linked to a table Brands).

I want the Brands table to contain a default set of records BUT also give users the option to add more.

Question

How do I populate that Brands table with a default set of records? Are there better ways to achieve this besides using a table?

The result

A Brands table containing a default set of records which can also be expanded by the user.

What am I using

I am using Visual Studio 2022, with SQLite-net (https://github.com/praeclarum/sqlite-net) and .NET MAUI.

Should I use a different method? Do I populate the table via the class Brands (which the table is based on)? Which seems inefficient (for this purpose) since it's static so you'd have to redeploy to make changes right?

Please do let me know if you need more information.

6
  • 2
    you need to create a default SQLIte db containing the data you want and include it in your project. At runtime you will copy that existing db to a writable folder. Alternately, you can just include a hardcoded set of data in your app and use that to populate the Brands table at runtime Commented May 21 at 19:30
  • I see! Do you have/know any resources that explain this well? Commented May 21 at 19:45
  • 1
    google.com/… Commented May 21 at 19:53
  • Thank you so so much. It took me a while to understand what was happening but now I got what I needed. Took me more effort than it probably should haha! Commented May 21 at 23:56
  • Database designers usually have a DDL schema which has both the CREATE TABLE and the INSERT INTO commands which is used to initialize and populate a database. You can ship the DDL with your application, I would imagine in the Raw folder and you would just load and execute the SQL commands on startup. If you do not require persistence, you can consider using ":memory:" to create a blank in-memory database everytime your application starts. Commented May 22 at 1:38

1 Answer 1

0

This is my first time answering a question on Stack Overflow, so my inexperience will also show! However, I've worked with .NET MAUI, SQLite-net, and MVVM, so I can help.

You're on the right track with your initial thoughts.

How do I populate that Brands table with a default set of records? Are there better ways to achieve this besides using a table?

Using a table for Brands is absolutely the correct approach, especially since you want users to be able to add more. This provides persistence and flexibility. Storing them directly in the database allows for easy management, querying.

To populate the Brands table with default records, you should use a data seeding approach during your database initialisation. This ensures that the default brands are present when the application is run for the first time (or if the database is reset), but also allows for user additions without overwriting the defaults.

Should I use a different method? Do I populate the table via the class Brands (which the table is based on)? Which seems inefficient (for this purpose) since it's static so you'd have to redeploy to make changes right?

You are absolutely correct. Populating the table directly from a static list within the Brand class itself (or any fixed part of your compiled code) is inefficient and not architecturally correct.

Solution (One of many ways, but you could look into separating this as you learn more!)
Create your Database Initialization & Seeding Logic

public class DatabaseService
{
    private SQLiteAsyncConnection _database;
    private string _dbPath; // Store the database path

    public DatabaseService()
    {
        _dbPath = Path.Combine(FileSystem.AppDataDirectory, "MyCars.db3");
    }

    public async Task InitAsync()
    {
        if (_database != null)
            return; // Already initialized

        _database = new SQLiteAsyncConnection(_dbPath);

        // 1. Create the Brand table if it doesn't exist
        await _database.CreateTableAsync<Brand>();

        // 2. Seed default brands if the table is empty
        await SeedDefaultBrandsAsync();
    }

    private async Task SeedDefaultBrandsAsync()
    {
        var brandCount = await _database.Table<Brand>().CountAsync();
        if (brandCount == 0) // Only seed if the table is empty
        {
            var defaultBrands = new List<Brand>
            {
                new Brand { Name = "Toyota" },
                new Brand { Name = "Honda" },
                new Brand { Name = "Ford" },
                // Add more default brands here
            };
            await _database.InsertAllAsync(defaultBrands);
            Console.WriteLine("Default brands seeded successfully!");
        }
        else
        {
            Console.WriteLine("Brands table already has data, skipping seeding.");
        }
    // Example: Method to get all brands (for your dropdown)
    public async Task<List<Brand>> GetBrandsAsync()
    {
        await InitAsync(); // Ensure DB is initialized
        return await _database.Table<Brand>().ToListAsync();
    }

    // Example: Method to save a new brand (for user additions)
    public async Task<int> SaveBrandAsync(Brand brand)
    {
        await InitAsync();
        if (brand.Id == 0)
        {
            return await _database.InsertAsync(brand);
        }
        else
        {
            return await _database.UpdateAsync(brand);
        }
    
}
}

Inside MauiProgram.cs

        // Register your DatabaseService as a singleton
        // A singleton means only one instance of DatabaseService exists throughout the app's lifetime.
        builder.Services.AddSingleton<DatabaseService>();

Usage

public partial class AddCarViewModel : ObservableObject
{
    private readonly DatabaseService _databaseService;

    [ObservableProperty]
    private ObservableCollection<Brand> _availableBrands;

    [ObservableProperty]
    private Brand _selectedBrand; // For your dropdown selection

    public AddCarViewModel(DatabaseService databaseService) // DI provides the instance
    {
        _databaseService = databaseService;
        LoadBrandsCommand.Execute(null); // Call this to load brands when the ViewModel is created
    }

    [RelayCommand]
    private async Task LoadBrands()
    {
        // 1. Ensure the database is initialized (will also seed if empty)
        await _databaseService.InitAsync();
        // 2. Get the list of brands from the database
        var brands = await _databaseService.GetBrandsAsync();
        AvailableBrands = new ObservableCollection<Brand>(brands);
    }

    // You would have other commands for saving cars, etc.
}

I hope this helps- any questions feel free to ask, I'll check back on this thread.

I recommend checking out James, he has a great starter guide to C# MAUI, covering everything you asked and more!

Sign up to request clarification or add additional context in comments.

1 Comment

This is a very thorough written out way for me to approach this * with * explanation! Thank you very much!!! The answer that Jason provided me has already helped me get on my way but regardless it is nice to see an in app approach as to delivering a filled database with the app. Both would give me the result I am looking for. In terms of James, I am watching his stuff already, it is what got me into learning this all in the first place! :D

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.