Monday, December 17, 2018

Azure Cosmos DB SDK 3.0

   

Cosmos DB SDK 3.0

     Azure Cosmos DB has a new .NET SDK which is currently in public preview version. Since it's still in public preview version, Cosmos DB team recommends to use the version 2.x in production. I am excited to see that this version supports streams. You can use SDK 3 in .Net 4.6.1+ or .Net Core 2.0+ applications. Also, this version is open source and it is available at GitHub

    I use the following data model in my talks about Cosmos DB. I am going to use the same model since you can generate it by using WideWorldImporters database. Here is the query to generate it.


SELECT TOP 100 sales.orders.OrderId as id, sales.orders.OrderId,sales.orders.OrderDate, sales.orders.ExpectedDeliveryDate, Sales.Customers.CustomerID, Sales.Customers.CustomerName as [Customer.CustomerName], Sales.Customers.CreditLimit as [Customer.CreditLimit], Sales.Customers.AccountOpenedDate as [Customer.AccountOpenedDate], Sales.Customers.IsOnCreditHold as [Customer.IsOnCreditHold], Sales.Customers.DeliveryAddressLine1 as [Customer.Address1], Sales.Customers.DeliveryAddressLine2 as [Customer.Address2], Sales.Customers.DeliveryPostalCode as [Customer.Zipcode], Application.People.PersonID as [SalesPerson.PersonId], Application.People.FullName as [SalesPerson.FullName], Application.People.PhoneNumber as [SalesPerson.PhoneNumber], Application.People.IsExternalLogonProvider as [SalesPerson.IsExternalProvider], Application.People.EmailAddress as [SalesPerson.Email] 
FROM sales.orders join Sales.Customers on Sales.Orders.CustomerID = Sales.Customers.CustomerID 
join Application.People on sales.Orders.SalespersonPersonID = Application.People.PersonID

        This query gives me a simple data model. I have a main entity named Order, I join Order table to Customers and People tables to get informaton about the Customer and the salesperson. Here is what Order object looks like in Visual Studio.


   Next, I downloaded the SDK 3 from Nuget. Use the following synthax in Nuget Package Manager Console 

Install-Package Microsoft.Azure.Cosmos -Version 3.0.0.1-preview –prerelease


   To connect to the Cosmos DB in Azure or local emulator, I will need to pass Uri and endpoint information. You can find these information when you click Keys link in Azure portal or  in the QuickStart tab in Emulator.

Azure Portal

Azure Cosmos DB Emulator

I am going to put these information under appsettings in web.config. 


   Now, I have enough information to connect to Cosmos DB. DocumentClient used to be top level in SDK 2.x, It is replaced by CosmosClient in SDK 3.0, I need to pass endpoint and primary key to initialize CosmosClient.

var cosmosclient = new CosmosClient(currentEndpoint, currentUrl);

   Let's create a database first. I am not fan of creating databases from the code specially for SQL Server. Since we don't need to worry about schema problems in Cosmos DB, I might need to start to use this more but we still need to worry about what we should pass for the throughput options. At the end throughput is one of the key options determines how much Cosmos DB is going to cost. I like to set up the databases from the Azure Portal but SDK 3 gives you option if you like to do it from your Code. Remember all that lectures and arguments from your DBA when you tried to create a database with your ORM. You will not have them in Cosmos DB! I create a database named OrderTracker in this example.

var db = await cosmosClient.Databases.CreateDatabaseIfNotExistsAsync("OrderTracker");

     Next, Let's create a container in the new database. Just like creating database, I need to use the cosmosClient. There is a object named Containers under Databases property, I need to pass the name of the container and a partition key's path to CreateContainerIfNotExistsAsync function.

var response = await cosmosClient.Databases["OrderTracker"].Containers.CreateContainerIfNotExistsAsync("Orders", "/CustomerId");

    Now, we have a database named OrderTracker and it has a container named Orders. This container is going to store the Order object. It's time to insert some data into this container. To do that, I am going to use the CreateItemAsync function.

var response = await cosmosClient.Databases["OrderTracker"].Containers["Orders"].Items.CreateItemAsync(ordertosave.CustomerId.ToString(), ordertosave);

  It has been very easy to use CosmosDB SDK so far.  Let's try to read the data we just inserted now. To do that, I need to use ReadItemAsync method. I need to pass id and partitionid to be able to Read the order. Don't forget Read function will cost you always cheaper than running a query! Try to use Read as much as you can in your code!

var response = await cosmosClient.Databases["OrderTracker"].Containers["Orders"].Items.ReadItemAsync(ordertosave.CustomerId, ordertosave.OrderId);

    I use the following example in my demos when I talk about Cosmos DB SDK. Following code updates the data in Orders container. All the reponse objects have a property named RequestCharge. This property gives us how many Request Units are spent for our request. In the follwing example, I read the data first then update the data by using ReplaceItemAsync function.

public async Task<double> UpdateItem(Order ordertosave) 
 { 
     double total = 0; 
     var container = cosmosClient.Databases["OrderTracker"].Containers["Orders"]; 
     var response = await container.Items.ReadItemAsync<Order>(ordertosave.CustomerId, ordertosave.id);
     total += response.RequestCharge; 
     var itemBody = response.Resource; 
     itemBody = ordertosave; 
     response = await container.Items.ReplaceItemAsync<Order>(ordertosave.CustomerId, ordertosave.id, itemBody);
     total += response.RequestCharge;
     return total;
 }

    That's all I am going to cover today, I will continue to cover Cosmos DB SDK in my next posts.

1 comment: