{"id":3335,"date":"2019-07-27T23:46:49","date_gmt":"2019-07-28T06:46:49","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/odata\/?p=3335"},"modified":"2019-07-28T22:32:44","modified_gmt":"2019-07-29T05:32:44","slug":"integrating-cosmos-db-with-odata-part-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/odata\/integrating-cosmos-db-with-odata-part-1\/","title":{"rendered":"Integrating Cosmos DB with OData (Part 1)"},"content":{"rendered":"<p>We talked in previous articles about the pluggability of OData with any storage technology regardless of its schema, whether it\u2019s a SQL-based storage, NoSQL, In-Memory or simply a file on a hard-drive.<\/p>\n<p>This power of OData enables developers to work with powerful, planet-scale storage technologies such as Cosmos DB.<\/p>\n<p>In this article we are going to deep dive into one of three ways you can integrate Cosmos DB with OData but before we start, let\u2019s talk a little bit about Cosmos DB, it\u2019s capabilities and why it\u2019s important to be able to expose that storage powerful through an API with OData.<\/p>\n<p>&nbsp;<\/p>\n<h3>What is Cosmos DB?<\/h3>\n<p>Azure Cosmos DB is Microsoft&#8217;s globally distributed, multi-model database service. It enables you to elastically and independently scale throughput and storage across any number of Azure regions worldwide. You can elastically scale throughput and storage, and take advantage of fast, single-digit-millisecond data access using your favorite API including SQL, MongoDB, Cassandra, Tables, or Gremlin.<\/p>\n<p>Cosmos DB is a perfect solution for the hot category of storage, specifically data that needs to be accessed frequently and be retrieved as fast as possible.<\/p>\n<p>&nbsp;<\/p>\n<h3>Cosmos DB with OData<\/h3>\n<p>When planning to integrate Cosmos DB with OData, there are three different ways you can follow to accomplish that level of integration based on your preference and whichever model fits the application you\u2019re developing.<\/p>\n<p>If you don\u2019t have any specific preference when it comes to integrating Cosmos DB with OData, I highly recommend you try them all, and judge for yourself which approach is easier and best fits your needs.<\/p>\n<p>&nbsp;<\/p>\n<p>Let\u2019s talk about the first of these approaches in this article.<\/p>\n<p>&nbsp;<\/p>\n<h3>First Approach: Pre-Built ASP.NET Core Solution<\/h3>\n<p>Cosmos DB in Azure Portal comes with some amazing options that enable you to download a full solution with full CRUD operations and UI to interact with Cosmos DB.<\/p>\n<p>In order for you to do that, go to your Azure portal and create a new Cosmos DB resource as follows:<\/p>\n<p>&nbsp;<\/p>\n<h3>Setting up Cosmos DB<\/h3>\n<ol>\n<li>Click on \u201cCreate a resource\u201d button at the top left corner in your Azure Portal:<\/li>\n<\/ol>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-3336 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/1.png\" alt=\"\" width=\"624\" height=\"284\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/1.png 624w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/1-300x137.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/p>\n<ol start=\"2\">\n<li>Search for Azure Cosmos DB, then click \u201cCreate\u201d button.<\/li>\n<\/ol>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-3337 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/2.png\" alt=\"\" width=\"624\" height=\"419\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/2.png 624w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/2-300x201.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/p>\n<ol start=\"3\">\n<li>When you click the \u201cCreate\u201d button, you will be presented with a bunch of options to select which API you\u2019d like to choose to interact with Cosmos DB \u2013 for the first and second approach we are going to select \u201cCore (SQL)\u201d as our option as follows:<\/li>\n<\/ol>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-3338 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/3.png\" alt=\"\" width=\"624\" height=\"619\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/3.png 624w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/3-150x150.png 150w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/3-300x298.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/p>\n<p>You might need to create a new resource group and select an account name \u2013 for this demo I have named my account studentsdb.<\/p>\n<p>Make sure your account name is all lowercase.<\/p>\n<p>After that\u2019s done, click \u201cReview + create\u201d button to create your new Cosmos DB instance.<\/p>\n<p>The creation process of a Cosmos DB instance might take between 1 \u2013 5 minutes depending on what type of configuration you\u2019ve chosen to build your instance.<\/p>\n<ol start=\"4\">\n<li>When the creation is completed \u2013 go to the quick start option on the left side menu, you will be presented with the following options to work with Cosmos DB.<img decoding=\"async\" class=\"aligncenter wp-image-3339 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/4.png\" alt=\"\" width=\"624\" height=\"248\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/4.png 624w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/4-300x119.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/li>\n<li>Select \u201c.NET Core\u201d option then click the \u201cCreate \u2018Items\u2019 Contains\u201d button \u2013 it will create a sample container for you to work with.<\/li>\n<li>Once the items container is created, click the \u201cDownload\u201d button to download a full ASP.NET Core MVC solution for full CRUD operations to interact with the sample container you just created.\n<img decoding=\"async\" class=\"aligncenter wp-image-3340 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/5.png\" alt=\"\" width=\"624\" height=\"461\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/5.png 624w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/5-300x222.png 300w\" sizes=\"(max-width: 624px) 100vw, 624px\" \/><\/li>\n<li><span style=\"font-size: 1rem;\">Now that you have downloaded the solution, build the solution, then try to run the solution to make sure all the configurations are set correctly, all dependencies are downloaded and that you can actually interact with the container in your Cosmos DB instance &#8211; in this demo I&#8217;m going to add a couple of records in the ToDoList.\n<\/span>(Note: you might be prompted by Visual Studio 2019 that you&#8217;re opening a solution downloaded from the internet &#8211; since Azure portal is a trusted source go ahead and click OK)<\/li>\n<\/ol>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-3346 size-full\" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/6.png\" alt=\"\" width=\"595\" height=\"488\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/6.png 595w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/6-300x246.png 300w\" sizes=\"(max-width: 595px) 100vw, 595px\" \/><\/p>\n<p>To verify that the records you&#8217;ve created have been successfully persisted, you can go back to your Azure portal and click &#8220;Open Data Explorer&#8221; button to check the records you created.<\/p>\n<p>The following screenshots show you the data navigation and retrieval on the data explorer window in Azure:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-3347 \" src=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/7.png\" alt=\"\" width=\"1262\" height=\"477\" srcset=\"https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/7.png 1401w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/7-300x113.png 300w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/7-768x291.png 768w, https:\/\/devblogs.microsoft.com\/odata\/wp-content\/uploads\/sites\/23\/2019\/07\/7-1024x387.png 1024w\" sizes=\"(max-width: 1262px) 100vw, 1262px\" \/><\/p>\n<p>This completes and verifies the setup portion of this first approach.<\/p>\n<p>Now, let&#8217;s go ahead an utilize the CRUD operations code to build a new API and integrate OData.<\/p>\n<p>You will notice that the solution we downloaded from Azure Portal implements the Repository pattern, which offer all CRUD operations needed to run an API.<\/p>\n<p>For this demo, we will focus on the following code in <em>ItemController.cs<\/em> file:<\/p>\n<pre class=\"lang:c# decode:true\">        private readonly IDocumentDBRepository&lt;todo.Models.Item&gt; Respository;\r\n        public ItemController(IDocumentDBRepository&lt;todo.Models.Item&gt; Respository)\r\n        {\r\n            this.Respository = Respository;\r\n        }\r\n\r\n        [ActionName(\"Index\")]\r\n        public async Task&lt;IActionResult&gt; Index()\r\n        {\r\n            var items = await Respository.GetItemsAsync(d =&gt; !d.Completed);\r\n            return View(items);\r\n        }<\/pre>\n<p>We will create an API controller let&#8217;s call it <em>ItemsController.cs\u00a0<\/em>and use the exact same code snippet above to build an endpoint that returns all items from Cosmos DB in JSON format &#8211; our new controller would look something like this:<\/p>\n<pre class=\"lang:default decode:true \">using System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\nusing Microsoft.AspNetCore.Mvc;\r\nusing todo;\r\nusing todo.Models;\r\n\r\nnamespace quickstartcore.Controllers\r\n{\r\n    [Produces(\"application\/json\")]\r\n    [Route(\"api\/Items\")]\r\n    public class ItemsController : Controller\r\n    {\r\n        private readonly IDocumentDBRepository&lt;Item&gt; Respository;\r\n        public ItemsController(IDocumentDBRepository&lt;Item&gt; Respository)\r\n        {\r\n            this.Respository = Respository;\r\n        }\r\n\r\n        \/\/ GET: api\/Items\r\n        [HttpGet]\r\n        public async Task&lt;IEnumerable&lt;Item&gt;&gt; Get()\r\n        {\r\n            return await Respository.GetItemsAsync(d =&gt; !d.Completed);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p>Let&#8217;s verify our endpoint is functional by hitting the endpoint in the browser or using a tool like Postman, your response for hitting an endpoint:<\/p>\n<pre class=\"lang:default decode:true\">http:\/\/localhost:1234\/api\/items<\/pre>\n<p>Your response should look something like this:<\/p>\n<pre class=\"lang:default decode:true\">[\r\n    {\r\n        \"id\": \"3f0beb77-dd24-4b51-a921-6a34c60e7b4b\",\r\n        \"name\": \"Brush your teeth\",\r\n        \"description\": \"brush your teeth tonight\",\r\n        \"isComplete\": false\r\n    },\r\n    {\r\n        \"id\": \"739c3cef-58b6-48a6-ad8f-21b485bb326f\",\r\n        \"name\": \"Organize Office\",\r\n        \"description\": \"Organize your office\",\r\n        \"isComplete\": false\r\n    }\r\n]<\/pre>\n<p>&nbsp;<\/p>\n<h3>OData Integration<\/h3>\n<p>Now that we have implemented and verified our controller endpoint is functional, let&#8217;s do the exact same steps we&#8217;ve done in this <a href=\"https:\/\/devblogs.microsoft.com\/odata\/supercharging-asp-net-core-api-with-odata\/\">article<\/a> to implement OData in our solution.\nI will summarize these steps here as follows:<\/p>\n<ol>\n<li>Add a Nuget package <strong>Microsoft.AspNetCore.OData\u00a0<\/strong>to your solution.<\/li>\n<li>Add OData service in your <em>startup.cs<\/em> file, then enable dependency injection along with the functions you want OData to provide through your API, here&#8217;s an example of how your file should look:\n<pre class=\"lang:c# decode:true\">using System.Linq;\r\nusing Microsoft.AspNet.OData.Extensions;\r\nusing Microsoft.AspNetCore.Builder;\r\nusing Microsoft.AspNetCore.Hosting;\r\nusing Microsoft.Extensions.Configuration;\r\nusing Microsoft.Extensions.DependencyInjection;\r\nusing Microsoft.Extensions.Logging;\r\nusing todo;\r\n\r\nnamespace quickstartcore\r\n{\r\n    public class Startup\r\n    {\r\n        public Startup(IHostingEnvironment env)\r\n        {\r\n            var builder = new ConfigurationBuilder()\r\n                .SetBasePath(env.ContentRootPath)\r\n                .AddJsonFile(\"appsettings.json\", optional: true, reloadOnChange: true)\r\n                .AddJsonFile($\"appsettings.{env.EnvironmentName}.json\", optional: true)\r\n                .AddEnvironmentVariables();\r\n            Configuration = builder.Build();\r\n        }\r\n\r\n        public IConfigurationRoot Configuration { get; }\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            \/\/ Add framework services.\r\n            services.AddMvc();\r\n\r\n            services.AddSingleton&lt;IDocumentDBRepository&lt;todo.Models.Item&gt;&gt;(new DocumentDBRepository&lt;todo.Models.Item&gt;());\r\n            services.AddOData();\r\n        }\r\n\r\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)\r\n        {\r\n            loggerFactory.AddConsole(Configuration.GetSection(\"Logging\"));\r\n            loggerFactory.AddDebug();\r\n\r\n            if (env.IsDevelopment())\r\n            {\r\n                app.UseDeveloperExceptionPage();\r\n                app.UseBrowserLink();\r\n            }\r\n            else\r\n            {\r\n                app.UseExceptionHandler(\"\/Home\/Error\");\r\n            }\r\n\r\n            app.UseStaticFiles();\r\n\r\n            app.UseMvc(routes =&gt;\r\n            {\r\n                routes.MapRoute(\r\n                    name: \"default\",\r\n                    template: \"{controller=Item}\/{action=Index}\/{id?}\");\r\n\r\n                routes.EnableDependencyInjection();\r\n                routes.Select().Filter().OrderBy().Expand();\r\n            });\r\n        }\r\n    }\r\n}<\/pre>\n<\/li>\n<li>Let&#8217;s update our controller (<em>ItemsController.cs<\/em>) to enable OData query &#8211; your controller file should look as follows:\n<pre class=\"lang:c# decode:true \">using System.Collections.Generic;\r\nusing System.Threading.Tasks;\r\nusing Microsoft.AspNet.OData;\r\nusing Microsoft.AspNetCore.Mvc;\r\nusing todo;\r\nusing todo.Models;\r\n\r\nnamespace quickstartcore.Controllers\r\n{\r\n    [Produces(\"application\/json\")]\r\n    [Route(\"api\/Items\")]\r\n    public class ItemsController : Controller\r\n    {\r\n        private readonly IDocumentDBRepository&lt;Item&gt; Respository;\r\n        public ItemsController(IDocumentDBRepository&lt;Item&gt; Respository)\r\n        {\r\n            this.Respository = Respository;\r\n        }\r\n\r\n        \/\/ GET: api\/Items\r\n        [HttpGet]\r\n        [EnableQuery()]\r\n        public async Task&lt;IEnumerable&lt;Item&gt;&gt; Get()\r\n        {\r\n            return await Respository.GetItemsAsync(d =&gt; !d.Completed);\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<\/li>\n<li>Let&#8217;s verify our new endpoint with OData integration by hitting an endpoint like:\n<pre class=\"lang:default decode:true \">http:\/\/localhost:36442\/api\/items?$select=name<\/pre>\n<p>And your response should look as follows:<\/p>\n<pre class=\"lang:default decode:true\">[\r\n    {\r\n        \"name\": \"Brush your teeth\"\r\n    },\r\n    {\r\n        \"name\": \"Organize Office\"\r\n    }\r\n]<\/pre>\n<p>&nbsp;<\/li>\n<\/ol>\n<p>By seeing this result, we verified OData is functional on your API retrieving and processing data from your Cosmos DB instance container.\nIn the next article, we will discuss working with OData &amp; Cosmos DB using the EntityFramework in ASP.NET Core API.<\/p>\n<h3>Final Notes<\/h3>\n<ol>\n<li>You can download the solution I used to run this demo from <a href=\"https:\/\/github.com\/hassanhabib\/ODataWithCosmosDBPart1\">here<\/a> (Don&#8217;t forget to update the endpoint &amp; key values in <em>DocumentDBRepository.cs<\/em> file.<\/li>\n<li>The current demo uses ASP.NET Core 2.2 example, but there are so many other options including classic ASP.NET MVC applications that I encourage you to try out.<\/li>\n<li>The current demo uses Item as a model, you will need to modify the solution slightly to work with whatever model you want to run your application.<\/li>\n<li>I highly recommend following this <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/cosmos-db\/\">link<\/a> to learn more about Cosmos DB and it&#8217;s capabilities.<\/li>\n<li>Huge thanks to Cosmos DB team for providing such a great documentation around such powerful technology.<\/li>\n<li>I also highly recommend staying up-to-date with all the new updates in Cosmos DB by following this <a href=\"https:\/\/azure.microsoft.com\/en-gb\/blog\/tag\/cosmos-db\/\">link<\/a> to their blog.<\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We talked in previous articles about the pluggability of OData with any storage technology regardless of its schema, whether it\u2019s a SQL-based storage, NoSQL, In-Memory or simply a file on a hard-drive. This power of OData enables developers to work with powerful, planet-scale storage technologies such as Cosmos DB. In this article we are going [&hellip;]<\/p>\n","protected":false},"author":3348,"featured_media":3345,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,117],"tags":[],"class_list":["post-3335","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-odata","category-webapi"],"acf":[],"blog_post_summary":"<p>We talked in previous articles about the pluggability of OData with any storage technology regardless of its schema, whether it\u2019s a SQL-based storage, NoSQL, In-Memory or simply a file on a hard-drive. This power of OData enables developers to work with powerful, planet-scale storage technologies such as Cosmos DB. In this article we are going [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/3335","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/users\/3348"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/comments?post=3335"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/posts\/3335\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media\/3345"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/media?parent=3335"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/categories?post=3335"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/odata\/wp-json\/wp\/v2\/tags?post=3335"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}