SlideShare a Scribd company logo
Open source, high performance database


What’s New in the C#/.NET Driver
            Robert Stam
      Software Engineer, 10gen

                                      October 4, 2012

                                                        1
• The C#/.NET driver
  – Is written in C#
  – Can be called from other .NET languages
• Where to find more information:
  – http://www.mongodb.org/display/DOCS/CSharp+Language+Center




                                                                 2
• Recent versions
  –   1.4     Introduced support for LINQ queries
  –   1.4.1   Added support for additional LINQ queries
  –   1.4.2   A few bug fixes
  –   1.5     Serialization changes, new Query builders
  –   1.6     Support for new server 2.2 features
• Upcoming versions
  – 1.6.1     Minor fixes to 1.6 (primarily ReadPreference)
  – 2.0       Major changes (backward breaking)



                                                              3
• Today’s topics:
   –   Serialization overview (POCOs)
   –   The new Query builders
   –   LINQ queries
   –   Authentication
   –   What's new in 1.6
   –   What's new in 1.6.1
   –   Plans for 2.0




                                        4
• Documents are stored as BSON in the database
• When you read a document from the database what
  do you get back in your C# program?
• You can choose to get back either:
   – A BsonDocument
   – A plain old C# object (POCO) that you defined
• Serialization is the process by which a POCO instance
  is transformed to and from a BSON document



                                                          5
• An in memory representation of a BSON document
• Important classes:
  – BsonValue (abstract base class)
  – BsonInt32, BsonInt64, BsonString, BsonDateTime, …
  – BsonDocument, BsonArray
• More information:
  http://www.mongodb.org/display/DOCS/CSharp+Driver+Tutorial#CSharpD
  riverTutorial-BsonValueandsubclasses




                                                                       6
• Very likely you will want to use your own classes
  instead of BsonDocument
• Serialization makes that possible
• Sample code:
var collection = database.GetCollection<Employee>("employees");
var employee = collection.FindOne(
    Query<Employee>.EQ(e => e.EmployeeNumber, 1234));
employee.Salary += 1000;
collection.Save(employee);




                                                                  7
• The driver users serializers to convert POCOs to and
  from BSON documents
• A serializer is a class that implements IBsonSerializer
• A serializer is registered by calling
  BsonSerializer.RegisterSerializer
• The driver provides many serializers for common
  .NET types
• You can write your own if you need to
• Class map based serialization works automatically for
  your POCOs if you follow a few simple rules
                                                            8
• If your POCOs follow these rules they can be
  serialized automatically by the C#/.NET driver:
   – Has a public no-argument constructor
   – Has a public get/set property for each value that you want
     to have serialized
• In most cases automatic class map based
  serialization just works
• You only need to do something when you want to
  override the automatic serialization


                                                                  9
• One way to configure class map based serialization is
  by annotating your class with attributes
[BsonIgnoreExtraElements]
public class Employee {
    [BsonId]
    public ObjectId EmployeeNumber { get; set; }
    [BsonElement("nm")]
    public string Name { get; set; }
    [BsonDateTimeOptions(DateOnly = true)]
    public DateTime DateOfBirth { get; set; }
    [BsonRepresentation(BsonType.Int64)]
    public int Salary { get; set; }
}



                                                          10
• If you want your domain classes to be independent of
  your persistence layer you can configure serialization
  in code instead of using attributes
BsonClassMap.RegisterClassMap<Employee>(cm => {
    cm.AutoMap();
    cm.SetIgnoreExtraElements(true);
    cm.SetIdMember(cm.GetMemberMap(c => c.EmployeeNumber));
    cm.GetMemberMap(c => c.Name).SetElementName("nm");
    cm.GetMemberMap(c => c.DateOfBirth)
        .SetSerializationOptions(
            DateTimeSerializationOptions.DateOnlyInstance);
    cm.GetMemberMap(c => c.Salary)
        .SetRepresentation(BsonType.Int64);
});

                                                              11
• What is a query?
   – Anything that implements IMongoQuery
   – IMongoQuery has an implied contract: that when the
     object is serialized to a BSON document it will be a valid
     MongoDB query
• Ways to create a query:
   –   Use the typed query builder
   –   Use the untyped query builder
   –   new QueryDocument { … }
   –   new QueryWrapper(object query)


                                                                  12
• Version 1.5 introduced a new query builder
• What was wrong with the old query builder?
  – It exposed too many of the idiosyncrasies of the native
    MongoDB query language (implied and, unusual
    restrictions of not, etc…)
  – It required some helper classes (QueryComplete,
    QueryNot, etc…) that were intended to be internal but yet
    had to be public or you couldn't write a query
  – The query language rules that the helper classes were
    attempting to enforce were changing from version to
    version of the server but the driver couldn't adapt
    gracefully because the rules were encoded in source code
                                                                13
• Works at a slightly higher level (e.g., requires
  Query.And instead of implied and)
• Much simpler API (and no helper classes that leak
  out into the public API)
• Mostly compatible with the old query builder
  (specially for simple queries)
• Easier to maintain from version to version of the
  server



                                                      14
• Yes! The old query builder will be removed in 2.0
• For the time being, you can continue using the old
  query builder without changing your source code
  (much) by adding the following lines to the top of
  your source file:
#pragma warning disable 618 // DeprecatedQuery is marked Obsolete
using Query = MongoDB.Driver.Builder.DeprecatedQuery;




                                                                    15
• There is a method in the untyped query builder for
  every query operator in the MongoDB query
  language
Query.EQ("_id", 1234)
Query.EQ("nm", "John Doe")
Query.NE("EmployeeStatus", 1) // assumes Status.Active == 1
Query.GT("Salary", 100000)

// are equivalent to
new QueryDocument("_id", 1234)
new QueryDocument("nm", "John Doe")
new QueryDocument("EmployeeStatus", new BsonDocument("$ne", 1))
new QueryDocument("Salary", new BsonDocument("$gt", 100000))


                                                                  16
• You have to know the element name
   – What if you use [BsonElement] to change the element
     name?
   – What if you mistype the element name?
• You have to correctly serialize any values yourself
   – What if you serialize the value wrong?
   – What if you don't even know how to serialize the value?




                                                               17
• The typed builder has the same methods as the
  untyped builder but is type aware and type safe
Query<Employee>.EQ(d   =>   d.EmployeeNumber, 1234)
Query<Employee>.EQ(d   =>   d.Name, "John Doe")
Query<Employee>.NE(d   =>   d.EmployeeStatus, Status.Active)
Query<Employee>.GT(d   =>   d.Salary, 100000)

// also equivalent to
new QueryDocument("_id", 1234)
new QueryDocument("nm", "John Doe")
new QueryDocument("EmployeeStatus", new BsonDocument("$ne", 1))
new QueryDocument("Salary", new BsonDocument("$gt", 100000))




                                                                  18
• The typed query builder also lets you write the
  predicate in C# and it will be translated to an
  equivalent MongoDB query
Query<Employee>.Where(d   =>   d.EmployeeNumber == 1234)
Query<Employee>.Where(d   =>   d.Name == "John Doe")
Query<Employee>.Where(d   =>   d.EmployeeStatus != Status.Active)
Query<Employee>.Where(d   =>   d.Salary > 100000)

// still equivalent to
new QueryDocument("_id", 1234)
new QueryDocument("nm", "John Doe")
new QueryDocument("EmployeeStatus", new BsonDocument("$ne", 1))
new QueryDocument("Salary", new BsonDocument("$gt", 100000))


                                                                    19
var query = Query.GTE("x", 1).LTE(3);
// becomes
var query = Query.And(Query.GTE("x", 1), Query.LTE("x", 3));

var query = Query.Not("x").GT(1);
// becomes
var query = Query.Not(Query.GT("x", 1));

var query = Query.Exists("x", true);
// becomes
var query = Query.Exists("x");

var query = Query.Exists("x", false);
// becomes
var query = Query.NotExists("x");



                                                               20
• LINQ is supported for queries only (although
  Query<T>.Where supports writing predicates in C#
  that can be used with Update)
• You opt-in to LINQ using AsQueryable()
var collection = database.GetCollection<Employee>("employees");
var query = from e in collection.AsQueryable()
    where e.Name == "John Doe" && e.Salary >= 100000
    select e;

foreach (var employee in query) {
    // process employee
}



                                                                  21
• C# compiler creates an Expression tree
• C#/.NET driver translates the Expression tree to an
  equivalent MongoDB query at run time
• Requirements
   – For each C# property referenced in the LINQ query the
     driver has to be able to figure out the matching element
     name in the BSON document (using dotted names for
     nested elements)
   – For each test using those C# properties the driver has to be
     able to translate the test into an equivalent MongoDB
     query operator

                                                                    22
• The primary goal is: we will only support LINQ
  queries that have a reasonable translation to an
  equivalent MongoDB query
• The reason: we want to ensure predictable
  performance from LINQ queries (no black magic, no
  surprises)
• So, you will not find:
   – Any hidden map/reduce or Javascript tricks
   – Any hidden client side processing
• Online LINQ tutorial at:
  http://www.mongodb.org/display/DOCS/CSharp+Driver+LINQ+Tutorial
                                                                    23
var query = from e in collection.AsQueryable<Employee>()
    where e.EmployeeStatus == Status.Active
    select e;
// translates to (assuming enum value for Active is 1):
{ EmployeeStatus : 1 }

var query = from e in collection.AsQueryable<Employee>()
    where e.EmployeeStatus != Status.Active
    select e;
// translates to:
{ EmployeeStatus : { $ne : 1 } }




                                                           24
var query = from e in collection.AsQueryable<Employee>()
    where e.Name.Contains("oh")
    select e;
// translates to:
{ nm: /oh/s }

var query = from e in collection.AsQueryable<Employee>()
    where e.Name.StartsWith("John")
    select e;
// translates to:
{ nm: /^John/s }




                                                           25
var query = from e in collection.AsQueryable<Employee>()
    where e.Skills[0] == "Java"
    select e;
// translates to:
{ "Skills.0" : "Java" }

var query = from e in collection.AsQueryable<Employee>()
    where e.Skills.Length == 3
    select e;
// translates to:
{ Skills : { $size : 3 } }




                                                           26
var query = from e in collection.AsQueryable<Employee>()
    where e.Address.City == "Hoboken"
    select e;
// translates to:
{ "Address.City" : "Hoboken" }




                                                           27
var states = new [] { "NJ", "NY", "PA" };
var query = from e in collection.AsQueryable<Employee>()
    where states.Contains(e.Address.State)
    select e;
// translates to:
{ "Address.State" : { $in : [ "NJ", "NY", "PA" ] } }

// alternative syntax using C#/.NET driver's "In" method
var query = from e in collection.AsQueryable<Employee>()
    where e.Address.State.In(states)
    select e;




                                                           28
var desiredSkills = new [] { "Java", "C#" };
var query = from e in collection.AsQueryable<Employee>()
    where e.Skills.ContainsAny(desiredSkills)
    select e;
// translates to:
{ "Skills" : { $in : [ "Java", "C#" ] } }

var query = from e in collection.AsQueryable<Employee>()
    where e.Skills.ContainsAll(desiredSkills)
    select e;
// translates to:
{ "Skills" : { $all : [ "Java", "C#" ] } }

// note: ContainsAny and ContainsAll are defined by the C#/.NET
   driver and are not part of standard LINQ



                                                                  29
var query = from e in collection.AsQueryable<Employee>()
    where
        e.Addresses.Any(a =>
            a.City == "Hoboken" &&
            a.State == "NJ")
    select e;
// translates to:
{ "Addresses" : { $elemMatch :
    { City : "Hoboken", State : "NJ" } } }




                                                           30
• You can "Inject" native MongoDB queries into a LINQ
  query if you need to include a test that LINQ doesn't
  support, without giving up LINQ entirely
var query = from e in collection.AsQueryable()
    where
        e.Salary > 50000 &&
        Query.NotExists("EmployeeStatus").Inject()
    select e;
// translates to:
{
    Salary : { $gt : 50000 },
    EmployeeStatus : { $exists : false }
}


                                                          31
• Credentials on the connection string
• Passing the credentials to GetDatabase
• Using the credentials store




                                           32
• The easiest way to provide credentials is using the
  connection string
var connectionString = "mongodb://user:pwd@localhost/?safe=true";
var server = MongoServer.Create(connectionString);
var database = server.GetDatabase("hr");




                                                                    33
• You can also provide the credentials when you call
  GetDatabase
var credentials = new MongoCredentials("user", "pwd");
var database = server.GetDatabase("hr", credentials);




                                                         34
• If you are using different credentials for each
  database you can use a credentials store to hold all
  the credentials (in code only, not supported on the
  connection string)
var credentialsStore = new MongoCredentialsStore();
credentialsStore.AddCredentials(
    "hr", new MongoCredentials("user1", "pwd1"));
credentialsStore.AddCredentials(
    "inventory", new MongoCredentials("user2", "pwd2"));
var settings = new MongoServerSettings {
    CredentialsStore = credentialsStore,
    SafeMode = SafeMode.True
};
var server = MongoServer.Create(settings);
                                                           35
• To authenticate using the admin database you have to
  flag the credentials as being admin credentials
• You can either add "(admin)" to the end of the user
  name or set the Admin flag to true
var cs = "mongodb://user(admin):pwd@localhost/?safe=true";
var server = MongoServer.Create(cs);

var adminCredentials = new MongoCredentials("user", "pwd", true);
var settings = new MongoServerSettings {
    DefaultCredentials = adminCredentials,
    SafeMode = SafeMode.True
};
var server = MongoServer.Create(settings);

                                                                    36
• You have to provide admin credentials to run a
  command against the admin database
var   adminCredentials = new MongoCredentials("user", "pwd", true);
var   adminDatabase = server.GetDatabase("admin", adminCredentials);
var   adminCommand = new CommandDocument { … }; // some admin command
var   result = adminDatabase.RunCommand(adminCommand);




                                                                        37
• Some helper methods require admin credentials
var adminCredentials = new MongoCredentials("user", "pwd", true);
var result = database.RenameCollection(
    "from", "to", adminCredentials);




                                                                    38
•   [BsonSerializer] attribute
•   Support for TTL collections
•   Aggregate helper method
•   ReadPreference (including tag sets)
•   New ConnectionModes




                                          39
• You no longer have to register a serializer
[BsonSerializer(typeof(EmployeeSerializer))]
public class Employee {
    // properties, methods, etc…
}




                                                40
• New SetTimeToLive method in IndexOptions
var keys = IndexKeys.Ascending("timestamp");
var options = IndexOptions.SetTimeToLive(TimeSpan.FromHours(24));
collection.CreateIndex(keys, options);




                                                                    41
• Sends an aggregation pipeline to the server
var pipeline = new BsonDocument[] {
    new BsonDocument {
        { "$group", new BsonDocument {
            { "_id", 1 },
            { "avgx", new BsonDocument {
                { "$avg", "$x" }
            }}
        }}
    }
};

var result = collection.Aggregate(pipeline);
var avgx = result.ResultDocuments.First()["avgx"].ToDouble();


See:
http://docs.mongodb.org/manual/applications/aggregation/
                                                                42
• Replaces slaveOk
// predefined constants
ReadPreference.Primary
ReadPreference.PrimaryPreferred
ReadPreference.Secondary
ReadPreference.SecondaryPreferred
ReadPreference.Nearest

// mapping of slaveOk to ReadPreference
slaveOk == false maps to ReadPreference.Primary
slaveOk == true maps to ReadPreference.SecondaryPreferred

See:
http://docs.mongodb.org/manual/applications/replication/#read-preference-modes


                                                                                 43
• Tags further restrict which servers to use
var tagSets = new ReplicaSetTagSet[]
{
    new ReplicaSetTagSet { { "dc", "ny" }, { "rack", "1" } }
};
var readPreference = new ReadPreference {
    ReadPreferenceMode = ReadPreferenceMode.Secondary,
    TagSets = tagSets
};




                                                               44
• Determines how the driver connects to server(s)
public enum ConnectionMode
{
    Automatic,
    Direct,
    ReplicaSet,
    ShardRouter
}

// Automatic and ShardRouter are new
// Automatic is now the default




                                                    45
• Driver automatically determines how to connect
  when the connection mode is Automatic
   – If replica set name is provided, then ReplicaSet
   – If only one host is provided, then Direct
   – Otherwise, discover what kind of server(s) they are by
     connecting to them and asking them




                                                              46
• ReadPreference bug fixes
   – SecondaryPreferred routing
   – SecondaryAcceptableLatency configurable
   – mongos $readPreference bug
• Serialization of null values for interface properties




                                                          47
• Major release with breaking changes likely
   –   Being developed on the x2.0 branch (master is for 1.6.x)
   –   Improvements to the BsonDocument object model
   –   Redesign of the automapping conventions system
   –   Improvements to the API
        • Fewer namespaces
        • Fewer overloads, better handling of optional items
        • Multiple collection classes for different use cases?
   – LINQ to Aggregation framework
   – Move to .NET Framework 4 or 4.5? C# 5.0?
        • What about Mono compatibility?
   – Async support? Obsolete APM pattern or C# 5.0?
                                                                  48
• Please provide feedback:
   – mongodb-csharp (preferred for 2.0 design discussions)
   – mongodb-user (for general questions)
   – JIRA (for specific bug reports and feature requests)




                                                             49
Open source, high performance database


         Q&A
        Robert Stam
  Software Engineer, 10gen




                                         50

More Related Content

PPT
Introduction to mongodb
PPT
Introduction to MongoDB
PDF
Introduction to MongoDB
PPT
Introduction to mongoDB
PDF
Mongodb tutorial at Easylearning Guru
PPTX
Intro To Mongo Db
PPTX
An Introduction To NoSQL & MongoDB
Introduction to mongodb
Introduction to MongoDB
Introduction to MongoDB
Introduction to mongoDB
Mongodb tutorial at Easylearning Guru
Intro To Mongo Db
An Introduction To NoSQL & MongoDB

What's hot (20)

PPTX
Mongo db intro.pptx
PDF
MongoDB World 2016: Poster Sessions eBook
PPTX
MongoDB
PDF
Introduction to MongoDB
PPTX
Mango Database - Web Development
PDF
Mongo db dhruba
PPTX
Basics of MongoDB
PDF
Introduction to mongo db
ODP
Introduction to MongoDB
PPTX
A Presentation on MongoDB Introduction - Habilelabs
PPTX
MongoDB: An Introduction - june-2011
PPTX
MongoDB 101
PPTX
Introduction to MongoDB
PDF
Intro To MongoDB
PPTX
MongoDB presentation
PPT
MongoDB Pros and Cons
DOCX
Mongo db report
PPTX
Mongo db
PDF
An introduction to MongoDB
PPTX
Top 10 frameworks of node js
Mongo db intro.pptx
MongoDB World 2016: Poster Sessions eBook
MongoDB
Introduction to MongoDB
Mango Database - Web Development
Mongo db dhruba
Basics of MongoDB
Introduction to mongo db
Introduction to MongoDB
A Presentation on MongoDB Introduction - Habilelabs
MongoDB: An Introduction - june-2011
MongoDB 101
Introduction to MongoDB
Intro To MongoDB
MongoDB presentation
MongoDB Pros and Cons
Mongo db report
Mongo db
An introduction to MongoDB
Top 10 frameworks of node js
Ad

Similar to Webinar: What's new in the .NET Driver (20)

PDF
Webinar: What's new in the .NET Driver
KEY
Welcome the Offical C# Driver for MongoDB
PDF
Mongo db for C# Developers
PPTX
Introduction to the new official C# Driver developed by 10gen
PDF
Mongo db for c# developers
PDF
NDC London 2013 - Mongo db for c# developers
PDF
Mongo db first steps with csharp
PDF
MongodB Internals
PDF
The MongoDB Driver for F#
PPTX
Using MongoDB with the .Net Framework
PPT
9. Document Oriented Databases
PPTX
Getting Started with MongoDB Using the Microsoft Stack
ODP
Mongo db rev001.
PDF
Which Questions We Should Have
PPTX
Introduction to MongoDB
PDF
PDF
Building your first app with MongoDB
PPTX
mongodb introduction11111111111111111111
PPTX
No SQL DB lecture showing structure and syntax
PDF
Benchmarking at Parse
Webinar: What's new in the .NET Driver
Welcome the Offical C# Driver for MongoDB
Mongo db for C# Developers
Introduction to the new official C# Driver developed by 10gen
Mongo db for c# developers
NDC London 2013 - Mongo db for c# developers
Mongo db first steps with csharp
MongodB Internals
The MongoDB Driver for F#
Using MongoDB with the .Net Framework
9. Document Oriented Databases
Getting Started with MongoDB Using the Microsoft Stack
Mongo db rev001.
Which Questions We Should Have
Introduction to MongoDB
Building your first app with MongoDB
mongodb introduction11111111111111111111
No SQL DB lecture showing structure and syntax
Benchmarking at Parse
Ad

More from MongoDB (20)

PDF
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
PDF
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
PDF
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
PDF
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
PDF
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
PDF
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
PDF
MongoDB SoCal 2020: MongoDB Atlas Jump Start
PDF
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
PDF
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
PDF
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
PDF
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
PDF
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
PDF
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
PDF
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
PDF
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
PDF
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
PDF
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
PDF
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
PDF
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
PDF
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: MongoDB Atlas Jump Start
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...

Recently uploaded (20)

DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PDF
KodekX | Application Modernization Development
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Electronic commerce courselecture one. Pdf
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
Modernizing your data center with Dell and AMD
PPTX
A Presentation on Artificial Intelligence
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
Cloud computing and distributed systems.
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
cuic standard and advanced reporting.pdf
The AUB Centre for AI in Media Proposal.docx
CIFDAQ's Market Insight: SEC Turns Pro Crypto
KodekX | Application Modernization Development
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Peak of Data & AI Encore- AI for Metadata and Smarter Workflows
Encapsulation_ Review paper, used for researhc scholars
Electronic commerce courselecture one. Pdf
Reach Out and Touch Someone: Haptics and Empathic Computing
“AI and Expert System Decision Support & Business Intelligence Systems”
Modernizing your data center with Dell and AMD
A Presentation on Artificial Intelligence
Chapter 3 Spatial Domain Image Processing.pdf
Spectral efficient network and resource selection model in 5G networks
Dropbox Q2 2025 Financial Results & Investor Presentation
Diabetes mellitus diagnosis method based random forest with bat algorithm
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Unlocking AI with Model Context Protocol (MCP)
Cloud computing and distributed systems.
NewMind AI Monthly Chronicles - July 2025
cuic standard and advanced reporting.pdf

Webinar: What's new in the .NET Driver

  • 1. Open source, high performance database What’s New in the C#/.NET Driver Robert Stam Software Engineer, 10gen October 4, 2012 1
  • 2. • The C#/.NET driver – Is written in C# – Can be called from other .NET languages • Where to find more information: – http://www.mongodb.org/display/DOCS/CSharp+Language+Center 2
  • 3. • Recent versions – 1.4 Introduced support for LINQ queries – 1.4.1 Added support for additional LINQ queries – 1.4.2 A few bug fixes – 1.5 Serialization changes, new Query builders – 1.6 Support for new server 2.2 features • Upcoming versions – 1.6.1 Minor fixes to 1.6 (primarily ReadPreference) – 2.0 Major changes (backward breaking) 3
  • 4. • Today’s topics: – Serialization overview (POCOs) – The new Query builders – LINQ queries – Authentication – What's new in 1.6 – What's new in 1.6.1 – Plans for 2.0 4
  • 5. • Documents are stored as BSON in the database • When you read a document from the database what do you get back in your C# program? • You can choose to get back either: – A BsonDocument – A plain old C# object (POCO) that you defined • Serialization is the process by which a POCO instance is transformed to and from a BSON document 5
  • 6. • An in memory representation of a BSON document • Important classes: – BsonValue (abstract base class) – BsonInt32, BsonInt64, BsonString, BsonDateTime, … – BsonDocument, BsonArray • More information: http://www.mongodb.org/display/DOCS/CSharp+Driver+Tutorial#CSharpD riverTutorial-BsonValueandsubclasses 6
  • 7. • Very likely you will want to use your own classes instead of BsonDocument • Serialization makes that possible • Sample code: var collection = database.GetCollection<Employee>("employees"); var employee = collection.FindOne( Query<Employee>.EQ(e => e.EmployeeNumber, 1234)); employee.Salary += 1000; collection.Save(employee); 7
  • 8. • The driver users serializers to convert POCOs to and from BSON documents • A serializer is a class that implements IBsonSerializer • A serializer is registered by calling BsonSerializer.RegisterSerializer • The driver provides many serializers for common .NET types • You can write your own if you need to • Class map based serialization works automatically for your POCOs if you follow a few simple rules 8
  • 9. • If your POCOs follow these rules they can be serialized automatically by the C#/.NET driver: – Has a public no-argument constructor – Has a public get/set property for each value that you want to have serialized • In most cases automatic class map based serialization just works • You only need to do something when you want to override the automatic serialization 9
  • 10. • One way to configure class map based serialization is by annotating your class with attributes [BsonIgnoreExtraElements] public class Employee { [BsonId] public ObjectId EmployeeNumber { get; set; } [BsonElement("nm")] public string Name { get; set; } [BsonDateTimeOptions(DateOnly = true)] public DateTime DateOfBirth { get; set; } [BsonRepresentation(BsonType.Int64)] public int Salary { get; set; } } 10
  • 11. • If you want your domain classes to be independent of your persistence layer you can configure serialization in code instead of using attributes BsonClassMap.RegisterClassMap<Employee>(cm => { cm.AutoMap(); cm.SetIgnoreExtraElements(true); cm.SetIdMember(cm.GetMemberMap(c => c.EmployeeNumber)); cm.GetMemberMap(c => c.Name).SetElementName("nm"); cm.GetMemberMap(c => c.DateOfBirth) .SetSerializationOptions( DateTimeSerializationOptions.DateOnlyInstance); cm.GetMemberMap(c => c.Salary) .SetRepresentation(BsonType.Int64); }); 11
  • 12. • What is a query? – Anything that implements IMongoQuery – IMongoQuery has an implied contract: that when the object is serialized to a BSON document it will be a valid MongoDB query • Ways to create a query: – Use the typed query builder – Use the untyped query builder – new QueryDocument { … } – new QueryWrapper(object query) 12
  • 13. • Version 1.5 introduced a new query builder • What was wrong with the old query builder? – It exposed too many of the idiosyncrasies of the native MongoDB query language (implied and, unusual restrictions of not, etc…) – It required some helper classes (QueryComplete, QueryNot, etc…) that were intended to be internal but yet had to be public or you couldn't write a query – The query language rules that the helper classes were attempting to enforce were changing from version to version of the server but the driver couldn't adapt gracefully because the rules were encoded in source code 13
  • 14. • Works at a slightly higher level (e.g., requires Query.And instead of implied and) • Much simpler API (and no helper classes that leak out into the public API) • Mostly compatible with the old query builder (specially for simple queries) • Easier to maintain from version to version of the server 14
  • 15. • Yes! The old query builder will be removed in 2.0 • For the time being, you can continue using the old query builder without changing your source code (much) by adding the following lines to the top of your source file: #pragma warning disable 618 // DeprecatedQuery is marked Obsolete using Query = MongoDB.Driver.Builder.DeprecatedQuery; 15
  • 16. • There is a method in the untyped query builder for every query operator in the MongoDB query language Query.EQ("_id", 1234) Query.EQ("nm", "John Doe") Query.NE("EmployeeStatus", 1) // assumes Status.Active == 1 Query.GT("Salary", 100000) // are equivalent to new QueryDocument("_id", 1234) new QueryDocument("nm", "John Doe") new QueryDocument("EmployeeStatus", new BsonDocument("$ne", 1)) new QueryDocument("Salary", new BsonDocument("$gt", 100000)) 16
  • 17. • You have to know the element name – What if you use [BsonElement] to change the element name? – What if you mistype the element name? • You have to correctly serialize any values yourself – What if you serialize the value wrong? – What if you don't even know how to serialize the value? 17
  • 18. • The typed builder has the same methods as the untyped builder but is type aware and type safe Query<Employee>.EQ(d => d.EmployeeNumber, 1234) Query<Employee>.EQ(d => d.Name, "John Doe") Query<Employee>.NE(d => d.EmployeeStatus, Status.Active) Query<Employee>.GT(d => d.Salary, 100000) // also equivalent to new QueryDocument("_id", 1234) new QueryDocument("nm", "John Doe") new QueryDocument("EmployeeStatus", new BsonDocument("$ne", 1)) new QueryDocument("Salary", new BsonDocument("$gt", 100000)) 18
  • 19. • The typed query builder also lets you write the predicate in C# and it will be translated to an equivalent MongoDB query Query<Employee>.Where(d => d.EmployeeNumber == 1234) Query<Employee>.Where(d => d.Name == "John Doe") Query<Employee>.Where(d => d.EmployeeStatus != Status.Active) Query<Employee>.Where(d => d.Salary > 100000) // still equivalent to new QueryDocument("_id", 1234) new QueryDocument("nm", "John Doe") new QueryDocument("EmployeeStatus", new BsonDocument("$ne", 1)) new QueryDocument("Salary", new BsonDocument("$gt", 100000)) 19
  • 20. var query = Query.GTE("x", 1).LTE(3); // becomes var query = Query.And(Query.GTE("x", 1), Query.LTE("x", 3)); var query = Query.Not("x").GT(1); // becomes var query = Query.Not(Query.GT("x", 1)); var query = Query.Exists("x", true); // becomes var query = Query.Exists("x"); var query = Query.Exists("x", false); // becomes var query = Query.NotExists("x"); 20
  • 21. • LINQ is supported for queries only (although Query<T>.Where supports writing predicates in C# that can be used with Update) • You opt-in to LINQ using AsQueryable() var collection = database.GetCollection<Employee>("employees"); var query = from e in collection.AsQueryable() where e.Name == "John Doe" && e.Salary >= 100000 select e; foreach (var employee in query) { // process employee } 21
  • 22. • C# compiler creates an Expression tree • C#/.NET driver translates the Expression tree to an equivalent MongoDB query at run time • Requirements – For each C# property referenced in the LINQ query the driver has to be able to figure out the matching element name in the BSON document (using dotted names for nested elements) – For each test using those C# properties the driver has to be able to translate the test into an equivalent MongoDB query operator 22
  • 23. • The primary goal is: we will only support LINQ queries that have a reasonable translation to an equivalent MongoDB query • The reason: we want to ensure predictable performance from LINQ queries (no black magic, no surprises) • So, you will not find: – Any hidden map/reduce or Javascript tricks – Any hidden client side processing • Online LINQ tutorial at: http://www.mongodb.org/display/DOCS/CSharp+Driver+LINQ+Tutorial 23
  • 24. var query = from e in collection.AsQueryable<Employee>() where e.EmployeeStatus == Status.Active select e; // translates to (assuming enum value for Active is 1): { EmployeeStatus : 1 } var query = from e in collection.AsQueryable<Employee>() where e.EmployeeStatus != Status.Active select e; // translates to: { EmployeeStatus : { $ne : 1 } } 24
  • 25. var query = from e in collection.AsQueryable<Employee>() where e.Name.Contains("oh") select e; // translates to: { nm: /oh/s } var query = from e in collection.AsQueryable<Employee>() where e.Name.StartsWith("John") select e; // translates to: { nm: /^John/s } 25
  • 26. var query = from e in collection.AsQueryable<Employee>() where e.Skills[0] == "Java" select e; // translates to: { "Skills.0" : "Java" } var query = from e in collection.AsQueryable<Employee>() where e.Skills.Length == 3 select e; // translates to: { Skills : { $size : 3 } } 26
  • 27. var query = from e in collection.AsQueryable<Employee>() where e.Address.City == "Hoboken" select e; // translates to: { "Address.City" : "Hoboken" } 27
  • 28. var states = new [] { "NJ", "NY", "PA" }; var query = from e in collection.AsQueryable<Employee>() where states.Contains(e.Address.State) select e; // translates to: { "Address.State" : { $in : [ "NJ", "NY", "PA" ] } } // alternative syntax using C#/.NET driver's "In" method var query = from e in collection.AsQueryable<Employee>() where e.Address.State.In(states) select e; 28
  • 29. var desiredSkills = new [] { "Java", "C#" }; var query = from e in collection.AsQueryable<Employee>() where e.Skills.ContainsAny(desiredSkills) select e; // translates to: { "Skills" : { $in : [ "Java", "C#" ] } } var query = from e in collection.AsQueryable<Employee>() where e.Skills.ContainsAll(desiredSkills) select e; // translates to: { "Skills" : { $all : [ "Java", "C#" ] } } // note: ContainsAny and ContainsAll are defined by the C#/.NET driver and are not part of standard LINQ 29
  • 30. var query = from e in collection.AsQueryable<Employee>() where e.Addresses.Any(a => a.City == "Hoboken" && a.State == "NJ") select e; // translates to: { "Addresses" : { $elemMatch : { City : "Hoboken", State : "NJ" } } } 30
  • 31. • You can "Inject" native MongoDB queries into a LINQ query if you need to include a test that LINQ doesn't support, without giving up LINQ entirely var query = from e in collection.AsQueryable() where e.Salary > 50000 && Query.NotExists("EmployeeStatus").Inject() select e; // translates to: { Salary : { $gt : 50000 }, EmployeeStatus : { $exists : false } } 31
  • 32. • Credentials on the connection string • Passing the credentials to GetDatabase • Using the credentials store 32
  • 33. • The easiest way to provide credentials is using the connection string var connectionString = "mongodb://user:pwd@localhost/?safe=true"; var server = MongoServer.Create(connectionString); var database = server.GetDatabase("hr"); 33
  • 34. • You can also provide the credentials when you call GetDatabase var credentials = new MongoCredentials("user", "pwd"); var database = server.GetDatabase("hr", credentials); 34
  • 35. • If you are using different credentials for each database you can use a credentials store to hold all the credentials (in code only, not supported on the connection string) var credentialsStore = new MongoCredentialsStore(); credentialsStore.AddCredentials( "hr", new MongoCredentials("user1", "pwd1")); credentialsStore.AddCredentials( "inventory", new MongoCredentials("user2", "pwd2")); var settings = new MongoServerSettings { CredentialsStore = credentialsStore, SafeMode = SafeMode.True }; var server = MongoServer.Create(settings); 35
  • 36. • To authenticate using the admin database you have to flag the credentials as being admin credentials • You can either add "(admin)" to the end of the user name or set the Admin flag to true var cs = "mongodb://user(admin):pwd@localhost/?safe=true"; var server = MongoServer.Create(cs); var adminCredentials = new MongoCredentials("user", "pwd", true); var settings = new MongoServerSettings { DefaultCredentials = adminCredentials, SafeMode = SafeMode.True }; var server = MongoServer.Create(settings); 36
  • 37. • You have to provide admin credentials to run a command against the admin database var adminCredentials = new MongoCredentials("user", "pwd", true); var adminDatabase = server.GetDatabase("admin", adminCredentials); var adminCommand = new CommandDocument { … }; // some admin command var result = adminDatabase.RunCommand(adminCommand); 37
  • 38. • Some helper methods require admin credentials var adminCredentials = new MongoCredentials("user", "pwd", true); var result = database.RenameCollection( "from", "to", adminCredentials); 38
  • 39. [BsonSerializer] attribute • Support for TTL collections • Aggregate helper method • ReadPreference (including tag sets) • New ConnectionModes 39
  • 40. • You no longer have to register a serializer [BsonSerializer(typeof(EmployeeSerializer))] public class Employee { // properties, methods, etc… } 40
  • 41. • New SetTimeToLive method in IndexOptions var keys = IndexKeys.Ascending("timestamp"); var options = IndexOptions.SetTimeToLive(TimeSpan.FromHours(24)); collection.CreateIndex(keys, options); 41
  • 42. • Sends an aggregation pipeline to the server var pipeline = new BsonDocument[] { new BsonDocument { { "$group", new BsonDocument { { "_id", 1 }, { "avgx", new BsonDocument { { "$avg", "$x" } }} }} } }; var result = collection.Aggregate(pipeline); var avgx = result.ResultDocuments.First()["avgx"].ToDouble(); See: http://docs.mongodb.org/manual/applications/aggregation/ 42
  • 43. • Replaces slaveOk // predefined constants ReadPreference.Primary ReadPreference.PrimaryPreferred ReadPreference.Secondary ReadPreference.SecondaryPreferred ReadPreference.Nearest // mapping of slaveOk to ReadPreference slaveOk == false maps to ReadPreference.Primary slaveOk == true maps to ReadPreference.SecondaryPreferred See: http://docs.mongodb.org/manual/applications/replication/#read-preference-modes 43
  • 44. • Tags further restrict which servers to use var tagSets = new ReplicaSetTagSet[] { new ReplicaSetTagSet { { "dc", "ny" }, { "rack", "1" } } }; var readPreference = new ReadPreference { ReadPreferenceMode = ReadPreferenceMode.Secondary, TagSets = tagSets }; 44
  • 45. • Determines how the driver connects to server(s) public enum ConnectionMode { Automatic, Direct, ReplicaSet, ShardRouter } // Automatic and ShardRouter are new // Automatic is now the default 45
  • 46. • Driver automatically determines how to connect when the connection mode is Automatic – If replica set name is provided, then ReplicaSet – If only one host is provided, then Direct – Otherwise, discover what kind of server(s) they are by connecting to them and asking them 46
  • 47. • ReadPreference bug fixes – SecondaryPreferred routing – SecondaryAcceptableLatency configurable – mongos $readPreference bug • Serialization of null values for interface properties 47
  • 48. • Major release with breaking changes likely – Being developed on the x2.0 branch (master is for 1.6.x) – Improvements to the BsonDocument object model – Redesign of the automapping conventions system – Improvements to the API • Fewer namespaces • Fewer overloads, better handling of optional items • Multiple collection classes for different use cases? – LINQ to Aggregation framework – Move to .NET Framework 4 or 4.5? C# 5.0? • What about Mono compatibility? – Async support? Obsolete APM pattern or C# 5.0? 48
  • 49. • Please provide feedback: – mongodb-csharp (preferred for 2.0 design discussions) – mongodb-user (for general questions) – JIRA (for specific bug reports and feature requests) 49
  • 50. Open source, high performance database Q&A Robert Stam Software Engineer, 10gen 50