Skip to content
Mauricio David edited this page Nov 19, 2016 · 13 revisions

LiteDB is a document database, so there is no JOIN between collections. You can use embedded documents (sub-documents) or create a reference between collections. To create this reference you ca use [BsonRef] attribute or use DbRef method from fluent API mapper.

Mapping a reference on database initialization

public class Customer
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
}

public class Order
{
    public int OrderId { get; set; }
    public Customer Customer { get; set; }
}

If you didn't do any mapping, when you save an Order, Customer are saved as an embedded document (with no link to any other collection). If you change customer name in Customer colleciton this change will not affect Order.

Order => { _id: 123, Customer: { CustomerId: 99, Name: "John Doe" } }

If you want store only customer reference in Order, you can decorate your class:

public class Order
{
    public int OrderId { get; set; }

    [BsonRef("customers")] // where "customers" are Customer collection name
    public Customer Customer { get; set; }
}

Or use fluent API:

BsonMapper.Global.Entity<Order>()
    .DbRef(x => x.Customer, "customers"); // where "customers" are Customer collection name

Now, when you store Order you are storing only link reference.

Order => { _id: 123, Customer: { $id: 4, $ref: "customers"} }

Quering results

When you query a document with a cross collection reference, you can auto load references using Include method before query.

var orders = db.GetCollection<Order>("orders");

var order1 = db
    .Include(x => x.Customer)
    .FindById(1);

DbRef also support List<T> or Array, like:

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class Order
{
    public int OrderId { get; set; }
    public DateTime OrderDate { get; set; }
    public List<Product> Products { get; set; }
}

BsonMapper.Global.Entity<Order>()
    .DbRef(x => x.Products);

LiteDB will respect if you Products field are null or empty list when restore from datafile. If you do not use Include in query, classes are loaded with only ID setted (all other properties will stay with default/null value).