mbdavid / LiteDB

LiteDB - A .NET NoSQL Document Store in a single data file
http://www.litedb.org
MIT License
8.52k stars 1.24k forks source link

Add "Cascading Include" to "DbRef for cross references" docs section #322

Closed johnkea closed 7 years ago

johnkea commented 7 years ago

Dear Mauricio David, it is quite confusing at the beginning how one can realize Cascading Include in LiteDB. It might quite obvious for you as for creator but for many people who has no time to trace the sources or who are dealing with C# not so long time it is quite puzzling. I suggest to extend "DbRef for cross references" section on main page and add there more complex example of several levels of referencing such that people might have immediate idea how to do it. E.g.: `

namespace _01_simple {
using System;
using LiteDB;

public class A {
    public int Id { set; get; }
    public string Name { set; get; }
    public B B_Ref { set; get; }
}
public class B {
    public int Id { set; get; }
    public string Name { set; get; }
    public C C_Ref { set; get; }
}
public class C {
    public int Id { set; get; }
    public string Name { set; get; }
    public D D_Ref { set; get; }
}
public class D {
    public int Id { set; get; }
    public string Name { set; get; }
}

class Program {
    static void Main(string[] args) {
        test_01();
    }

    static string NameInDb<T>() {
        var name = typeof(T).Name + "s";
        return name;
    }

    static void test_01()   {
        if (System.IO.File.Exists(@"MyData.db"))
            System.IO.File.Delete(@"MyData.db");

        using (var db = new LiteDatabase(@"MyData.db")) {
            var As = db.GetCollection<A>(NameInDb<A>());
            var Bs = db.GetCollection<B>(NameInDb<B>());
            var Cs = db.GetCollection<C>(NameInDb<C>());
            var Ds = db.GetCollection<D>(NameInDb<D>());

            LiteDB.BsonMapper.Global.Entity<A>().DbRef(x => x.B_Ref, NameInDb<B>());
            LiteDB.BsonMapper.Global.Entity<B>().DbRef(x => x.C_Ref, NameInDb<C>());
            LiteDB.BsonMapper.Global.Entity<C>().DbRef(x => x.D_Ref, NameInDb<D>());

            var d = new D { Name = "I am D." };
            var c = new C { Name = "I am C.", D_Ref = d };
            var b = new B { Name = "I am B.", C_Ref = c };
            var a = new A { Name = "I am A.", B_Ref = b };

            Ds.Insert(d);
            Cs.Insert(c);
            Bs.Insert(b);
            As.Insert(a);
        }

        using (var db = new LiteDatabase(@"MyData.db")) {
            var As = db.GetCollection<A>(NameInDb<A>());
            var Bs = db.GetCollection<B>(NameInDb<B>());
            var Cs = db.GetCollection<C>(NameInDb<C>());
            var Ds = db.GetCollection<C>(NameInDb<D>());

            LiteDB.BsonMapper.Global.Entity<A>().DbRef(x => x.B_Ref, NameInDb<B>());
            LiteDB.BsonMapper.Global.Entity<B>().DbRef(x => x.C_Ref, NameInDb<C>());
            LiteDB.BsonMapper.Global.Entity<C>().DbRef(x => x.D_Ref, NameInDb<D>());

            var all_a = As
                .Include(x => x.B_Ref)
                .Include(x => x.B_Ref.C_Ref)
                .Include(x => x.B_Ref.C_Ref.D_Ref)
                .FindAll();

            foreach (var a in all_a) {
                if (a.B_Ref == null) throw new Exception("B_Ref");
                if (a.B_Ref.C_Ref == null) throw new Exception("C_Ref");
                if (a.B_Ref.C_Ref.D_Ref == null) throw new Exception("D_Ref");
            }
        }
    }
}
}

`

mbdavid commented 7 years ago

Hi @johnkea, neasted includes are not supported yet. It's on my plans to v3, Your code are corrent, the API must be works as you write.

johnkea commented 7 years ago

Hi @mbdavid, indeed, the code works fine for this example. That means the LiteDB supports Cascading Include, right (one has only to explicitly code it by the include calls with required properties' paths)? Or should I expect surprises in my project?

johnkea commented 7 years ago

Hi @mbdavid, ok, I see, e.g., once, let say, B_Ref is a List of B, then there is no chance to force deeper Include...

mbdavid commented 7 years ago

Yes, works only on first level (A load B), To B load C and C load D include method must be changed to support. This is not too hard to implement, but when B is a List<B> you must include each element. So it's much more complex to implement.

Take a look on dev branch and gitter channel. I'm updating dev works there.

mbdavid commented 7 years ago

v3-beta was released with support to neasted includes.