Skip to content
mbdavid edited this page Mar 14, 2015 · 16 revisions

LiteDB supports POCO class as strong types documents. When you get LiteCollection instance from LiteDatabase.GetCollection<T> you can set <T> type. This type will be your document type. If this <T> was diferent than BsonDocument, LiteDB internal maps your class to BsonDocument. To do this, LiteDB uses BsonMapper class:

// Simple strong type document
public class Customer
{
    public ObjectId CustomerId { get; set; }
    public string Name { get; set; }
    public DateTime CreateDate { get; set; }
    public List<Phone> Phones { get; set; }
    public bool IsActive { get; set; }
}

var typedCustomerCollection = db.GetCollection<Customer>("customer");

var schemelessCollection = db.GetCollection("customer"); // <T> is BsonDocument

BsonMapper convert each property class in a document field folling this rules:

  • Classes must be pulic with a public one non-paramter constructor
  • Properties must be public
  • Properties can be read-only or read/write
  • Class must have an Id property, <ClassName>Id property or any property with [BsonId] attribute
  • A property can be decorated with [BsonIgnore] to not be mapped to document
  • A property can be decorared with [BsonField] to have a custom name field
  • No circular references allowed
  • Max of 20 deep inner classes
  • Class fields are not converted to document
  • BsonMapper use a global instance that cache mapping information for a better performance. This instance is on LiteDatabase.Mapper property too.

In addition of basic BSON data types, BsonMapper maps others .NET data types to BSON data type:

.NET Data Type BSON Data Type
Int16, UInt16, Byte Int32
UInt32 , UInt64 Int64
Single, Decimal Double
Char, Enum String
IList<T> Array
T[] Array
NameValueCollection Document
IDictionary<K,T> Document
  • Nullable<T> are accepted. If value is null, BSON data type is Null, otherwise, BSON value will be .NET then underlying type.
  • For IDictionary<K, T>, K key must be String or simple data type (convertable using Convert.ToString(..)).

Register a custom type

You can register your own map function, using RegisterType<T> instance method. To register, you need create serialize/deserialize functions.

BsonMapper.Global.RegisterType<Uri>
(
    serialize: (uri) => uri.AbsoluteUri,
    deserialize: (bson) => new Uri(bson.AsString)
);
  • Serialize functions pass a <T> object instance as input paramter and expect return a BsonValue
  • Deserialize function pass a BsonValue object as input paramter and except return a <T> value
  • RegisterType supports complex objects by using BsonDocument or BsonArray

Mapping options

BsonMapper support some options:

Name Default Description
SerializeNullValues false Serialize field if value is null
TrimWhitespace true Trim strings properties before map to document
EmptyStringToNull true Empty string convert to null
ResolvePropertyName (s) => s A function to map property name to document field name

BsonMapper offers 2 predefined functions to resolve property name: UseCamelCase() and UseLowerCaseDelimiter("_").

BsonMapper.Global.UseLowerCaseDelimiter("_");

public class Customer
{
    public string FirstName { get; set; }
}

var doc = BsonMapper.Global.ToDocument(new Customer { FirstName = "John" });

var john = doc["first_name"];

AutoId

By default, typed documents will recive an auto Id value on insert. LiteDB support auto-id for this data types:

.NET data type New Value
ObjectId ObjectId.NewObjectId()
Guid Guid.NewGuid()
Int32 Sequence value starting in 1

But if you don't use or want another data type for Id, you can set previously:

var customer = new Customer { Id = "john-doe", Name = "John Doe" };

You also can create your own auto-id function, using RegisterAutoId<T>:

BsonMapper.Global.RegisterAutoId<long>
(
    isEmpty: (value) => value == 0,
    newId: (collection) => DateTime.UtcNow.Ticks
);

public class Calendar
{
    public long CalendarId { get; set; }
}
  • isEmpty returns true to indicate when this type is considerate empty. In this example, zero will be empty value.
  • newId returns new id value. Gets LiteCollection<BsonDocument> instance as input parameter if you need use.

Index definition

BsonMapper support index definition direct on property using [BsonIndex] attribute. You can define index options like, Unique or IgnoreCase. This is useful to avoid always run col.EnsureIndex("field") before run a query.

public class Customer
{
    public int Id { get; set; }
    
    [BsonIndex]
    public string Name { get; set; }
    
    [BsonIndex(new IndexOptions { Unique = true, IgnoreCase = false, RemoveAccents = false })]
    public string Email { get; set; }
}

IndexOptions class has this settings:

Name Default Description
Unique false Do not allow duplicates values in index
IgnoreCase true Store string on index in lowercase
RemoveAccents true Store string on index removing accents
TrimWhitespace true Store string on index removing trimming spaces
EmptyStringToNull true If string is empty, convert to Null

To get better performance, [BsonIndex] checks only if index exists but do not check if you are changing options. To change an index option in a existing index you must run EnsureIndex with new index options. This method drop current index and create a new one with new options.