Search code examples
sqlitexamarinormxamarin.androidmany-to-many

Create many-to-many table in constructor crashes as second table hasn't been created yet


I decided to implement database in Xamarin.Android that stores data on the device and very occasionally gets it from the server. Anyway I wanted to create database from scratch if it stores no tables.

My issue is that I have models that are used to create new tables, but those models are connected by relation many-to-many with themselves and that crashes transaction during first try to create table.

I know that is related to constraints but I have no idea how to refactor app to avoid this. I couldn't find any reply related to this directly.

Any thoughts?

class Database
{
    private SQLiteConnection _connection;

    public Database()
    {
        _connection = new SQLite().GetConnection();
        LogHelper.CustomLog("SQL Created");
        _connection.BeginTransaction();
        _connection.CreateTable<Dish>(); //there is the issue
        _connection.CreateTable<Ingredient>();
        _connection.Commit();
        LogHelper.CustomLog("SQL DBs created");

        AddIngredient(new Ingredient() { Id = 1, Name = "apple", Vegetarian = false, GlutenFree = false });
        AddDish(new Dish() { Id = 1, Calories = "23", Desc = "test", Name = "oranges", Time = 30, Ingredients = GetIngredientList() });
    }
}


public class Dish
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Desc { get; set; }
    public int    Time { get; set; }
    //public string Rating { get; set; }
    public string Calories { get; set; }

    [ForeignKey(typeof(Ingredient))]
    public int IngredientId { get; set; }
    [ManyToMany(typeof(Dish))]
    public List<Ingredient> Ingredients { get; set; }

    public override string ToString()
    {
        return string.Format("[Dish: Id={0}, Name={1}, Desc={2}, Time={3}, 
Ingredients={4}, Calories={6}]",
            Id, Name, Desc, Time, Ingredients, Calories);
    }
}

public class Ingredient
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public bool Vegetarian { get; set; }
    public bool GlutenFree { get; set; }

    [ForeignKey(typeof(Dish))]
    public int DishId { get; set; }
    [ManyToMany(typeof(Ingredient))]
    public List<Dish> Dishes { get; set; }
}

Solution

  • Check out SQLite-Net extensions for many to many relationships.

    Quotes from the documentation:

    Many-to-many relationships cannot be expressed using a foreign key in one of the entities, because foreign keys represent X-to-one relationships. Instead, an intermediate entity is required. This entity is never used directly in the application, but for clarity's shake, SQLite-Net Extensions will never create a table that the user hasn't defined explicitly.