<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Nick Chapsas</title>
    <description>The latest articles on DEV Community by Nick Chapsas (@elfocrash).</description>
    <link>https://dev.to/elfocrash</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F71833%2F2d22ed95-7b68-4c22-b921-02b1e7e23a98.jpg</url>
      <title>DEV Community: Nick Chapsas</title>
      <link>https://dev.to/elfocrash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elfocrash"/>
    <language>en</language>
    <item>
      <title>CosmosDB Fluent Pagination with Cosmonaut</title>
      <dc:creator>Nick Chapsas</dc:creator>
      <pubDate>Thu, 27 Sep 2018 10:41:43 +0000</pubDate>
      <link>https://dev.to/elfocrash/cosmosdb-fluent-pagination-with-cosmonaut-25gh</link>
      <guid>https://dev.to/elfocrash/cosmosdb-fluent-pagination-with-cosmonaut-25gh</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Ever wondered why the Azure Portal has scroll forward pagination and next/previous pagination but no page size + page number pagination? Go on take a wild guess. If you said "Because it runs on CosmosDB" then you're right. The Azure portal is getting it's results from CosmosDB that's why you don't see any form of server side skip and take pagination.&lt;/p&gt;

&lt;p&gt;If you ever see a page size and page number combination in the portal then the pagination is happening on the client side. An example of that would be the "Logs" section of Application Insights, which is able to return paged results with page size and page number but those results are pre-fetched and they are just rendered on the spot. We know that because you can find all the results returned in pages of 100 in the network traffic tool of our browser of choice. The client side code will do the rest of the paging job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FhmlVle3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FhmlVle3.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  CosmosDB pagination support
&lt;/h3&gt;

&lt;p&gt;CosmosDB doesn't support your traditional type of skip/take pagination. Instead results are always paged with a maximum page size.&lt;/p&gt;

&lt;p&gt;Skip take pagination is however, the most requested CosmosDB feature since August of 2014. The official ComosDB Team account replied in March of 2018 that they are planning to implement it, so we're good.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvDpygqr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FvDpygqr.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Judging based on the pace features are being delivered currently, I would not expect it to be delivered anytime soon so we need an alternative, at least for now.&lt;/p&gt;

&lt;p&gt;So what does CosmosDB support as of today in terms of pagination?&lt;/p&gt;

&lt;p&gt;Well, you have two values related to how results are being returned. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MaxItemCount&lt;/li&gt;
&lt;li&gt;RequestContinuation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MaxItemCount is the maximum nnumber of items to be returned in the enumeration operation. They can be less, but they won't exceed that number.&lt;br&gt;
The RequestContinuation is the continuation token which identifies which was the last result set for this operation and points CosmosDB to the next set of data it needs to return.&lt;/p&gt;

&lt;p&gt;This is enough functionality for someone to workaround the lack of skip take pagination. This is where Cosmonaut kicks in and does the heavy lifting for you.&lt;/p&gt;
&lt;h3&gt;
  
  
  Cosmonaut's implementation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Elfocrash/Cosmonaut" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FxL7AjSv.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since I started working on &lt;a href="https://github.com/Elfocrash/Cosmonaut" rel="noopener noreferrer"&gt;Cosmonaut&lt;/a&gt; I knew that, eventually, I'd have to add fluent pagination support.&lt;/p&gt;

&lt;p&gt;I did not want to mess with the &lt;code&gt;Skip&lt;/code&gt; and &lt;code&gt;Take&lt;/code&gt; LINQ methods because I know that eventually CosmosDB will support both of them (only supports &lt;code&gt;Take&lt;/code&gt; for now).&lt;/p&gt;

&lt;p&gt;Cosmonaut supports an &lt;code&gt;IQueryable&lt;/code&gt; extension called &lt;code&gt;WithPagination()&lt;/code&gt;. This method has two overloads.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WithPagination(int pageNumber, int pageSize)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WithPagination(string continuationToken, int pageSize)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, the first signature looks very much like a clear skip/take type implementation of the pagination. The second one is the direct CosmosDB approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do they work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first signature, that has both page number and page size, can get inefficient and expensive as the page number value increases. This is because the only way this method can work is by going through all the pages from the start until it hits that requested page number and page size.&lt;/p&gt;

&lt;p&gt;The second signature is both efficient and fast because it points straight to the next set of results. That's because you provide the continuation token.&lt;/p&gt;

&lt;p&gt;These methods work in Cosmonaut with both LINQ and SQL queries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How can you use them?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first signature is as simple to use as the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;OrderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;secondPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;OrderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this reads very simple and I think is very straightforward. The same thing with SQL would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"select * from c order by c.Name asc"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;secondPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"select * from c order by c.Name asc"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;These methods work with both the &lt;code&gt;CosmonautClient&lt;/code&gt; and the &lt;code&gt;CosmosStore&lt;/code&gt; methods.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, as I mentioned before, this is the method that can get inefficient as you go to higher page numbers. That's why the &lt;code&gt;WithPagination&lt;/code&gt; signature that supports the continuation token is recommended.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"But how do I get the continuation token?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The pagination update also introduced a new results extension method called &lt;code&gt;ToPagedListAsync()&lt;/code&gt;. This method returns a &lt;code&gt;CosmosPagedResults&lt;/code&gt; object. This object contains 3 very handy properties for your paged operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Results&lt;/code&gt;, which is a list of the results for your query&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HasNextPage&lt;/code&gt;, which is a boolean indicating if there are more pages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NextPageToken&lt;/code&gt;, which is a string providing you the next page continuation token, if any&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how this works. I'll write the same two page code that I have above but this time I'll use the continuation token approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;OrderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToPagedListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;secondPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;firstPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NextPageToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;OrderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToPagedListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple? I hope so. In a real life scenario, you would get the continuation token, store it on the client side (web app, desktop app, mobile app) and provide it for the next page.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CosmosPagedResults&lt;/code&gt; also support a &lt;code&gt;GetNextPageAsync&lt;/code&gt; method which automatically gets the token and size from the last page. The same two queries would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;firstPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;booksStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;OrderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToPagedListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;secondPage&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;firstPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetNextPageAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note:&lt;/p&gt;

&lt;p&gt;All of the above works with the &lt;code&gt;CosmonautClient&lt;/code&gt; querying methods as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;cosmonautClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Book&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"localtest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"shared"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;WithPagination&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pagination recommendations
&lt;/h3&gt;

&lt;p&gt;Because page number and page size pagination goes though all the documents until it gets to the requested page, it can get slow and expensive. The recommended approach would be to use the page number and page size method once for the first page and get the results using the &lt;code&gt;.ToPagedListAsync()&lt;/code&gt; method. This method will return the next continuation token and it will also tell you if there are more pages for this query. Then use the continuation token alternative of &lt;code&gt;WithPagination&lt;/code&gt; to continue from your last query.&lt;/p&gt;

&lt;p&gt;Keep in mind that this approach means that you have to keep state on the client for the next query, but that's what you'd do if you were using previous/next buttons anyway.&lt;/p&gt;

&lt;p&gt;I hope this helps you make integration with CosmosDB easier. Don't forget to ask questions in the comments if something is unclear and feel free to suggest features or express ideas for &lt;a href="https://github.com/Elfocrash/Cosmonaut" rel="noopener noreferrer"&gt;Cosmonaut&lt;/a&gt;. Also, if you like the project then giving it a star on Github means a lot. Thank you.&lt;/p&gt;

</description>
      <category>cosmosdb</category>
      <category>azure</category>
      <category>nosql</category>
    </item>
    <item>
      <title>Testing your CosmosDB C# code and automating it with AppVeyor</title>
      <dc:creator>Nick Chapsas</dc:creator>
      <pubDate>Mon, 17 Sep 2018 13:08:29 +0000</pubDate>
      <link>https://dev.to/elfocrash/testing-your-cosmosdb-c-code-and-automating-it-with-appveyor-1001</link>
      <guid>https://dev.to/elfocrash/testing-your-cosmosdb-c-code-and-automating-it-with-appveyor-1001</guid>
      <description>&lt;h4&gt;
  
  
  Introduction
&lt;/h4&gt;

&lt;p&gt;Don't we all love well tested code? I know I do.&lt;br&gt;
It's just an awesome feeling knowing that if I change something over here, the thing over there didn't break.&lt;/p&gt;

&lt;p&gt;However, when your code depends on a third party library, then you have to hope that the code in that library is easy to work with and easy to test.&lt;/p&gt;

&lt;p&gt;If this isn't the first blog of mine that you read then you probably know that I'm working on an open-source ORM for CosmosDB called &lt;a href="https://github.com/Elfocrash/Cosmonaut"&gt;Cosmonaut&lt;/a&gt;. When I'm using a third party library and its code happens to be opensource then the first thing I do is to go to wherever it's code is hosted and check if there are tests covering it. Nobody wants to use untested code, so I knew when I started that I should cover as many scenarios and cases as possible.&lt;/p&gt;
&lt;h4&gt;
  
  
  Unit testing
&lt;/h4&gt;

&lt;p&gt;The CosmosDB SDK is not as friendly as it could be when it comes to unit testing (and the CosmosDB SDK team knows it, so it will get better).&lt;br&gt;
Normally, the way you would unit test such code would be to mock the calls that would go over the wire and just return the dataset that you want this scenario to return.&lt;/p&gt;

&lt;p&gt;However here is a list of things that make it really hard for you to test your code.&lt;/p&gt;
&lt;h5&gt;
  
  
  Problem 1
&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;ResourceResponse&lt;/code&gt; class has the constructor that contains the &lt;code&gt;DocumentServiceResponse&lt;/code&gt; parameter marked as &lt;code&gt;internal&lt;/code&gt;. This is bad because even though you can create a &lt;code&gt;ResourceReponse&lt;/code&gt; object from your DTO class you cannot set things like RUs consumed, response code and pretty much anything else because they are all coming from the &lt;code&gt;ResourceResponseBase&lt;/code&gt; which also has the &lt;code&gt;DocumentServiceResponse&lt;/code&gt; marked as internal.&lt;/p&gt;
&lt;h5&gt;
  
  
  Solution
&lt;/h5&gt;

&lt;p&gt;To solve this problem you have to somehow set the response headers for the &lt;code&gt;ResourceResponse&lt;/code&gt;. As you might have guessed already, then only way you can do that is via reflection. Here is an extension method that can convert your generic type object to a &lt;code&gt;ResourceResponse&lt;/code&gt; and allows you to set the &lt;code&gt;responseHeaders&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;em&gt;This extension method is also part of Cosmonaut&lt;/em&gt;&lt;/p&gt;

&lt;h5&gt;
  
  
  Problem 2
&lt;/h5&gt;

&lt;p&gt;The SDK is using IQueryable in order to build a fluent LINQ query and use it to query your CosmosDB. This LINQ query will be then converted into SQL via an internal LINQ2CosmosDBSQL provider that the SDK comes with. The problem with that is that if you want to mock your &lt;code&gt;IDocumentClient&lt;/code&gt;'s &lt;code&gt;CreateDocumentQuery&lt;/code&gt; to return a specific data set based on a LINQ expression then you're in for a ride.&lt;/p&gt;

&lt;h5&gt;
  
  
  Solution
&lt;/h5&gt;

&lt;p&gt;Lets take a look at the code.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;As you can see, it needs quite the setup. That's because the &lt;code&gt;IQueryable&lt;/code&gt; needs to be setup from the ground up or else it won't be properly translated.&lt;/p&gt;

&lt;h5&gt;
  
  
  Problem 3
&lt;/h5&gt;

&lt;p&gt;It's basically the same as Problem 2 but for SQL, which makes it slightly easier because there is no IQueryable to setup.&lt;/p&gt;

&lt;h5&gt;
  
  
  Solution
&lt;/h5&gt;

&lt;p&gt;Almost everything in the code from "Problem 2" is the same. The only differences are between the lines 24-47. You need to replace those with the code below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;These 3 are the most common unit testing problems you will face with the CosmosDB SDK. Thankfully the other operations are easier to test, especially if you make use of the &lt;code&gt;ToResourceResponse&lt;/code&gt; extension method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;: As I was writing this Microsoft released the 2.0.0 version of the CosmosDB SDK packages and in them they changed the constructors of come classes.&lt;/p&gt;

&lt;p&gt;If you are using a post 2.0.0 version of the SDK, here are the extension methods you need.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h4&gt;
  
  
  Integration testing
&lt;/h4&gt;

&lt;p&gt;Unit testing is awesome, but you also want to test your system against a real database. These tests should have a wider scope than the unit-sized context of your unit tests. I won't go in depth on this one because everyone's idea of integration testing seems to be different but what you need to remember is that we are trying to test again the real CosmosDB database.&lt;/p&gt;

&lt;p&gt;As you probably know, CosmosDB comes with it's own local emulator. That's great because we can use it to run our integration/system tests against. What's also great is that we can use the same emulator as part of our CI pipeline. &lt;/p&gt;

&lt;h4&gt;
  
  
  Automating unit and integration testing
&lt;/h4&gt;

&lt;p&gt;I personally use &lt;a href="https://www.appveyor.com/"&gt;AppVeyor&lt;/a&gt; because it is incredibly easy to setup and get started, it supports loads of stuff such as Azure services and Nuget building out of the box and it is also free for open source projects.&lt;/p&gt;

&lt;p&gt;AppVeyor is as simple to setup as linking your Github account and selecting the repository you want it to run against. Once you set that up it will trigger a build every time you commit code. There are tons of stuff to configure if you want something more specific but in this blog I will just explain how you can setup the CosmosDB emulator in AppVeyor. &lt;/p&gt;

&lt;p&gt;AppVeyor will look for an &lt;code&gt;appveyor.yml&lt;/code&gt; file in your repository. If it's not there it will use the settings that can be found in the "Configuration" section. Our &lt;code&gt;appveyor.yml&lt;/code&gt; will be pretty simple. We just want to &lt;code&gt;dotnet build&lt;/code&gt; and &lt;code&gt;dotnet test&lt;/code&gt; our code. Before that however we need to install the CosmosDB Emulator on the AppVeyor VM. In order to do that we will need the following powershell script:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Now the CosmosDB Emulator is installed and you can enjoy testing against it using the default CosmosDB Emulator url &lt;code&gt;https://localhost:8081&lt;/code&gt; and the well known key &lt;code&gt;C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the final appveyor.yml&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Once you set that up, a build will be kicked off every time you commit code in the repository and both unit and integration tests will be run against the local CosmosDB emulator instance.&lt;/p&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;

</description>
      <category>cosmosdb</category>
      <category>azure</category>
      <category>appveyor</category>
      <category>nosql</category>
    </item>
    <item>
      <title>How to easily start using CosmosDB in your C# application in no time with Cosmonaut</title>
      <dc:creator>Nick Chapsas</dc:creator>
      <pubDate>Mon, 07 May 2018 20:33:27 +0000</pubDate>
      <link>https://dev.to/elfocrash/how-to-easily-start-using-cosmosdb-in-your-c-application-in-no-time-with-cosmonaut--mb9</link>
      <guid>https://dev.to/elfocrash/how-to-easily-start-using-cosmosdb-in-your-c-application-in-no-time-with-cosmonaut--mb9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvcd6vc3zowmlc5ir4h6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqvcd6vc3zowmlc5ir4h6.png" width="600" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've used a lot of document based NoSQL databases. CosmosDB is by far my favourite, mainly because it's much more than that. Things like it's scale-ability, the different API options, the change feed or even the emulator that Microsoft provides are amazing. &lt;/p&gt;

&lt;p&gt;However, unless you are willing to dedicate a lot of time reading about it, the integration experience can be a nightmare for some. Things like it's pricing, it's performance, partition keys and indexing just to name a few, can be too much. On top of that you have to use the SDKs provided by Microsoft, which aren't bad at all but unless you know when to use which method, you will end up having bad performance or paying way more than what you should be.&lt;/p&gt;

&lt;p&gt;Here's where &lt;a href="https://github.com/Elfocrash/Cosmonaut" rel="noopener noreferrer"&gt;Cosmonaut&lt;/a&gt; comes into play.&lt;br&gt;
It is wrapper library around the SQL API of CosmosDB to allow flexible CRUD (and more) based on objects. Some might say that the SQL API SDK already does that but please keep readying and you'll see what I mean.&lt;/p&gt;
&lt;h5&gt;
  
  
  Installation
&lt;/h5&gt;

&lt;p&gt;Cosmonaut is published on &lt;a href="https://www.nuget.org/packages/Cosmonaut" rel="noopener noreferrer"&gt;Nuget&lt;/a&gt;.&lt;br&gt;
You can install it from the Nuget browser or the command line&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Package&lt;/span&gt; &lt;span class="n"&gt;Cosmonaut&lt;/span&gt;
&lt;span class="k"&gt;or&lt;/span&gt;
&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Cosmonaut&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you add the package, integration can be as simple as adding the following line in your DI service collection.&lt;br&gt;
&lt;code&gt;serviceCollection.AddCosmosStore&amp;lt;YourObject&amp;gt;(cosmosSettings);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once you do that you can get &lt;code&gt;ICosmosStore&amp;lt;YourObject&amp;gt;&lt;/code&gt; from DI and you are ready to roll.&lt;br&gt;
Alternatively, you can manually create a CosmosStore object.&lt;/p&gt;

&lt;p&gt;CosmosStoreSettings have only 3 mandatory settings in it. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DatabaseName&lt;/li&gt;
&lt;li&gt;AuthKey&lt;/li&gt;
&lt;li&gt;EndpointUrl&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are more things that can be configured like the &lt;code&gt;ConnectionPolicy&lt;/code&gt; or the &lt;code&gt;IndexingPolicy&lt;/code&gt; but if they are not set they will default to the CosmosDB default values.&lt;/p&gt;
&lt;h5&gt;
  
  
  How to use
&lt;/h5&gt;

&lt;p&gt;By default Cosmonaut will create/need one collection per object. However it also has logic for collection sharing between different objects. We will talk about this later.&lt;/p&gt;

&lt;p&gt;For now all you need to know is that there is a single main restriction.&lt;/p&gt;

&lt;p&gt;Your objects will NEED to tick one of the following checkboxes&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have a property of type &lt;code&gt;string&lt;/code&gt; named &lt;code&gt;Id&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Implement the &lt;code&gt;ICosmosEntity&lt;/code&gt; interface&lt;/li&gt;
&lt;li&gt;Extend the &lt;code&gt;CosmosEntity&lt;/code&gt; class&lt;/li&gt;
&lt;li&gt;Have a property of type &lt;code&gt;string&lt;/code&gt; with the attribute &lt;code&gt;[JsonProperty("id")]&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is to ensure that your object can be stored, retrieved and updated in CosmosDB.&lt;/p&gt;

&lt;p&gt;If you are planning to do any &lt;code&gt;Select(x =&amp;gt; x.Id)&lt;/code&gt; queries then you must have the &lt;code&gt;[JsonProperty("id")]&lt;/code&gt; attribute OR extend the &lt;code&gt;CosmosEntity&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;The name of the collection created by Cosmonaut (when the collection is missing) is generated in the following way. If the object has the &lt;code&gt;CosmosCollection&lt;/code&gt; attribute then you can specify the name of the collection there. If not then a pluralized version of the object's name will be used instead. The attribute is also great if you want to add Cosmonaut in your existing CosmosDB collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The CosmosStore has the following methods for object manipulation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AddAsync(TEntity entity)&lt;/code&gt; Adds an object in the CosmosDB collection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UpdateAsync(TEntity entity)&lt;/code&gt; Updates an existing object in the CosmosDB collection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UpsertAsync(TEntity entity)&lt;/code&gt; Updates an existing object in the CosmosDB collection or Adds it if it is not in the collection.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;RemoveAsync(TEntity entity)&lt;/code&gt; Removed an object from the CosmosDB collection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of the above also have a &lt;code&gt;Range&lt;/code&gt; method which allows the action to happen for a collection of items. RemoveAsync also supports expression removals based on a filter.&lt;/p&gt;

&lt;p&gt;The operation responses also contain the ResourceResponse of the Document itself as well in order to allow for the retrieval of low level information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When it comes to querying...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;...you can simply call the &lt;code&gt;.Query()&lt;/code&gt; method and have a IQueryable ready to use. Keep in mind that at the query level CosmosDB only supports &lt;code&gt;Where&lt;/code&gt;, &lt;code&gt;Select&lt;/code&gt; and &lt;code&gt;SelectMany&lt;/code&gt;.&lt;br&gt;
When you want to return the query you just built to a List or just get the first object you have two options. &lt;/p&gt;

&lt;p&gt;You can use the LINQ method &lt;code&gt;ToList()&lt;/code&gt; but this is a synchronous call that is not recommended. What you should do instead is to use one of the extension methods that come with Cosmonaut such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ToListAsync&lt;/li&gt;
&lt;li&gt;CountAsync&lt;/li&gt;
&lt;li&gt;FirstOrDefaultAsync&lt;/li&gt;
&lt;li&gt;FirstAsync&lt;/li&gt;
&lt;li&gt;SingleOrDefaultAsync&lt;/li&gt;
&lt;li&gt;SingleAsync&lt;/li&gt;
&lt;li&gt;MaxAsync&lt;/li&gt;
&lt;li&gt;MinAsync&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These methods will use the built int paging logic to ensure that you application doesn't get locked while Cosmonaut is retrieving documents for you.&lt;/p&gt;

&lt;p&gt;As you can tell this gives you pretty much everything you need to get you started.&lt;/p&gt;
&lt;h5&gt;
  
  
  Partition Key
&lt;/h5&gt;

&lt;p&gt;The partition key is one of the most important things you need to know about in CosmosDB. This blog won't explain exactly what it is and how it works but it will let you know how Cosmonaut works with it. More on partition keys &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;There are a couple of things you need to know about the partition key.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once a collection is created without a partition key, you CANNOT add one.&lt;/li&gt;
&lt;li&gt;Once a collection is created with a partition key, you CANNOT change it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In non shared collections Cosmonaut will not add a partition key by default. However by using the &lt;code&gt;[CosmosPartitionKey]&lt;/code&gt; attribute you can specify which property is your partition key property. This will be used to create the collection with the key if the collection isn't created yet.&lt;/p&gt;
&lt;h5&gt;
  
  
  Indexing
&lt;/h5&gt;

&lt;p&gt;Indexing plays a big role when it comes to querying your document's properties.&lt;br&gt;
By default a cosmosdb collection is created with the following collection rules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"indexingMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"consistent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"automatic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;"includedPaths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"indexes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Range"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"dataType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"precision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="s"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hash"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"dataType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"String"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="s"&gt;"precision"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="s"&gt;"excludedPaths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is also not a blog explaining Indexing so i won't go in depth but what you need to know is that you cannot partially query strings if the kind is Hash. You can only exact match them. Cosmonaut allows you to override that at the settings level. Changing the Hash to Range would allow things like &lt;code&gt;StartsWith&lt;/code&gt; to match the data you want.&lt;/p&gt;

&lt;p&gt;Example: If the String datatype is Hash then exact matches like the following, &lt;code&gt;cosmoStore.Query().FirstOrDefaultAsync(x =&amp;gt; x.SomeProperty.Equals($"Nick Chapsas")&lt;/code&gt; will return the item if it exists in CosmosDB but &lt;code&gt;cosmoStore.Query().FirstOrDefaultAsync(x =&amp;gt; x.SomeProperty.StartsWith($"Nick Ch")&lt;/code&gt; will throw an error. Changing the Hash to Range will make the latter work.&lt;/p&gt;

&lt;p&gt;However you can also override this at the query level aswell by just changing the &lt;code&gt;EnableScanInQuery&lt;/code&gt; in &lt;code&gt;FeedOptions&lt;/code&gt; to true.&lt;/p&gt;

&lt;p&gt;More on indexing &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/indexing-policies" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h5&gt;
  
  
  Saving money
&lt;/h5&gt;

&lt;p&gt;I get it. RU/s are scary, but don't worry, Cosmonaut is designed to take that fear away.&lt;/p&gt;

&lt;p&gt;You see, the way CosmosDB is charging you is hourly PER collection. However if you change your RU/s in an hour for even a second then you will be charged 1 hours worth of whatever the highest RU/s for that hour was.&lt;/p&gt;

&lt;p&gt;This can get out of hand and not every collection needs to be separated from the other. Keep in mind this is a schema-less database so why not share collections.&lt;/p&gt;

&lt;p&gt;Well Cosmonaut has built in support for collection sharing.&lt;br&gt;
All you need to do to reliably share collections without messing up your operations are two things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decorate your object with the &lt;code&gt;SharedCosmosCollection&lt;/code&gt; attribute.&lt;/li&gt;
&lt;li&gt;Implement the &lt;code&gt;ISharedCosmosEntity&lt;/code&gt; interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will also need to specify the name of the shared collection that this object will be using like that &lt;code&gt;[SharedCosmosCollection("shared")]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only compromise is that your indexing cannot be very specific because you are sharing collections.&lt;br&gt;
Something that i also enabled is that if you are collection sharing then the &lt;code&gt;id&lt;/code&gt; property will automatically become your partition key. There are two reasons that back up this choice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You cannot add a partition key after the collection is created and it's a shame to not have at least random partition distribution.&lt;/li&gt;
&lt;li&gt;You are not guaranteed to have any other common property between your documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Code
&lt;/h5&gt;

&lt;p&gt;Cosmonaut is open source on &lt;a href="https://github.com/Elfocrash/Cosmonaut" rel="noopener noreferrer"&gt;Github&lt;/a&gt; under the MIT license.&lt;/p&gt;

&lt;p&gt;Please consider giving it a try and reporting any issues there.&lt;br&gt;
Also a star on the GitHub repo makes me feel warm inside.&lt;/p&gt;

&lt;p&gt;Feedback is also hugely appreciated.&lt;/p&gt;

</description>
      <category>cosmosdb</category>
      <category>nosql</category>
      <category>database</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
