-
Notifications
You must be signed in to change notification settings - Fork 226
Configuration
MongoDB-CSharp has put a lot of effort into minimizing the amount of configuration you need to do. We have chosen sensible defaults for the .NET developer. However, we understand that interoperability with other languages is a must and sometimes things just need to be different. So, virtually every area of MongoDB-CSharp is open to extension, from the mapping configuration of your POCO classes to the Serializer/Deserializer itself.
The simplest of of configuring the Mongo is to simple create the Mongo object.
var mongo = new Mongo();
This will create an default configuration and connects to MongoDB on local host.
If you want to only change the connection string you can simply pass them to the Mongo constructor:
var mongo = new Mongo("Server=192.168.0.1");
Below is an example of what a configuration may look like. We wanted to give you a reference point for the detailed explanations further down the page.
var configure = new MongoConfigurationBuilder();
configure.ConnectionStringAppSettingsKey("tests");
configure.Mapping(mapping =>
{
mapping.DefaultProfile(p =>
{
p.AliasesAreCamelCased();
p.CollectionNamesAreCamelCasedAndPlural();
});
mapping.Map<Person>(c =>
{
c.CollectionName("person_bucket");
c.Member(x => x.FirstName).Alias("fn");
});
});
var mongo = new Mongo(configure.Build());
Typed Collections never need to be manually mapped. There is an intelligent class called AutoMapper that handles reading your type’s metadata via reflection and creating a map for you. In the future, we may offer a way to do this programmatically depending on need. For now, you have the ability to control all parts of the mapping process through 2 methods.
Profiles are a macro customization for a given set of types. There is always a default profile that will match every type except System.Object. In addition, you can optionally specify custom profiles to match a given type or set of types. For instance, if we wanted all the types in Examples.Domain to be mapped differently than all the types in Examples.ViewModels, we could create 1 profile for Examples.Domain and let the default profile handle Examples.ViewModels.
Profiles are used in the order of their registration process. So, if two profiles have overlapping types, then whichever was registered first will match.
configure.CustomProfile(t => t.Namespace == "Examples.Domain", p =>
{
p.AliasesAre(m => m.Name.ToLower());
});
The above code creates a custom profile that will match when a type’s namespace is Examples.Domain. In this case, all types in the Examples.Domain namespace will use the lowercased member’s name as their alias.
The default profile can also be configured as shown earlier, but it does not have a filter because it matches every type and is always the last profile in the chain.
MongoDB-CSharp mapping allows for inheritance chains to be configured. The profile object has a SubClassesAre method that allows us to specify our derived classes. See the Inheritance page for more details.
You can quickly override member resolution by implementing IMemberFinder and passing it to the profile’s FindMembersWith method.
Conventions are the building blocks of profiles. Each convention is an interface that can be implemented and then applied to a profile. In addition, some conventions have implementations based on delegates that are exposed through the MongoConfiguration object to make it easy to change behaviour. Below are all the conventions and their descriptions, along with their default implementation.
Determines how a .NET property or field name is mapped to a mongo property name. This is called an alias.
The default is to simply use the member name. So, a class with a property called Name will be persisted with an alias of Name.
Determines how to adapt a mongo array into a POCO class.
Currently, there are 4 collection adapters that the default convention uses. Array, ArrayList, GenericList, and GenericSet.
Determines the collection name a type maps to. This would be used when the IMongoDatabase.GetCollection() without specifying a collection name.
The default is to use the type’s name.
Determines the default value for a given type.
The default is to use the .NET default value.
Determines the discriminator for a given type.
The default is to use the type’s name.
Determines the mongo name to use for the discriminator.
The default is to use “_t”.
Determines the ExtendedProperties member. ExtendedProperties allow for mongo properties to be persisted without having a .NET member to map them to. ExtendedProperties can be anything that implements IDictionary<string, object>.
The default is to find a member called “ExtendedProperties”.
Determines which member is the identifier.
The default is to find a member called “Id”.
Determines the generator to use for a particular identifier type.
By default, Guid’s use a Comb generator and Oid’s use an OidGenerator. All other identifier types use an AssignedGenerator, which means user provided.
Determines the unsaved value for an id.
The default is to use the identifier’s type’s default value. For instance, Guid’s unsaved value is all 0’s.
Most of the above conventions can be overriden at a class and member level. This can be done in 2 ways.
There are 3 attributes that can be used currently. [MongoAliasAttribute] can be applied to a member to set it’s name. [MongoDefaultValueAttribute] can be applied to a member to change it’s default value. [MongoIgnoreAttribute] can be applied to a member to tell MongoDB-CSharp to ignore it.
As seen in the example at the start, it is possible to overrided classes and members through the configuration method called Map.
Most likely, you will never ever need to touch this (or even know that it exists). It handles communicating with the serializer/deserializer for how to construct objects. The default ISerializationFactory is the SerializationFactory which uses all the above configuration to handle mapping to and from POCO objects as well as mapping to and from Documents. If you’d like to implement super custom mapping or do something way outside the bounds of our implementation, this may be the easiest way in.