2.5 Properties

2.5.1 Accessing a property

You access MongoDB document properties by either using by simply typing its name, consider the following example where we get a document that has the _id "Doe_Jane" and get the value from the Salary property and the FullName property:

// Get a reference to MongoDB
dynamic storage = new DynStorage("mongodb://user:pass@example.org/MongoDBExample");

// Get reference to the ExampleMessagesCollection collection, it's created if it doesn't already exist
dynamic employeesCollection = storage.exampleEmployees;

// Get a reference to an  document using its _id to identify it
var employee = employeesCollection.Document("Doe_Jane");

// Write Jane Doe's salary to the console
Console.WriteLine(employee.FullName + "'s salary is $" +  employee.Salary + " USD/yr");

Alternatively, if you have a string with the property name you can access the property by accessing DynDocument as a Key/Value dictionary, the following example uses this approach to achieve the same as the previous example:

// Get a reference to MongoDB
dynamic storage = new DynStorage("mongodb://user:pass@example.org/MongoDBExample");

// Get reference to the ExampleMessagesCollection collection, it's created if it doesn't already exist
dynamic employeesCollection = storage.exampleEmployees;

// Get a reference to an  document using its id to identify it
DynDocument employee = employeesCollection.Document("Doe_Jane");

// Write Jane Doe's salary to the console
Console.WriteLine(employee["FullName"].PropertyValue + "'s salary is $" + employee["Salary"].PropertyValue + " USD/yr");

In the example above a call to DynProperty.PropertyValue property is required to get the actual value as the dictionary returns DynProperty objects.

2.5.2 Creating or updating a property

With Slazure, you create MongoDB document properties automatically when accessing them, you must however always call Save() or Update() method on the document object in question after one or more properties have been added or updated. The following example shows how we create a new employee document for John Doe by calling the DynDocument.Save() method:

// Get a reference to MongoDB
dynamic storage = new DynStorage("mongodb://user:pass@example.org/MongoDBExample");

// Get reference to the ExampleMessagesCollection collection, it's created if it doesn't already exist
dynamic employeesCollection = storage.exampleEmployees;

// Define a new document using an _id
var employee = employeesCollection.Document("Doe_Jane");

// Add some values to the employee document
employee.FullName = "John Doe";
employee.Salary = 60000;

// Save the new document to the Azure Collection Storage
employee.Save();

2.5.3 Listing properties

You list all document properties by accessing DynDocument as a Key/Value dictionary. In the following example all property names are listed for all documents that was returned from a Linq query:

public void EnumProperties()
{
    // Get a reference to the collection
    dynamic storage = new QueryableStorage<DynDocument>("mongodb://user:pass@example.org/MongoDBExample");
    QueryableCollection<DynDocument> collection = storage.TestCustomers;

    // Build collection query
    var queryResult = collection.Where("SignedUpForNewsletter = true and Age < 22");

    foreach (DynDocument document in queryResult)
    {
        foreach (KeyValuePair<string, IDynProperty> keyValuePair in document)
        {
            Console.WriteLine(keyValuePair.Key);
        }
    }
}

3 Examples

3.1 Writing to a database

Get a reference to the MongoDB with the DynStorage class and from it you can access any collection by its literal name. In the example create a collection called ExampleMessagesCollection that will hold some messages. The person that sent the message is identified by his/her IP-address and each message has a unique Guid to identity it. The CreateMessages() is the main entry point for creating messages with your class.

public static void CreateMessages()
{
    // Get a reference to MongoDB
    dynamic storage = new DynStorage("mongodb://user:pass@example.org/MongoDBExample");

    // Get reference to the ExampleMessagesCollection collection, it's created if it doesn't already exist
    dynamic messagesCollection = storage.ExampleMessagesCollection;

    AddMessage(messagesCollection, "127.0.0.1"new Guid("1539964a-db24-46ba-8410-a91a2ed440b1"), 
        "Dr. Livingstone, I presume?");
    AddMessage(messagesCollection, "192.168.1.100"new Guid("31F5E279-64EA-4796-8185-E75F3820D5ED"), 
        "Yes, and I feel thankful that I am here to welcome you.");
}

/// <summary>
/// Add a new message to the data MongoDB
/// </summary>
static void AddMessage(dynamic messagesCollection, string ipAddress, Guid messageId, string message)
{
    // Create an document in the ExampleMessagesCollection collection using the message id as the document id.
    var messageDocument = messagesCollection.Document(messageId.ToString());
    messageDocument.Message = message;
    messageDocument.IpAddress = ipAddress;

    // Save the document to the Azure MongoDB
    messageDocument.Save();
}

3.2 Querying a database using the Slazure object model

There are two ways of querying entities with Slazure; using the Slazure object model and using the Slazure LINQ provider. Firstly, let’s look at querying for entities with the Slazure object model. In the example below a call the ShowMessage() method would display the text "Dr. Livingstone, I presume?" in the console by simply referencing the document using the IP-address and message ID.

// Query for and display the message "Dr. Livingstone, I presume?"
public static string ShowMessage()
{
    // Get a reference to MongoDB
    dynamic storage = new DynStorage("mongodb://user:pass@example.org/MongoDBExample");

    // Get reference to the ExampleMessagesCollection collection, it's created if it doesn't already exist
    dynamic messagesCollection = storage.ExampleMessagesCollection;

    // Query for and display the message "Dr. Livingstone, I presume?"
    Console.WriteLine(MessageObjectModelQuery(messagesCollection, new Guid("1539964a-db24-46ba-8410-a91a2ed440b1")));
}

static string MessageObjectModelQuery(dynamic messagesCollection, Guid messageId)
{
    // Get a reference to an message document using the message id as the document id
    var messageDocument = messagesCollection.Document(messageId.ToString());

    return "Message=" + messageDocument.Message;
}

3.2.1 Slazure object model query optimizing

Each call to MessageObjectModelQuery() above makes a single database I/O operation to retrieve the Message property only, but what if there were two properties like below?

/// <summary>
/// Add a new message to the data MongoDB
/// </summary>
static void AddMessage(dynamic messagesCollection, string ipAddress, Guid messageId, string message, int messageNumber)
{
    // Create an document in the ExampleMessagesCollection collection using the message id as the document id.
    var messageDocument = messagesCollection.Document(messageId.ToString());
    messageDocument.Message = message;
    messageDocument.IpAddress = ipAddress;
    // Iterative message number sent from the IP-sddress
    messageDocument.Number = messageNumber;

    // Save the document to the Azure MongoDB
    messageDocument.Save();
}

static string MessageObjectModelQuery(dynamic messagesCollection, Guid messageId)
{
    // Get a reference to an message document using the message id as the document id
    var messageDocument = messagesCollection.Document(messageId.ToString());

    return "Message=" + messageDocument.Message + ", Number=" + messageDocument.Number;
}

In the case like above then each call to MessageObjectModelQuery() would mean two database I/O operations; one for each property read, which is of course wasteful of I/O resources. Fortunately, Slazure has a solution for this using the DynDocument.LoadSome() method like in the example below where both the Message and MessageNumber properties are queried from the storage with just a single I/O operation:

static string MessageObjectModelQuery(dynamic messagesCollection, Guid messageId)
{
    // Get a reference to an message document using the message id as the document id
    var messageDocument = messagesCollection.Document(messageId.ToString());
    var columnsToLoad = new List<string> { "Message""Number" };
    messageDocument.LoadSome(columnsToLoad);
    return "Message=" + messageDocument.Message + ", message number=" + messageDocument.Number;
}

Slazure also has a DynDocument.DynDocument.LoadAll() function which retrieves all the document properties in a single I/O operation:

static string MessageObjectModelQuery(dynamic messagesCollection, Guid messageId)
{
    // Get a reference to an message document using the message id as the document id
    var messageDocument = messagesCollection.Document( messageId.ToString());
    messageDocument.LoadAll();
    return "Message=" + messageDocument.Message + ", message number=" + messageDocument.Number;
}

3.3 Querying the database using the Slazure LINQ Provider

That’s the main things to consider when querying with the Slazure object model, now let’s look at achieving the same with the Slazure LINQ provider. In the example below we access the MongoDB using the QueryableStorage<TData> class this time; this is the data storage class that the Slazure LINQ Provider uses, and the DynDocument class is the base class for dynamically typed documents in Slazure:

// Query for and display the message "Dr. Livingstone, I presume?"
public static void ShowMessageWithLINQ()
{
    // Get a reference to MongoDB
    dynamic queryableStorage = new QueryableStorage<DynDocument>("mongodb://user:pass@example.org/MongoDBExample");
    QueryableCollection<DynDocument> queryableMessagesCollection = queryableStorage.ExampleMessagesCollection;

    Console.WriteLine(MessageLinqQuery(queryableMessagesCollection, "127.0.0.1"new Guid("1539964a-db24-46ba-8410-a91a2ed440b1")));
}

// Query for a message using the Slazure LINQ provider
static string MessageLinqQuery(IQueryable<DynDocument> messagesCollection, string ipAddress, Guid messageId)
{
    var messageQuery =
        messagesCollection.Where("IpAddress = @0 and id = @1", ipAddress, messageId.ToString())
        .Select("new(Message)");

    dynamic messageDocument = messageQuery.Cast<dynamic>().First();

    return "Message=" + messageDocument.Message + ", message number=" + messageDocument.Number;
}

3.3.1 Slazure LINQ Provider query optimizing

The above example would create two I/O operations since only Message is defined in the Select() query projection, by adding the Number property to the query projection you would fetch both document properties in a single I/O operation:

// Query for a message using the Slazure LINQ provider
static string MessageLinqQuery(IQueryable<DynDocument> messagesCollection, string ipAddress, Guid messageId)
{
    var messageQuery =
    messagesCollection.Where("IpAddress = @0 && id = @1", ipAddress, messageId.ToString())
    .Select("new(Message, Number)");

    dynamic messageDocument = messageQuery.Cast<dynamic>().First();

    return "Message=" + messageDocument.Message + ", message number=" + messageDocument.Number;
}
Published • Modified