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

LiteDB supports POCO classes 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 different 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

Mapper conventions

BsonMapper.ToDocument() auto convert each property class in a document field following this conventions:

  • Classes must be public with a public non-parameter 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 decorated with [BsonField] to have a custom name field
  • No circular references allowed
  • Max of 20 depth 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 types, BsonMapper maps others .NET types to BSON data type:

.NET type BSON 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
Any other .NET type Document
  • Nullable<T> are accepted. If value is null, BSON type is Null, otherwise, mapper will use .NET underlying type.
  • For IDictionary<K, T>, K key must be String or simple type (convertible 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 parameter and expect return a BsonValue
  • deserialize function pass a BsonValue object as input parameter and except return a <T> value
  • RegisterType supports complex objects by using BsonDocument or BsonArray

Mapping options

BsonMapper class settings:

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 int CustomerId { get; set; }

    public string FirstName { get; set; }

    [BsonField("customerLastName")]
    public string LastName { get; set; }
}

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

var id = doc["_id"].AsInt;
var john = doc["first_name"].AsString;
var doe = doc["customerLastName"].AsString;

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 Auto-increment, per collection, 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 call 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 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.

Do not use [BsonIndex] attribute on your Id primary key property. This property already has an unique index with default options.