GetWithChildren<T> retrieves only one layer of child objects

Issue #18 resolved
Marthinus Strydom created an issue

When I call GetAll() on a table, the method retrieves all the rows in the table with each row's child object that it has a relationship with, but the issue I am having is that it retrieves only one layer of child objects, e.g:

Code for GetAll():

public List<T> GetAll()
{
    List<T> list = new List<T>();

    foreach (T item in Database.Table<T>().ToList())
        list.Add(Database.GetWithChildren<T>(
            item.GetType().GetPrimaryKey().GetValue(item)));

    return list;
}

Let's say I have a table [Employee], having a [OneToMany] relationship with table [User], which in correlation has a [ManyToOne] relationship with table [Employee], and I have another table [UserSession], having a [ManyToOne] relationship with table [User], which in correlation has a [OneToMany] relationship with [UserSession].

Now when I call GetAll() on table [Employee] I get the rows' child objects of type [User] but the list of [UserSession]s object is missing.

Hope I made sense, Thank you

Comments (2)

  1. Guillermo GutiƩrrez

    Hi Marthinus,

    I've recently added support for cascade read and write operations. I recommend you to take a look at the Cascade Operations section in the documentation and this post I made in Xamarin forums where I explain in detail how it works. Basically, all read operations now have an optional recursive parameter that will recursively load all properties annotated with the adequate operation.

    A recursive 'GetAll' method is already provided in the library, hopefully you will be able to use it as is. This is the code:

    /// <summary>
    /// Fetches all the entities of the specified type with the filter and fetches all the relationship
    /// properties of all the returned elements.
    /// </summary>
    /// <returns>List of all the elements of the type T that matches the filter with the children already loaded</returns>
    /// <param name="conn">SQLite Net connection object</param>
    /// <param name="filter">Filter that will be passed to the <c>Where</c> clause when fetching
    /// objects from the database. No relationship properties are allowed in this filter as they
    /// are loaded afterwards</param>
    /// <param name="recursive">If set to <c>true</c> all the relationships with
    /// <c>CascadeOperation.CascadeRead</c> will be loaded recusively.</param>
    /// <typeparam name="T">Entity type where the object should be fetched from</typeparam>
    public static List<T> GetAllWithChildren<T>(this SQLiteConnection conn, Expression<Func<T, bool>> filter = null, bool recursive = false) where T : new()
    {
        var elements = conn.Table<T>();
        if (filter != null)
        {
            elements = elements.Where(filter);
        }
    
        var list = elements.ToList();
    
        foreach (T element in list)
        {
            conn.GetChildren(element, recursive);
        }
    
        return list;
    }
    

    Hope it helps.

  2. Log in to comment