I am trying to build a very simple Xamarin app that functions similarly to a Exercise/Day Planner. The SQLite database should hold a "Day"s table, and every day should relate to an "Activity"s table which it can query that days "Activity"s. These "Activity"s should be of a certain type, for simplicity lets say either "Walk", "Run" or "Swim". The user should then be able to perform basic CRUD operations on this database to recall previous days and it's associated activities. Ideally, using the SQLiteNetExtensions library, I should be able to make a simple call to retrieve data:
SQLiteAsyncConnection connection = DependencyService.Get<ISQLiteDb>().GetConnection();
var day = await connection.GetWithChildrenAsync<Day>(primaryKey, recursive = true);
Models (simplified):
using SQLite;
using SQLiteNetExtensions.Attributes;
using System;
using System.Collections.Generic;
public class Day {
public Day()
{
Date = DateTime.Now;
}
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public DateTime Date { get; set; }
[OneToMany]
public List<Activity> Activities { get; set; }
}
public abstract class Activity
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ManyToOne(typeof(Day))]
public Day Day { get; set; }
[ForeignKey]
public int DayRefId { get; set; }
public double Input { get; set; }
public virtual double OutputKms { get; set; }
}
public class Walk : Activity
{
public override double OutputKms { get { return Input * 3; } }
}
public class Run: Activity
{
public override double OutputKms { get { return Input * 5; } }
}
public class Swim: Activity
{
public override double OutputKms { get { return Input * 3; } }
}
I am initializing my database with the following code:
using SQLite;
using Xamarin.Forms;
using SQLiteNetExtensionsAsync.Extensions;
public async static Task InitDb()
{
SQLiteAsyncConnection connection = DependencyService.Get<ISQLiteDb>().GetConnection();
await connection.CreateTableAsync<Day>();
await connection.CreateTableAsync<Activity>();
await connection.CreateTableAsync<Walk>();
await connection.CreateTableAsync<Run>();
await connection.CreateTableAsync<Swim>();
}
The problem is that SQLite doesn't like tables based on abstract classes. On the line where I try to create the "Activity" table I get the following compilation error:
Error CS0310 'Activity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T'
I know working with abstract classes is supported in Entity Framework but I would rather stick to using SQLite if possible.
This seems like a simple problem but has been tricky for me to work out without resorting to the simplest poco objects and writing lots of repetitive code.
My question is how can I better restructure my code, what libraries can I use or what kind of mapping can I write in order to implement this. Appreciate any feedback. Thank you!