<?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: George Saadeh</title>
    <description>The latest articles on DEV Community by George Saadeh (@gsaadeh).</description>
    <link>https://dev.to/gsaadeh</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%2F603291%2F4654cf1f-3ff4-4bdd-8e09-ded17116fefb.png</url>
      <title>DEV Community: George Saadeh</title>
      <link>https://dev.to/gsaadeh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gsaadeh"/>
    <language>en</language>
    <item>
      <title>Hello AWS Microservice Extractor for .NET, Let's Work on that Legacy App</title>
      <dc:creator>George Saadeh</dc:creator>
      <pubDate>Wed, 08 Dec 2021 15:23:30 +0000</pubDate>
      <link>https://dev.to/gsaadeh/hello-aws-microservice-extractor-for-net-lets-work-on-that-legacy-app-27p8</link>
      <guid>https://dev.to/gsaadeh/hello-aws-microservice-extractor-for-net-lets-work-on-that-legacy-app-27p8</guid>
      <description>&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;Organizations are increasingly facing challenges while modernizing their legacy applications especially those their business depends on for day-to-day operations. Many are actively looking to progressively decompose large monoliths (legacy or not) into microservices as these systems become too large to deal with.&lt;/p&gt;

&lt;p&gt;There are different strategies, techniques and patterns teams can use to break down a monolithic application. Recently AWS introduced the &lt;a href="https://aws.amazon.com/microservice-extractor/" rel="noopener noreferrer"&gt;AWS Microservice Extractor for .NET&lt;/a&gt;, a new tool that helps customers on their path to extract microservices from their monolithic applications. It simplifies the process of refactoring applications into independent services using source code analysis and visual representations.&lt;/p&gt;

&lt;p&gt;In this tutorial, we look at how we can use the &lt;a href="https://aws.amazon.com/microservice-extractor/" rel="noopener noreferrer"&gt;AWS Microservice Extractor for .NET&lt;/a&gt; on a real-world application to extract a service.&lt;/p&gt;

&lt;p&gt;At the time of writing the AWS Microservice Extractor for .NET supports only .NET Framework CLR 4.0+ ASP.NET web service applications hosted on IIS and the extraction only supports CLR 4.7.0+. Therefore I decided to use the source of one of the Web API projects I worked on in the past which was built on .NET 4.6.1 and which I've upgraded to 4.7.2. Luckily the upgrade was smooth.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I do not own the source code of this application and I was only a contributor. Therefore I made sure not to share any code. I also disabled data sharing during analysis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is only worth noting that AWS Microservice Extractor for .NET is available for use at no cost which is phenomenal.&lt;/p&gt;

&lt;h1&gt;
  
  
  Preparations
&lt;/h1&gt;

&lt;p&gt;To prepare the environment, I followed the instructions in the &lt;a href="https://docs.aws.amazon.com/microservice-extractor/latest/userguide/microservice-extractor-prerequisites.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I created a new IAM user and attached a custom IAM policy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"serviceextract:GetConfig"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SectionForMetricsService"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"execute-api:invoke"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:execute-api:us-east-1:*:*/prod/POST/put-metric-data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:execute-api:us-east-1:*:*/prod/POST/put-log-data"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I then configured my AWS CLI profile and installed the AWS Microservice Extractor for .NET tool.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cyttdbd3xme95ha558s.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cyttdbd3xme95ha558s.png" alt="Setup the tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I did not need to do the rest of the steps since my Windows VM already had Visual Studio 2019 installed with multiple versions of the .NET framework.&lt;/p&gt;

&lt;p&gt;After the quick configuration the setup was successful.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzr0gkbu9josufdi6lcy5.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzr0gkbu9josufdi6lcy5.png" alt="Setup successful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Onboarding
&lt;/h1&gt;

&lt;p&gt;After downloading the application code on my machine I was ready to start the analysis.&lt;/p&gt;

&lt;p&gt;I clicked on Onboard application and I've added the solution file which points to the Web API application. I did not select the runtime profiling data.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw19896i0eojajdlzq2sa.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw19896i0eojajdlzq2sa.png" alt="Onboard application"&gt;&lt;/a&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3h4outqlfr8927sjpat.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3h4outqlfr8927sjpat.png" alt="Onboarding in progress"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a few minutes, the application was onboarded successfully.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It is worth noting that the tool includes analysis for .NET core portability which is great.&lt;/p&gt;
&lt;/blockquote&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtwsmcfgnes3ariv92hr.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqtwsmcfgnes3ariv92hr.png" alt="Onboarding successful"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Visualizing
&lt;/h1&gt;

&lt;p&gt;Now comes the exciting part. My application was analyzed and I was ready to see the visual representation.&lt;/p&gt;

&lt;p&gt;The purpose of this visualization exercise is to learn more about the application components, dependencies and metrics to "quickly" identify which could be refactored into smaller service. &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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjn8dq5yw0ca62rzhsext.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjn8dq5yw0ca62rzhsext.png" alt="Visualize the app high level"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, this was a bit surprising at first glance with all the different connections. After going through the &lt;a href="https://docs.aws.amazon.com/microservice-extractor/latest/userguide/microservice-extractor-use-visualization.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; I was able to navigate the interface slightly better and identity some of the services I have. I used the filter to look up my SpeakerService.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulalpnwfr00ae3kuttgg.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fulalpnwfr00ae3kuttgg.png" alt="Use the filter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To understand the dependencies of the service, I clicked on it and I was presented with a nice view of the edges. Superb!&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1wgznbe2nkqb5akh3hc.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1wgznbe2nkqb5akh3hc.png" alt="Visualize edges"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Isolating the service in a separate part of the graph was no trivial task. After some battling, I managed to get the components grouped and ready for extraction.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcg5xdryf4anllenwas4.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcg5xdryf4anllenwas4.png" alt="Group service"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h1&gt;
  
  
  Extracting
&lt;/h1&gt;

&lt;p&gt;Exhilarated and curious, I hit the extract group as service button.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w6uvre36thikhsrs5h7.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1w6uvre36thikhsrs5h7.png" alt="Extract group as service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I entered a few details about the service and then select which invocation method i want to use.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5f1p4h4rjo9wbddgtr80.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5f1p4h4rjo9wbddgtr80.png" alt="Service details"&gt;&lt;/a&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9tcpqv7gqeys5j5rtsr.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq9tcpqv7gqeys5j5rtsr.png" alt="Invocation method"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few rounds of trial and error between the visual designer and the extractor and I was still getting this. The extraction halted at 60%.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Command failed: error while building and applying rules to transform the MicroService: error while updating build files for microservice: unable to remove some projects from sln
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It was one of the &lt;code&gt;infrastructure&lt;/code&gt; projects that it couldn't remove from the solution.&lt;/p&gt;

&lt;p&gt;Nevertheless, the extraction of the &lt;code&gt;SpeakerService&lt;/code&gt; completed according to the application details screen and also the logs.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkepa3g4g0t2z0d1z4nwo.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkepa3g4g0t2z0d1z4nwo.png" alt="Service extracted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The log file can be found in the installation directly under /logs/drift-extraction.log.&lt;/p&gt;

&lt;p&gt;The extracted service was located in the installation directory.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnipf23zk8ko6l67gn2qd.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnipf23zk8ko6l67gn2qd.png" alt="Extracted service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Opening the solution of the ApiIntegrationService in Visual Studio revealed multiple missing "infrastructure" projects which is probably why the extraction failed.&lt;/p&gt;

&lt;p&gt;I can take it from here and add the missing dependencies and get the service in a build-able state.&lt;/p&gt;

&lt;h1&gt;
  
  
  Known Limits and Concerns
&lt;/h1&gt;

&lt;p&gt;This &lt;a href="https://docs.aws.amazon.com/microservice-extractor/latest/userguide/microservice-extractor-limits.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; article mentions a few limits that you need to know before you start using it.&lt;/p&gt;

&lt;p&gt;When extracting a microservice, you need to decide what to do with the building blocks and "shared" code. Do you publish those to nuget package (i.e. internal feed) and reference them, do you use code duplication by duplicating only what's needed etc. It's your call. The extractor however did not do very well with shared projects for me. I was not sure if I need to include all of these dependencies in the group. I believe there is additional manual work to be done.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;AWS Microservice Extractor for .NET is a fantastic tool. It offers great analysis and visualization capabilities with somehow limited or dissatisfying extraction capabilities (at least for me). &lt;/p&gt;

&lt;p&gt;It still provides a lot of assistance in your migration and can get you started on the right path. Any help is greatly required and appreciated. &lt;/p&gt;

&lt;p&gt;You still need to touch both the old application and the new extracted service, maybe add some missing dependencies.&lt;/p&gt;

&lt;p&gt;Not the glorious ending I was hoping for but nonetheless the start of a compelling journey. The tool was recently released and I expect great things for the future. &lt;/p&gt;

&lt;p&gt;P.S: I will update the article with any new findings and if I manage to get a smooth extraction for the service.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>dotnet</category>
      <category>microservices</category>
      <category>migration</category>
    </item>
    <item>
      <title>Migrating from Microsoft SQL Server to PostgreSQL using Babelfish and Amazon Aurora</title>
      <dc:creator>George Saadeh</dc:creator>
      <pubDate>Tue, 16 Nov 2021 14:23:42 +0000</pubDate>
      <link>https://dev.to/gsaadeh/migrating-from-microsoft-sql-server-to-postgresql-using-babelfish-and-amazon-aurora-1klj</link>
      <guid>https://dev.to/gsaadeh/migrating-from-microsoft-sql-server-to-postgresql-using-babelfish-and-amazon-aurora-1klj</guid>
      <description>&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;An increasing number of organizations are planning to move away from proprietary databases to open source for various reasons such asavoiding expensive costs and licensing terms while leveraging the flexibility and database freedom of modern offerings.&lt;/p&gt;

&lt;p&gt;Migrating from legacy and commercial databases is often a challenging, time-consuming and resource-intensive undertaking. In a legacy / enterprise environment, the database is often used by a variety of desktop and web applications, sometimes using different programming languages. Migrating the database would then require much work on those applications to rewrite the layer that interacts with the database. Many organizations are not willing to make such investment on these legacy applications.&lt;/p&gt;

&lt;p&gt;Babelfish for Aurora PostgreSQL is a new capability that makes it possible to run Microsoft SQL Server applications directly on Amazon Aurora with little to no code changes. &lt;/p&gt;

&lt;p&gt;In this tutorial, we look at how we can perform the migration on the infamous Northwind database and some of the challenges and considerations while migrating much larger and complex databases.&lt;/p&gt;

&lt;p&gt;I used a sample Northwind .NET application &lt;a href="https://github.com/codecypher/Northwind" rel="noopener noreferrer"&gt;available on Github&lt;/a&gt; for testing purposes to illustrate the different kinds of operations that we could run against the database. I also used the &lt;a href="https://github.com/Microsoft/sql-server-samples/tree/master/samples/databases/northwind-pubs" rel="noopener noreferrer"&gt;database script from Microsoft&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Compatibility Assessment
&lt;/h1&gt;

&lt;p&gt;Before starting the migration we need to assess the compatibility of our Microsoft SQL database with Babelfish for PostgreSQL. Such assessment will help us determine the feasibility and complexity of the migration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/babelfish-for-postgresql/babelfish_compass" rel="noopener noreferrer"&gt;Babelfish Compass&lt;/a&gt; is a tool that analyzes the SQL/DDL code for the database and determines which features are/aren't supported so you would know ahead of time how to make the migration successful and what sort of tweaks you might need to do on your existing database.&lt;/p&gt;

&lt;p&gt;To start with the assessment, I need to generate the SQL script for the database, something I can achieve using the SQL Server Management Studio if I don't have it already. Since I downloaded the script, I skipped that.&lt;/p&gt;

&lt;p&gt;I also need to have &lt;a href="https://github.com/babelfish-for-postgresql/babelfish_compass" rel="noopener noreferrer"&gt;Babelfish Compass&lt;/a&gt; installed. &lt;/p&gt;

&lt;p&gt;At this point I ran the assessment command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh ./BabelfishCompass.sh MyReport ~/Documents/Temp/NorthwindCore/src/scripts/instnwnd.sql &lt;span class="nt"&gt;-appname&lt;/span&gt; NorthwindCore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command ran successfully and the result looked promising.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc6icq0gbg0884gws2bq.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc6icq0gbg0884gws2bq.png" alt="Babelfish Compass Result"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The report was generated and I can analyze the results using the HTML page.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxafm3b5kjx61c9cevizg.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxafm3b5kjx61c9cevizg.png" alt="Babelfish Compass Report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luckily for me, there were no issues highlighted in the report... I may have chosen the database on purpose.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr57xdvue0eaqqax4f90.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr57xdvue0eaqqax4f90.png" alt="Babelfish Compass Report Findings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a real world scenario, you would need to make a decision on the migration following the report. You may be required to do further work on your database or tweak certain procedures or functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Limitations and Considerations
&lt;/h1&gt;

&lt;p&gt;Achieving full compatibility with Babelfish for PostgreSQL for large and complex databases is difficult. You can use &lt;a href="https://babelfishpg.org/docs/usage/limitations-of-babelfish/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to learn more about the limitations and the features that are not supported and determine if it's the right tool for your database.&lt;/p&gt;

&lt;p&gt;Another consideration is the version of PostgreSQL. At the time of writing, Babelfish supports only PostgreSQL version 13.4 and newer, which is not yet available for the serverless capacity type.&lt;/p&gt;

&lt;p&gt;As for region availability, Babelfish for Amazon Aurora PostgreSQL is available in all regions supported by Aurora PostgreSQL.&lt;/p&gt;

&lt;p&gt;On the application side, a discovery of the tools and frameworks is essential to assess the feasibility and risks ahead of the migration. Using Entity Framework or similar ORMs may or may not work, based on the setup, dependencies, versions and other factors.&lt;/p&gt;

&lt;h1&gt;
  
  
  Preparations
&lt;/h1&gt;

&lt;p&gt;I created a new Microsoft SQL Server RDS instance to act as the source database.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf9ut5ieyybk7nuoli1h.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvf9ut5ieyybk7nuoli1h.png" alt="MSSQL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I connected to the database using DataGrip (you can also use SSMS) and ran the northwind database script that I downloaded earlier.&lt;/p&gt;

&lt;p&gt;I then created the target Aurora PostgreSQL database cluster with a single writer instance. Note the database version that I used which is the minimum required to support Babelfish. You can also use the filters to show only the supported versions.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvs7lex2eiwvf1zsp913.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsvs7lex2eiwvf1zsp913.png" alt="PostgreSQL setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also turned Babelfish on in the settings.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmvmgnmy7wfdwfcnvuy7.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmvmgnmy7wfdwfcnvuy7.png" alt="PostgreSQL Babelfish"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read more about the different migration modes (single database vs multiple databases) in the &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/babelfish.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I ended up with a source and a target database.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4ekh62lsjkvo7lrjis2.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4ekh62lsjkvo7lrjis2.png" alt="Databases"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Schema Conversion
&lt;/h1&gt;

&lt;p&gt;In a standard database migration project, you can use the &lt;a href="https://docs.aws.amazon.com/SchemaConversionTool/latest/userguide/CHAP_Welcome.html" rel="noopener noreferrer"&gt;AWS Schema Conversion tool (AWS SCT)&lt;/a&gt; to convert your existing database schema from one database engine (i.e. MS SQL Server) to another (i.e. PostgreSQL). &lt;/p&gt;

&lt;p&gt;If you attempt to do so with the babelfish-enabled PostgreSQL database you will get all sorts of errors and permission issues because Babelfish maintains the database objects information in its &lt;em&gt;sys&lt;/em&gt; database.&lt;/p&gt;

&lt;p&gt;For this reason, I connected to the PostgreSQL instance using  &lt;a href="https://docs.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15" rel="noopener noreferrer"&gt;SQL Server Management Studio (SSMS)&lt;/a&gt; to create the &lt;code&gt;northwind&lt;/code&gt; database. Instead of using the default &lt;em&gt;SSMS Object Explorer&lt;/em&gt;, I used the &lt;em&gt;New Query&lt;/em&gt; window to connect. &lt;/p&gt;

&lt;p&gt;I then ran the following script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;DATABASE&lt;/span&gt; &lt;span class="n"&gt;northwind&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, I extracted the schema creation script from the Northwind script file I downloaded and I ran it in the same query window in SSMS.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvelu6i34uq7c6r8k4zf.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvelu6i34uq7c6r8k4zf.png" alt="Database creation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You could run into multiple iterations of code adjustments here.&lt;/p&gt;

&lt;p&gt;Upon completion, I was able to browse the created &lt;code&gt;babelfish_db&lt;/code&gt; in DataGrip by connecting to the PostgreSQL instance using the PostgreSQL driver.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6ph02y1b5qhitl918a0.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6ph02y1b5qhitl918a0.png" alt="babelfish db"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;I could have ran the entire script at this point to add the data, but I wanted to follow the steps of a real-world migration project and opt to use a full load using the &lt;a href="https://aws.amazon.com/dms/" rel="noopener noreferrer"&gt;Database Migration Service&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Database Migration
&lt;/h1&gt;

&lt;p&gt;The schema has been created in the PostgreSQL database and I was ready to start migrating the data.&lt;/p&gt;

&lt;p&gt;Using the AWS Database Migration Service (DMS), I created a new replication instance first.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjntntxlw9yvvdj3ym0s.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjntntxlw9yvvdj3ym0s.png" alt="DMS Replication Instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also created two endpoints representing our source and target databases.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53qslign2woblr8aocg9.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53qslign2woblr8aocg9.png" alt="MSSQL endpoint"&gt;&lt;/a&gt;&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg35fqzwvs1xydeubua4g.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg35fqzwvs1xydeubua4g.png" alt="PostgreSQL endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I created the database migration task and ran a full load of the data into the target PostgreSQL database. For the transformations and mappings, I selected the "convert-lowercase" rule for the tables and columns in the &lt;code&gt;dbo&lt;/code&gt; schema.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkukasyrrd52b4883uzr4.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkukasyrrd52b4883uzr4.png" alt="DMS Load Complete"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The data has been loaded successfully and I was ready to run the app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Testing the App
&lt;/h1&gt;

&lt;p&gt;Before I declared success, I wanted to run the application by pointing to the Microsoft SQL Server database and then switching the connection string to point to the new PostgreSQL instance.&lt;/p&gt;

&lt;p&gt;After a few rounds of minor code changes, mainly because of the Entity framework setup in the sample application, my test was successful!&lt;/p&gt;

&lt;p&gt;I recorded a few steps of the testing I did.&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%2Fgsaadeh-blogs.s3.eu-west-1.amazonaws.com%2Fbabelfish_northwind_640.gif" 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%2Fgsaadeh-blogs.s3.eu-west-1.amazonaws.com%2Fbabelfish_northwind_640.gif" alt="Testing the App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion and Considerations
&lt;/h1&gt;

&lt;p&gt;If you are planning a migration from MS SQL Server to open source then Babelfish is a fantastic tool. It provides the capability for PostgreSQL to understand queries from applications written for Microsoft SQL Server. It can also provide you a quick migration path, with no or minor changes to your application.&lt;/p&gt;

&lt;p&gt;Before using Babelfish and deciding whether it is the right one for you, I encourage you to &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/babelfish.html" rel="noopener noreferrer"&gt;check the documentation&lt;/a&gt; and understand how the capability works and what limitations are relevant to the applications you are trying to migrate.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>database</category>
      <category>migration</category>
      <category>opensource</category>
    </item>
    <item>
      <title>A better way to work with AWS DynamoDB and .NET</title>
      <dc:creator>George Saadeh</dc:creator>
      <pubDate>Tue, 13 Apr 2021 06:31:54 +0000</pubDate>
      <link>https://dev.to/gsaadeh/a-better-way-to-work-with-aws-dynamodb-and-net-3fop</link>
      <guid>https://dev.to/gsaadeh/a-better-way-to-work-with-aws-dynamodb-and-net-3fop</guid>
      <description>&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;One of the challenges that we faced when we started building our platform a few years ago was the .NET tooling around DynamoDB. Most of our developers had been using .NET full-fledged and micro ORMs such as Entity Framework and Dapper with relational databases and expected the same experience with DynamoDB, our key-value and document database of choice.&lt;/p&gt;

&lt;p&gt;Originally, we began using the .NET DynamoDB SDK and it worked well for us. We quickly found ourselves creating extensions and wrappers around the SDK to remove the low level duplicated code, mainly aimed to be more productive, until we stumbled upon a new tool, which was exactly what we have been looking for.  &lt;/p&gt;

&lt;h1&gt;
  
  
  Introducing PocoDynamo
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/ServiceStack/PocoDynamo"&gt;PocoDynamo&lt;/a&gt; is a Typed .NET client which extends ServiceStack's Simple POCO life by enabling re-use of your code-first data models with Amazon's industrial strength and highly-scalable NoSQL DynamoDB. It enhances and improves AWSSDK's low-level client, with rich, native support for intuitively mapping your re-usable code-first POCO Data models into DynamoDB Data Types. Thus improving the overall developer experience and productivity and makes working with DynamoDB, a joy!&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting Started
&lt;/h1&gt;

&lt;p&gt;In this section we will discuss how to get started using PocoDynamo in a real-world application using some of the best practices we learned.&lt;/p&gt;

&lt;p&gt;First we will need to add the NuGet package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; dotnet add package ServiceStack.Aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we'll need to create an instance of AmazonDynamoDBClient with the AWS credentials and Region info:&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IAmazonDynamoDB&lt;/span&gt; &lt;span class="nf"&gt;CreateAmazonDynamoDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;serviceUrl&lt;/span&gt;&lt;span class="p"&gt;)&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;clientConfig&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;AmazonDynamoDBConfig&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;RegionEndpoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RegionEndpoint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EUWest1&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;serviceUrl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;clientConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceURL&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceUrl&lt;/span&gt;&lt;span class="p"&gt;;&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;dynamoClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AmazonDynamoDBClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clientConfig&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;dynamoClient&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;We can now create an instance of PocoDynamo. We can register the instance through dependency injection as the clients are Thread-Safe.&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;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IAmazonDynamoDB&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;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateAmazonDynamoDb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceUrl&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IPocoDynamo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;PocoDynamo&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we will configure PocoDynamo by adding it to our Startup class. The purpose of this configuration is to initialize the schema which we will discuss in the following sections in more details.&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureDynamoDb&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. Now we are ready to add PocoDynamo as a dependency by injecting it in the constructor:&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="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;EmployeeController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IPocoDynamo&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;_db&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&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;h1&gt;
  
  
  Design Approaches
&lt;/h1&gt;

&lt;p&gt;When it comes to designing your data model in DynamoDB, there are two distinct design approaches multi-table or single-table. We are not going to discuss the difference between the two approaches, you can find plenty of articles about that. We will merely show how we can use the library in both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Table
&lt;/h2&gt;

&lt;p&gt;In a multi-table approach, we have one table per each entity and each item maps to a single instance of the entity providing consistency across attributes.&lt;/p&gt;

&lt;p&gt;First we define an entity such as Employee&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HashKey&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;DepartmentId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;departmentId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"D"&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;DepartmentId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;departmentId&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;Next we register the table for the employee type&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;employeeType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// This is how we set the name of the table&lt;/span&gt;
&lt;span class="n"&gt;employeeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AliasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"employee"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a new Employee to the table, it is very simple&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;employee&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Employee&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="n"&gt;departmentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PutItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;employee&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to read the employee from the table&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;employee&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetItem&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a multi-table approach, working with PocoDynamo is very straightforward and doesn't require any additional considerations unlike a single-table approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single-Table
&lt;/h2&gt;

&lt;p&gt;In a single-table approach, one table holds multiple types of entities within it. Each item has different attributes set on it depending on its entity type. While this approach might be less common, it has lots of advantages when querying "related" data such as in a one to many relationship. Let's see an example.&lt;/p&gt;

&lt;p&gt;First we will create two entities. We will define a generic combination of HashKey/RangeKey and we will create a Type attribute to hold the type name.&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Customer&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRecord&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="p"&gt;...&lt;/span&gt;

     &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;CustomerId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"D"&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="n"&gt;HashKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"CUSTOMER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CustomerId&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="n"&gt;RangeKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"CUSTOMER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CustomerId&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="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"CUSTOMER"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Order&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRecord&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;orderTotal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;OrderId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"D"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;OrderTotal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderTotal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;CreatedDate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;HashKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"CUSTOMER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;customerId&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="n"&gt;RangeKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"ORDER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;OrderId&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="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"ORDER"&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;Next we are going to register both entities to map to the &lt;em&gt;same&lt;/em&gt; table.&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;customerType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AliasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customer-orders"&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;orderType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;orderType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AliasAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customer-orders"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RegisterTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RegisterTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderType&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating Customers and Orders would look similar to how we  do it in a single-table approach so I am going to omit it. What we will focus on how we can query data.&lt;/p&gt;

&lt;p&gt;The first example we will look at is how to query a single customer by customer id. Notice the use of the same Hash key and Range key to indicate that we are querying a customer here and not customer and orders.&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;customer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_db&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromQuery&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;KeyCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"HashKey = :customerId  and RangeKey = :orderId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;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;"customerId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"CUSTOMER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"orderId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"CUSTOMER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&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="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;SingleOrDefault&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second example we will look at is how to query the orders of a customer (in a case of one-to-many relationship). Notice the use of &lt;code&gt;begins_with&lt;/code&gt; in the expression as we would like to query only orders and not to include the customer data since it will break the mapping.&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;orders&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_db&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FromQuery&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;KeyCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"HashKey = :customerId  and begins_with(RangeKey, :order)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;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;"customerId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"CUSTOMER#&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;id&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"order"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"ORDER"&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="nf"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a single table approach, you will need to use the right combination of Hash / Range key to get exactly the data that you need.&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerations
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;PocoDynamo has a &lt;em&gt;10&lt;/em&gt; Tables free-quota usage limit which can be unlocked with a commercial license key.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;In this article we've looked at ServiceStack's PocoDynamo and how it can help us be more productive when working with DynamoDB. If you are okay with buying a commercial license, it is well worth it. If you know of any similar tools, free or open-source, I'd be glad to hear about it. &lt;/p&gt;

&lt;p&gt;You can find the source code on &lt;a href="https://github.com/gsaadeh/pocodynamo-demo"&gt;Github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>dotnet</category>
      <category>nosql</category>
      <category>dynamodb</category>
    </item>
  </channel>
</rss>
