Search code examples
android-sqlitemaui

Sqlite (Android) : How to use object as attribute in another object?


I have a class, "Course", which I recently changed to consolidate some attributes into another class, "Assessment". The attributes for Course now include "public Assessment OA" and "public Assessment PA". Attempting to initialize the database now throws the following error: "System.NotSupportedException: 'Don't know about C971.Models.Assessment'" I've seen several other people hit this error from what appear to be completely different reasons. Any thoughts on how I can correct this?

Alternatively, is this just very wrong? I may be expecting functionality that doesn't exist. Would it be more correct to use a FK to reference the Assessment objects in their own table?

public class Course
{
    [PrimaryKey, AutoIncrement] public int id { get; set; }
    public int termId { get; set; }
    public DateTime startDate { get; set; }
    public DateTime endDate { get; set; }
    public DateTime dueDate { get; set; }
    public courseStatus status { get; set; } = courseStatus.planned;
    public string name { get; set; } = "Placeholder Name";
    public string notes { get; set; } = string.Empty;
    public bool alertStartDate { get; set; } = false;
    public bool alertEndDate { get; set; } = false;
    public bool isSetOA { get; set; } = false;
    public bool isSetPA { get; set; } = false;
    public Assessment OA { get; set; }
    public Assessment PA { get; set; }
    public string courseInfo { get; set; } = string.Empty;
    public string instructorName { get; set; } = string.Empty;
    public string instructorPhone { get; set; } = string.Empty;
    public string instructorEmail { get; set; } = string.Empty;
    public enum courseStatus { inProgress, completed, dropped, planned }
}
public class Assessment
{
    [PrimaryKey, AutoIncrement] public int id { get; set; }
    public string name { get; set; } = string.Empty;
    public DateTime startDate {  get; set; }
    public DateTime endDate { get; set; }
    public DateTime dueDate { get; set; }
    public string info { get; set; } = string.Empty;
    public bool startAlert { get; set; } = false;
    public bool endAlert { get; set; } = false;
}
private static SQLiteAsyncConnection? Database;
static async Task Init()
{
    Debug.WriteLine("TermTrackerDB.Init start");
    try
    {
        if (Database is not null) //Don't create DB if already exists
            return;

        Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
        //var result = await Database.CreateTableAsync<Course>();
        await Database.CreateTableAsync<Assessment>();
        await Database.CreateTableAsync<Course>();
        await Database.CreateTableAsync<Term>();
        
    }
    catch (Exception e)
    {
        Debug.WriteLine($"Try Catch: TermTrackerDB Init; Exception: {0}", e);
        throw;
    }
    
}

I'm uncertain if these other examples are related, but I've linked them here for context:

Xamarin.Forms Sqlite-net NotSupportedException on ManyToOne relationship "Don't know about <model>"

SQLite doesn't know about class


Solution

  • You can try to add a foreign Key ( public int CourseId { get; set; }) for Assessment.cs

    public class Assessment
    {
        [PrimaryKey, AutoIncrement] 
        public int id { get; set; }
    
        public string name { get; set; } = string.Empty;
        public DateTime startDate {  get; set; }
        public DateTime endDate { get; set; }
        public DateTime dueDate { get; set; }
        public string info { get; set; } = string.Empty;
        public bool startAlert { get; set; } = false;
        public bool endAlert { get; set; } = false;
         
        //add a ForeignKey
        [ForeignKey(typeof(Course))]
        public int CourseId { get; set; }
    }
    

    And add [OneToOne]( or OneToMany) attribute for properties Assessment OA and Assessment PA onCourse.cs.

    public class Course
    {
        [PrimaryKey, AutoIncrement] 
        public int id { get; set; }
        public int termId { get; set; }
    
        [OneToOne]
        public Assessment OA { get; set; }
    
        [OneToOne]
        public Assessment PA { get; set; }
    
    }
    

    Note:

    1.Please install nuget SQLiteNetExtensions

    2.I don't know the relationship of your data tables, you can adjust the mapping relationship according to your needs(OneToOne ,OneToMany, ManyToOne).

    3.You can also refer to this thread: how to access items from one model inside another when I save the items.