<?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>Forem: Brandon Minnick</title>
    <description>The latest articles on Forem by Brandon Minnick (@brminnick).</description>
    <link>https://forem.com/brminnick</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%2F276946%2F50a8f12e-7fcb-4d88-9bfc-093df0668604.png</url>
      <title>Forem: Brandon Minnick</title>
      <link>https://forem.com/brminnick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/brminnick"/>
    <language>en</language>
    <item>
      <title>Android Image Classification with TensorFlow Lite &amp; Azure Custom Vision Service</title>
      <dc:creator>Brandon Minnick</dc:creator>
      <pubDate>Thu, 09 Apr 2020 20:59:09 +0000</pubDate>
      <link>https://forem.com/azure/android-image-classification-with-tensorflow-lite-azure-custom-vision-service-2na</link>
      <guid>https://forem.com/azure/android-image-classification-with-tensorflow-lite-azure-custom-vision-service-2na</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a guest blog by &lt;a href="https://twitter.com/hindrikes" rel="noopener noreferrer"&gt;Daniel Hindrikes&lt;/a&gt;. Daniel is a Microsoft MVP, Speaker, and Xamarin + Cloud Solution Architect at &lt;a href="https://tretton37.com/" rel="noopener noreferrer"&gt;tretton37&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Image Classification allows our Xamarin apps to recognize objects in a photo.&lt;/p&gt;

&lt;p&gt;Being able to take a photo and recognize its contents is becoming more and more common. We experience it in our banking apps when making a mobile deposit, in our photo apps when adding filters, and in our HotDog apps to determine whether or not our meal is a hotdog.&lt;/p&gt;

&lt;p&gt;Thanks to Azure Custom Vision Service, we don't have to learn complex machine learning algorithms to implement image classification.&lt;/p&gt;

&lt;p&gt;This article will walkthrough how to implement it using Azure's &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service&lt;/a&gt;, &lt;a href="https://www.tensorflow.org/lite" rel="noopener noreferrer"&gt;TensorFlow Lite&lt;/a&gt; (an open source machine learning platform) and &lt;a href="https://docs.microsoft.com/xamarin/android?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Xamarin.Android&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: For Xamarin.iOS, we can also use Azure's Custom Vision Service with CoreML, but we'll save that for another blog post.&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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2Fmushrooms.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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2Fmushrooms.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Image Classification Libraries
&lt;/h2&gt;

&lt;p&gt;We'll be leveraging Azure &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service&lt;/a&gt; and &lt;a href="https://www.tensorflow.org/lite" rel="noopener noreferrer"&gt;TensorFlow Lite&lt;/a&gt; to implement our image classification.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Azure Custom Vision Service
&lt;/h3&gt;

&lt;p&gt;Azure's &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service&lt;/a&gt; makes it easy to create and train machine learning models - no previous Artificial Intelligence (AI) or Machine Learning (ML) experience is necessary.&lt;/p&gt;

&lt;p&gt;Using the &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service Web Portal&lt;/a&gt;, we can do the following without writing any AI/ML code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload a training image&lt;/li&gt;
&lt;li&gt;Tag / Label the object(s) in the image&lt;/li&gt;
&lt;li&gt;Repeat (the model gets better with more training data)&lt;/li&gt;
&lt;li&gt;That's it - Custom Vision Service takes care of the rest!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. TensorFlow Lite
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.tensorflow.org/lite" rel="noopener noreferrer"&gt;TensorFlow Lite&lt;/a&gt; is an open source machine learning platform that allows us to use &lt;a href="https://www.tensorflow.org/" rel="noopener noreferrer"&gt;TensorFlow&lt;/a&gt; on IoT and Mobile devices.&lt;/p&gt;

&lt;p&gt;Both TensoryFlow Lite and TensorFlow are completely &lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;open-source on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing Image Classification with Azure + Xamarin.Android
&lt;/h2&gt;

&lt;p&gt;The completed Image Classification sample app is available here on GitHub: &lt;a href="https://github.com/dhindrik/MushroomDetector/" rel="noopener noreferrer"&gt;https://github.com/dhindrik/MushroomDetector/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Training the Model
&lt;/h3&gt;

&lt;p&gt;Using the &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service Web Portal&lt;/a&gt;, we will first train models for image classification.&lt;/p&gt;

&lt;p&gt;1) In the &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service Web Portal&lt;/a&gt;, click &lt;strong&gt;New Project&lt;/strong&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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FNew-Project-300x300.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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FNew-Project-300x300.png" alt="New Project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) In the &lt;strong&gt;Create new project window&lt;/strong&gt;, make the following selections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: XamarinImageClassification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description&lt;/strong&gt;: Identify Objects in Images&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource&lt;/strong&gt;: [Create a new resource]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Type&lt;/strong&gt;: Classification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classification Types&lt;/strong&gt;: Multilabel (Multiple tags per image)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domains&lt;/strong&gt;: General (compact)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export Capabilities&lt;/strong&gt;: Basic platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3) In the &lt;strong&gt;Create new project window&lt;/strong&gt;, click &lt;strong&gt;Create project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;4) In the &lt;strong&gt;XamarinImageClassification&lt;/strong&gt; window, click &lt;strong&gt;Add images&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;5) Select images that contain the object to identify&lt;/p&gt;

&lt;p&gt;6) In the &lt;strong&gt;Image Upload&lt;/strong&gt; window, add a tag&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In this example, we are tagging images of mushrooms&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;7) In the Image upload window, click Upload&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Continue uploading images until you have at least 5 images for each tag&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;8) In the &lt;strong&gt;XamarinImageClassification&lt;/strong&gt; window, in the top-right of the window, click the &lt;strong&gt;Train Model&lt;/strong&gt; button (the green image of gears)&lt;/p&gt;

&lt;p&gt;9) In the &lt;strong&gt;Choose Training Type&lt;/strong&gt; window, select &lt;strong&gt;Quick Training&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;10) In the &lt;strong&gt;Choose Training Type&lt;/strong&gt; window, select &lt;strong&gt;Train&lt;/strong&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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FTrain-300x207.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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FTrain-300x207.png" alt="Choose Training Type"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Export Trained Models from Azure Custom Vision Service
&lt;/h3&gt;

&lt;p&gt;Now that we've trained our model, let's &lt;a href="https://docs.microsoft.com/azure/cognitive-services/custom-vision-service/export-your-model?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;export it for use in our mobile app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This allows us to use the model without an internet connection which improves the user's privacy because their photos will never leave their mobile device.&lt;/p&gt;

&lt;p&gt;To export our model, lets do the following:&lt;/p&gt;

&lt;p&gt;1) On the &lt;strong&gt;XamarinImageClassifcation&lt;/strong&gt; window, on the top of the page, select the &lt;strong&gt;Performance&lt;/strong&gt; tab&lt;/p&gt;

&lt;p&gt;2) On The &lt;strong&gt;Performance&lt;/strong&gt; tab, tap the &lt;strong&gt;Export&lt;/strong&gt; button (the downward-pointing arrow)&lt;/p&gt;

&lt;p&gt;3) On the &lt;strong&gt;Choose your platform&lt;/strong&gt; window, select &lt;strong&gt;TensorFlow&lt;/strong&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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FExport-to-TensorFlow-300x288.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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FExport-to-TensorFlow-300x288.png" alt="Choose Your Platform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4) In the &lt;strong&gt;Choose your platform&lt;/strong&gt; dropdown, select &lt;strong&gt;TensorFlow Lite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;5) In the &lt;strong&gt;Choose your platform&lt;/strong&gt; window, select &lt;strong&gt;Download&lt;/strong&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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FChoose-Your-Platform-300x149.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%2Fdevblogs.microsoft.com%2Fxamarin%2Fwp-content%2Fuploads%2Fsites%2F44%2F2020%2F03%2FChoose-Your-Platform-300x149.png" alt="Choose your platform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Import TensorFlowLite into our Xamarin.Android App
&lt;/h3&gt;

&lt;p&gt;1) In our Xamarin.Android project, install the &lt;a href="https://www.nuget.org/packages/Xamarin.TensorFlow.Lite" rel="noopener noreferrer"&gt;TensorFlow Lite NuGet Package&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This NuGet Package is an &lt;a href="https://github.com/xamarin/XamarinComponents/tree/master/XPlat/TensorFlow.Lite" rel="noopener noreferrer"&gt;open-source project&lt;/a&gt; created by the Xamarin team at Microsoft. It contains C# bindings for the &lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;orginal TensorFlow Lite library&lt;/a&gt; which makes it possible to use in our Xamarin.Android app&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%2Fuser-images.githubusercontent.com%2F13558917%2F76364288-b24f5880-631c-11ea-9d0a-d817efab4233.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%2Fuser-images.githubusercontent.com%2F13558917%2F76364288-b24f5880-631c-11ea-9d0a-d817efab4233.png" alt="Xamarin.TensorFlow.Lite NuGet Package"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2) Unzip the exported model that we downloaded from the &lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Custom Vision Service Web Portal&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Inside the zip-file, are &lt;code&gt;labels.txt&lt;/code&gt; and &lt;code&gt;model.tflite&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;labels.txt&lt;/code&gt;  contains the image tags created during the training preparation at the Custom Vision website&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;models.tflite&lt;/code&gt;  is the machine learning model that we use to make our predictions&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;3) In Visual Studio, in the Xamarin.Android project, right-click on the &lt;strong&gt;Assets&lt;/strong&gt; folder&lt;/p&gt;

&lt;p&gt;4) On the right-click menu, select &lt;strong&gt;Add&lt;/strong&gt; &amp;gt; &lt;strong&gt;Existing Item...&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;5) In the &lt;strong&gt;Add Existing Item&lt;/strong&gt; menu, select both of the recently unzipped files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;models.tflite&lt;/li&gt;
&lt;li&gt;labels.txt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;6) In Visual Studio, in the &lt;strong&gt;Xamarin.Android&lt;/strong&gt; &amp;gt; &lt;strong&gt;Assets&lt;/strong&gt; folder, right-click on &lt;strong&gt;labels.txt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;7) In the right-click menu, select &lt;strong&gt;Properties&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;8) In the &lt;strong&gt;Properties&lt;/strong&gt; window, select &lt;strong&gt;Build Action&lt;/strong&gt; &amp;gt; &lt;strong&gt;Android Asset&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;9) In Visual Studio, in the &lt;strong&gt;Xamarin.Android&lt;/strong&gt; &amp;gt; &lt;strong&gt;Assets&lt;/strong&gt; folder, right-click on &lt;strong&gt;models.tflite&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;10) In the right-click menu, select &lt;strong&gt;Properties&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;11) In the &lt;strong&gt;Properties&lt;/strong&gt; window, select &lt;strong&gt;Build Action&lt;/strong&gt; &amp;gt; &lt;strong&gt;Android Asset&lt;/strong&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%2Fuser-images.githubusercontent.com%2F13558917%2F76364295-b4b1b280-631c-11ea-845f-fe0ff2e0a415.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%2Fuser-images.githubusercontent.com%2F13558917%2F76364295-b4b1b280-631c-11ea-845f-fe0ff2e0a415.png" alt="AndroidAsset"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Implement Image Classification Code for Xamarin.Android
&lt;/h3&gt;

&lt;p&gt;Now that we've imported the model, it is time to write code.&lt;/p&gt;

&lt;p&gt;The completed Image Classification sample app is available here on GitHub: &lt;a href="https://github.com/dhindrik/MushroomDetector/" rel="noopener noreferrer"&gt;https://github.com/dhindrik/MushroomDetector/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Xamarin.Android project, add both &lt;code&gt;ImageClassifcationModel.cs&lt;/code&gt;  and &lt;code&gt;TensorflowClassifier.cs:&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ImageClassificationModel.cs
&lt;/h3&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;ImageClassificationModel&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;ImageClassificationModel&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;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="n"&gt;TagName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="n"&gt;Probability&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;probability&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;float&lt;/span&gt; &lt;span class="n"&gt;Probability&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="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;TagName&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="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  TensorflowClassifier.cs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Collections.Generic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Linq&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Android.App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Android.Graphics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Java.IO&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Java.Nio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Java.Nio.Channels&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TensorflowClassifier&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//FloatSize is a constant with the value of 4 because a float value is 4 bytes&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;FloatSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;//PixelSize is a constant with the value of 3 because a pixel has three color channels: Red Green and Blue&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;PixelSize&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="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ImageClassificationModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;image&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;mappedByteBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetModelAsMappedByteBuffer&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;interpreter&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;Xamarin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TensorFlow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Interpreter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mappedByteBuffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;//To resize the image, we first need to get its required width and height&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;tensor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;interpreter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetInputTensor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&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;shape&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tensor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shape&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;width&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shape&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shape&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;byteBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GetPhotoAsByteBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;//use StreamReader to import the labels from labels.txt&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;streamReader&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;StreamReader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"labels.txt"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="c1"&gt;//Transform labels.txt into List&amp;lt;string&amp;gt;&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;streamReader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadToEnd&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\n'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&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;s&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;span class="c1"&gt;//Convert our two-dimensional array into a Java.Lang.Object, the required input for Xamarin.TensorFlow.List.Interpreter&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;outputLocations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;float&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="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&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;outputs&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Java&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Lang&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputLocations&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;interpreter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;byteBuffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outputs&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;classificationResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;float&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;]&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;//Map the classificationResult to the labels and sort the result to find which label has the highest probability&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;classificationModelList&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;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ImageClassificationModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&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;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&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;label&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;classificationModelList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&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;ImageClassificationModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;classificationResult&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]));&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;classificationModelList&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;//Convert model.tflite to Java.Nio.MappedByteBuffer , the require type for Xamarin.TensorFlow.Lite.Interpreter&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;MappedByteBuffer&lt;/span&gt; &lt;span class="nf"&gt;GetModelAsMappedByteBuffer&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;assetDescriptor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenFd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"model.tflite"&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;inputStream&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;FileInputStream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assetDescriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileDescriptor&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;mappedByteBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inputStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FileChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MapMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadOnly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assetDescriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assetDescriptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeclaredLength&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;mappedByteBuffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;//Resize the image for the TensorFlow interpreter&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;ByteBuffer&lt;/span&gt; &lt;span class="nf"&gt;GetPhotoAsByteBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;height&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;bitmap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BitmapFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DecodeByteArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&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;resizedBitmap&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateScaledBitmap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;height&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;modelInputSize&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;FloatSize&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;PixelSize&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;byteBuffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ByteBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AllocateDirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;modelInputSize&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;byteBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ByteOrder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NativeOrder&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;pixels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="n"&gt;resizedBitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetPixels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resizedBitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resizedBitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resizedBitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Height&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;pixel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;//Loop through each pixels to create a Java.Nio.ByteBuffer&lt;/span&gt;
        &lt;span class="k"&gt;for&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;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&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;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&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;pixelVal&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pixels&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;pixel&lt;/span&gt;&lt;span class="p"&gt;++];&lt;/span&gt;

                &lt;span class="n"&gt;byteBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PutFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixelVal&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="m"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;byteBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PutFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixelVal&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="m"&gt;0xFF&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;byteBuffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PutFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixelVal&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&lt;/span&gt; &lt;span class="m"&gt;0xFF&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="n"&gt;bitmap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Recycle&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;byteBuffer&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;That's it! Now we can pass an image into &lt;code&gt;TensorflowClassifier.Classify&lt;/code&gt; to retrieve our &lt;code&gt;ImageClassificationModel&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;p&gt;Check out the links below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dhindrik/MushroomDetector/blob/master/MushroomDetector.Android/TensorflowClassifier.cs" rel="noopener noreferrer"&gt;Completed Code on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://customvision.ai/?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Azure Custom Vision Service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/azure/cognitive-services?WT.mc_id=aiapril-devto-bramin" rel="noopener noreferrer"&gt;Azure Cognitive Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=pRDL5BtV_Fg&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;The Community AI Show: Custom Vision, Xamarin and Simpsons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/microsoftazure/ai-april-content-dashboar-8e8cd6e8aa98" rel="noopener noreferrer"&gt;Microsoft's AI April&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=yDqvOsMRceo&amp;amp;feature=youtu.be" rel="noopener noreferrer"&gt;App In The Cloud - Build an app powered by Custom Vision in Azure Cognitive Services&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>xamarin</category>
      <category>azure</category>
      <category>aiapril</category>
      <category>android</category>
    </item>
    <item>
      <title>Introducing GitTrends: GitHub Insights</title>
      <dc:creator>Brandon Minnick</dc:creator>
      <pubDate>Mon, 02 Mar 2020 21:12:28 +0000</pubDate>
      <link>https://forem.com/brminnick/introducing-gittrends-github-insights-1o29</link>
      <guid>https://forem.com/brminnick/introducing-gittrends-github-insights-1o29</guid>
      <description>&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;iOS&lt;/th&gt;
&lt;th&gt;Android&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://apps.apple.com/us/app/gittrends-github-insights/id1500300399"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tah5E5co--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/13558917/75712535-ed96bb00-5c7c-11ea-8bd4-e9bd36365bb2.png" alt=""&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://play.google.com/store/apps/details?id=com.minnick.gittrends"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WPHT8abD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/13558917/75712286-8d077e00-5c7c-11ea-86f0-cd693630eee0.png" alt=""&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I am so excited to release GitTrends on Product Hunt today! &lt;a href="https://www.producthunt.com/posts/gittrends-github-insights"&gt;https://www.producthunt.com/posts/gittrends-github-insights&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitTrends helps you to monitor your GitHub Repositories:&lt;br&gt;
✅ Connect to GitHub&lt;br&gt;
✅ Monitor GitHub Repo Views&lt;br&gt;
✅ Monitor GitHub Repo Clones&lt;br&gt;
✅ Discover Referring Sites&lt;/p&gt;

&lt;p&gt;I created GitTrends because I love contributing to open source libraries, but I had trouble keeping track of which repos were receiving traffic and which ones were not. For example, I recently discovered that a repo I hadn't updated in +2 years was still getting 10-20 views per week.  &lt;/p&gt;

&lt;p&gt;All of the code is totally open source on GitHub and I absolutely welcome new feature requests and PRs!&lt;/p&gt;

&lt;p&gt;📝 &lt;a href="https://www.producthunt.com/posts/gittrends-github-insights"&gt;Leave us a comment on Product Hunt&lt;/a&gt;&lt;br&gt;
⭐️ &lt;a href="https://github.com/brminnick/GitTrends/"&gt;Open a Feature Request on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;GitHub Login&lt;/th&gt;
&lt;th&gt;Repo Traffic&lt;/th&gt;
&lt;th&gt;Referring Sites&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d5kALsay--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/13558917/75208427-77500100-5730-11ea-9654-7255ed051536.gif" alt="View Repositories"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--guVXIud4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/13558917/75208368-5091ca80-5730-11ea-8602-8c63244bf229.gif" alt="View Repo"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fXV8hVda--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/13558917/75208328-30faa200-5730-11ea-92c7-d316f6cb39e6.gif" alt="Referring Site"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gwXqX8O5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/13558917/74350902-43a5cc00-4d6b-11ea-8c9f-c1bafbfcb415.gif" alt="View Repositories"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BH_sNcRo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/13558917/74351618-363d1180-4d6c-11ea-8244-dc2e1c6cdfe4.gif" alt="View Repo"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0L6u9GEw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://user-images.githubusercontent.com/13558917/74351991-b9f6fe00-4d6c-11ea-9eb5-57260493256b.gif" alt="Referring Site"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mobile App
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/xamarin/?WT.mc_id=gittrends-devto-bramin"&gt;Xamarin&lt;/a&gt; - build native apps for Android, iOS, and macOS using .NET code and platform-specific user interfaces&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/xamarin/essentials/?WT.mc_id=gittrends-devto-bramin"&gt;Xamarin.Essentials&lt;/a&gt; - provides cross-platform APIs for their mobile applications&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/xamarin/get-started/what-is-xamarin-forms?WT.mc_id=gittrends-devto-bramin"&gt;Xamarin.Forms&lt;/a&gt; - an open-source UI framework to build Android, iOS, and Windows applications from a single shared codebase&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/appcenter/?WT.mc_id=gittrends-devto-bramin"&gt;AppCenter&lt;/a&gt; - continuously build, test, release, and monitor mobile apps&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/brminnick/AsyncAwaitBestPractices"&gt;AsyncAwaitBestPractices&lt;/a&gt; - Extensions for System.Threading.Tasks.Task&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/autofac/Autofac"&gt;Autofac&lt;/a&gt; - an IoC container for .NET&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sthewissen/Xamarin.Forms.DebugRainbows"&gt;Debug Rainbows&lt;/a&gt; - Xamarin.Forms UI layout tool&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/zzzprojects/html-agility-pack"&gt;HTML Agility Pack&lt;/a&gt; - an agile HTML parser that builds a read/write DOM and supports plain XPATH or XSLT&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/App-vNext/Polly"&gt;Polly&lt;/a&gt; - .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/reactiveui/refit"&gt;Refit&lt;/a&gt; - Refit is a REST library for .NET that converts REST APIs into live interfaces&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/praeclarum/sqlite-net"&gt;Sqlite-net&lt;/a&gt; - an open source, minimal library to allow .NET, .NET Core, and Mono applications to store data in SQLite 3 databases&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://syncfusion.com"&gt;Syncfusion&lt;/a&gt; - a UI Component Suite for Building Powerful Web, Desktop, and Mobile Apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloud Backend
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/dotnet/core/?WT.mc_id=gittrends-devto-bramin"&gt;.NET Core&lt;/a&gt; - an &lt;a href="https://github.com/dotnet/core"&gt;open-source&lt;/a&gt;, general-purpose development platform maintained by Microsoft and the .NET community on &lt;a href="https://github.com/dotnet/core"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=gittrends-devto-bramin"&gt;Azure Functions&lt;/a&gt; - a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection?WT.mc_id=gittrends-devto-bramin"&gt;Azure Functions Dependency Injection&lt;/a&gt; - Azure Functions supports the dependency injection (DI) software design pattern, which is a technique to achieve &lt;a href="https://docs.microsoft.com/dotnet/standard/modern-web-apps-azure-architecture/architectural-principles?WT.mc_id=gittrends-devto-bramin#dependency-inversion"&gt;Inversion of Control (IoC)&lt;/a&gt; between classes and their dependencies&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/dotnet/architecture/microservices/implement-resilient-applications/implement-http-call-retries-exponential-backoff-polly?WT.mc_id=gittrends-devto-bramin"&gt;Polly + HttpClientFactory&lt;/a&gt; - the recommended approach for retries with exponential backoff is to take advantage of more advanced .NET libraries&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?WT.mc_id=gittrends-devto-bramin#generated-clients"&gt;Refit + HttpClientFactory&lt;/a&gt; - &lt;code&gt;IHttpClientFactory&lt;/code&gt; can be used in combination with third-party libraries such as Refit&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>ios</category>
      <category>android</category>
    </item>
    <item>
      <title>Xamarin: Efficiently Using a SQLite Database</title>
      <dc:creator>Brandon Minnick</dc:creator>
      <pubDate>Thu, 20 Feb 2020 22:06:46 +0000</pubDate>
      <link>https://forem.com/brminnick/xamarin-efficiently-using-a-sqlite-database-4eep</link>
      <guid>https://forem.com/brminnick/xamarin-efficiently-using-a-sqlite-database-4eep</guid>
      <description>&lt;p&gt;The most popular SQLite ORM for Xamarin is &lt;a href="https://github.com/praeclarum/sqlite-net"&gt;SQLite-net&lt;/a&gt;. Let's explore the most efficient way to use it in our apps!&lt;/p&gt;

&lt;p&gt;If you'd like to skip to the completed code, jump to Section 9: &lt;em&gt;Put It All Together&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A completed sample app using this implementation is also available here: &lt;a href="https://github.com/brminnick/GitTrends"&gt;https://github.com/brminnick/GitTrends&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Locate the App Data Directory
&lt;/h2&gt;

&lt;p&gt;Both iOS and Android have a specific/unique file directory for each app, and this is where we'll store the &lt;code&gt;.db3&lt;/code&gt; database file. We can easily locate it using &lt;code&gt;Xamarin.Essentials.FileSystem&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Be sure to first add the &lt;a href="https://www.nuget.org/packages/Xamarin.Essentials"&gt;Xamarin.Essentials NuGet Package&lt;/a&gt; and follow its &lt;a href="https://docs.microsoft.com/xamarin/essentials/get-started?WT.mc_id=sqlite-devto-bramin"&gt;Getting Started Instructions&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_databasePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Xamarin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Essentials&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppDataDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SqliteDatabase.db3"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Use SQLiteOpenFlags
&lt;/h2&gt;

&lt;p&gt;SQLite-net offers an &lt;a href="https://github.com/praeclarum/sqlite-net/wiki/Asynchronous-API"&gt;asynchronous API&lt;/a&gt;, &lt;code&gt;SQLiteAsyncConnection&lt;/code&gt;. This allows us to use async/await when performing database operations.&lt;/p&gt;

&lt;p&gt;SQLite also offers a &lt;a href="https://www.sqlite.org/c3ref/open.html"&gt;few different options&lt;/a&gt; when creating a database connection using &lt;code&gt;SQLiteOpenFlags&lt;/code&gt;, and here are the ones I recommend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.sqlite.org/c3ref/open.html"&gt;&lt;code&gt;SQLiteOpenFlags.ReadWrite&lt;/code&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"The database is opened for reading and writing if possible, or reading only if the file is write protected by the operating system"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sqlite.org/c3ref/open.html"&gt;&lt;code&gt;SQLiteOpenFlags.Create&lt;/code&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;"[The database] is created if it does not already exist"&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.sqlite.org/sharedcache.html"&gt;&lt;code&gt;SQLiteOpenFlags.SharedCache&lt;/code&gt;&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Allows for multi-threaded database access&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;"When a thread establishes multiple connections to the same database, the connections share a single data and schema cache. This can significantly reduce the quantity of memory and IO required by the system"&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_databasePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadWrite&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedCache&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Use Lazy Initialization
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.microsoft.com/dotnet/framework/performance/lazy-initialization?WT.mc_id=sqlite-devto-bramin"&gt;official Microsoft Docs&lt;/a&gt; say it best: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lazy initialization of an object means that its creation is deferred until it is first used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because File IO operations and creating a database can be expensive (i.e., it requires many CPU cycles and can take longer than expected), we don't want to initialize our database until we need it. This avoids creating our database when the app launches, keeping our app's launch time to a minimum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Lazy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_databaseConnectionHolder&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;Lazy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_databasePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadWrite&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedCache&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt; &lt;span class="n"&gt;DatabaseConnection&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_databaseConnectionHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Retrieve the Database Connection
&lt;/h2&gt;

&lt;p&gt;To use the database connection, we must ensure the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure Database has been created

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new SQLiteAsyncConnection&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ensure Tables have been created &amp;amp; mapped

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CreateTables(CreateFlags createFlags, params Type[] types)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To accomplish both, I created &lt;code&gt;async Task&amp;lt;SQLiteAsyncConnection&amp;gt; GetDatabaseConnection&amp;lt;T&amp;gt;()&lt;/code&gt; where &lt;code&gt;T&lt;/code&gt; is the Model's type. This method ensures the database table has been created &amp;amp; mapped before returning the database connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&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="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableMappings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&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;MappedType&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;T&lt;/span&gt;&lt;span class="p"&gt;)))&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;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateTablesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;T&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&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;DatabaseConnection&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;h2&gt;
  
  
  5. Use Write-Ahead Logging
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://github.com/praeclarum/sqlite-net/blob/91c17adc183487dd3e7a41e90430c286a7add7db/src/SQLiteAsync.cs#L128"&gt;SQLite-net v1.6.0+&lt;/a&gt;, Write Ahead Logging (WAL), is available which brings &lt;a href="https://www.sqlite.org/wal.html"&gt;many performance advantages&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;WAL is significantly faster in most scenarios&lt;/li&gt;
&lt;li&gt;WAL provides more concurrency as readers do not block writers and a writer does not block readers. Reading and writing can proceed concurrently.&lt;/li&gt;
&lt;li&gt;Disk I/O operations tends to be more sequential using WAL.&lt;/li&gt;
&lt;li&gt;WAL uses many fewer fsync() operations and is thus less vulnerable to problems on systems where the fsync() system call is broken.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are also &lt;a href="https://www.sqlite.org/wal.html"&gt;disadvantages to using WAL&lt;/a&gt;, most of which however don't impact Xamarin mobile apps. But be sure to understand both the advantages and disadvantages before enabling WAL in your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&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="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableMappings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&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;MappedType&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;T&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// On sqlite-net v1.6.0+, enabling write-ahead logging allows for faster database execution&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableWriteAheadLoggingAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&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;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateTablesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;T&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&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;DatabaseConnection&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;h2&gt;
  
  
  6. Always Attempt and Retry
&lt;/h2&gt;

&lt;p&gt;When using multi-threading and async/await to interact with a SQLite database, sometimes this exception is thrown:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;SQLite.SQLiteException: database is locked&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Anecdotally, I've noticed this exception gets thrown more often in SQLite-net v1.6.0+ when WAL is enabled.&lt;/p&gt;

&lt;p&gt;When this exception happens, we just need to retry our SQL query again after the database has been unlocked.&lt;/p&gt;

&lt;p&gt;There is an amazing library called &lt;a href="https://www.nuget.org/packages/Polly/"&gt;Polly&lt;/a&gt; that will catch an exception, wait a specified period of time, then try to execute the function again.&lt;/p&gt;

&lt;p&gt;For this, I created &lt;code&gt;AttemptAndRetry&amp;lt;T&amp;gt;&lt;/code&gt; which will execute a &lt;code&gt;Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt;&lt;/code&gt;, but if it throws a &lt;code&gt;SQLite.SQLiteException&lt;/code&gt; it will attempt to execute it again asynchronously. &lt;/p&gt;

&lt;p&gt;Between retries, I recommend using an &lt;a href="https://wikipedia.org/wiki/Exponential_backoff"&gt;Exponential Backoff&lt;/a&gt; to ensure there are 2&lt;sup&gt;n&lt;/sup&gt; milliseconds in between. This means that if the first attempt fails, the first retry will happen 2&lt;sup&gt;1&lt;/sup&gt; (2) milliseconds later (1 millisecond is a &lt;em&gt;really&lt;/em&gt; long time for a CPU). If the second attempt fails, its subsequent retry will happen 2&lt;sup&gt;2&lt;/sup&gt; (4) milliseconds later. And if third attempt fails, its subsequent retry will happen 2&lt;sup&gt;3&lt;/sup&gt; (8) milliseconds later, etc.&lt;/p&gt;

&lt;p&gt;In this example, we will retry 10 times, meaning the final attempt will occur 2 seconds after its previous try, and all 11 attempts (1 attempt + 10 retries) will occur over a total timespan of 4.094 seconds. In other words, if each attempt fails, including the final attempt, the database will throw a &lt;code&gt;SQLite.SQLiteException&lt;/code&gt; after approximately 4 seconds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AttemptAndRetry&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numRetries&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="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQLiteException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numRetries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pollyRetryAttempt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="nf"&gt;pollyRetryAttempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;attemptNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMilliseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Pow&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="n"&gt;attemptNumber&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;h2&gt;
  
  
  7. Use &lt;code&gt;ConfigureAwait(false)&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You may notice that every time I use the &lt;code&gt;await&lt;/code&gt; keyword, I also use &lt;code&gt;.ConfigureAwait(false)&lt;/code&gt;. This is done to increase performance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ConfigureAwait(false)&lt;/code&gt; ensures that the background thread doesn't return to the calling thread (which can be the Main Thread, aka the UI Thread). For Xamarin apps, we want to avoid using the Main Thread for database operations to ensure our app doesn't freeze and remains responsive.&lt;/p&gt;

&lt;p&gt;I highly recommend watching this session I delivered at NDC Oslo to learn more: &lt;a href="https://www.youtube.com/watch?v=J0mcYVxJEl0"&gt;"Correcting Common Async Await Mistakes in .NET"&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=J0mcYVxJEl0"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hv5nIBE7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/13558917/62509892-a32a8a00-b7d2-11e9-9460-267220838b76.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Use ValueTask
&lt;/h2&gt;

&lt;p&gt;New in .NET Standard 2.1 is &lt;a href="https://docs.microsoft.com/dotnet/api/system.threading.tasks.valuetask-1?view=netcore-3.0WT.mc_id=sqlite-devto-bramin"&gt;&lt;code&gt;System.Threading.Tasks.ValueTask&lt;/code&gt;&lt;/a&gt;. &lt;br&gt;
(If you can't yet upgrade to .NET Standard 2.1, you can still use &lt;code&gt;ValueTask&lt;/code&gt; by installing the &lt;a href="https://www.nuget.org/packages/System.Threading.Tasks.Extensions/"&gt;&lt;code&gt;System.Threading.Tasks.Extensions&lt;/code&gt; NuGet Package&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;If you're new to &lt;code&gt;ValueTask&lt;/code&gt;, check out this great write-up: &lt;a href="https://blogs.msdn.microsoft.com/dotnet/2018/11/07/understanding-the-whys-whats-and-whens-of-valuetask?WT.mc_id=sqlite-devto-bramin"&gt;Understanding the Whys, Whats, and Whens of ValueTask&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tl;dr&lt;/strong&gt; &lt;code&gt;VaueTask&lt;/code&gt; can be used to improve async/await performance when the hot-path of a method doesn't require the &lt;code&gt;await&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GetDatabaseConnection&lt;/code&gt; only uses the &lt;code&gt;await&lt;/code&gt; keyword the first time it is called. Thus its hot-path does not use require &lt;code&gt;await&lt;/code&gt;, making it the perfect use-case for &lt;code&gt;ValueTask&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To implement &lt;code&gt;ValueTask&lt;/code&gt; for &lt;code&gt;GetDatabaseConnection&amp;lt;T&amp;gt;&lt;/code&gt;, just replace &lt;code&gt;Task&amp;lt;SQLiteAsyncConnection&amp;gt;&lt;/code&gt; with &lt;code&gt;ValueTask&amp;lt;SQLiteAsyncConnection&amp;gt;&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;ValueTask&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&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="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableMappings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&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;MappedType&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;T&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// On sqlite-net v1.6.0+, enabling write-ahead logging allows for faster database execution&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableWriteAheadLoggingAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&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;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateTablesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;T&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&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;DatabaseConnection&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;h2&gt;
  
  
  9. Put It All Together
&lt;/h2&gt;

&lt;p&gt;Putting all of these best practices together, I've created &lt;code&gt;abstract class BaseDatabase&lt;/code&gt;. I copy/paste this abstract class into all of my Xamarin applications where I use a database. &lt;/p&gt;

&lt;p&gt;A completed sample app using this implementation is available here: &lt;a href="https://github.com/brminnick/GitTrends"&gt;https://github.com/brminnick/GitTrends&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  BaseDatabase.cs
&lt;/h3&gt;

&lt;p&gt;Be sure to first add the following NuGet Packages to your app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.nuget.org/packages/sqlite-net-pcl/"&gt;SQLite-Net&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nuget.org/packages/Xamarin.Essentials"&gt;Xamarin.Essentials&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Used to locate the app's data Directory&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/xamarin/essentials/get-started?WT.mc_id=none-stackoverflow-bramin"&gt;Getting Started Instructions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nuget.org/packages/Polly/"&gt;Polly&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;Used to attempt database actions and automatically retry if unsuccessful&lt;/li&gt;
&lt;li&gt;(Polly doesn't require any initialization code)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nuget.org/packages/System.Threading.Tasks.Extensions/"&gt;ValueTask&lt;/a&gt; (Not required for .NET Standard 2.1+)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;SQLite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Xamarin.Essentials&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Xamarin.Forms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyNamespace&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseDatabase&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_databasePath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Combine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FileSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppDataDirectory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"SqliteDatabase.db3"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;Lazy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_databaseConnectionHolder&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;Lazy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_databasePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReadWrite&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;SQLiteOpenFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SharedCache&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt; &lt;span class="n"&gt;DatabaseConnection&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_databaseConnectionHolder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLiteAsyncConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;GetDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&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="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TableMappings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Any&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;MappedType&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;T&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// On sqlite-net v1.6.0+, enabling write-ahead logging allows for faster database execution&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableWriteAheadLoggingAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&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;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateTablesAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateFlags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&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;T&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&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;DatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AttemptAndRetry&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;numRetries&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="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SQLite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQLiteException&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numRetries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pollyRetryAttempt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="nf"&gt;pollyRetryAttempt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;attemptNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMilliseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Pow&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="n"&gt;attemptNumber&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: Inheriting from BaseDatabase
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyNamespace&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CustomerDatabase&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BaseDatabase&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomerModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAllCustomers&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;databaseConnection&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;GetDatabaseConnection&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomerModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;AttemptAndRetry&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;databaseConnection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CustomerModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;ToListAsync&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I highly recommend using &lt;code&gt;BaseDatabase.cs&lt;/code&gt; in all of your Xamarin apps to take advantage of these awesome performance improvements!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.microsoft.com/dotnet/framework/performance/lazy-initialization?WT.mc_id=sqlite-devto-bramin"&gt;Lazy Loading&lt;/a&gt;&lt;/strong&gt; - ensure your app launches quickly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.sqlite.org/wal.html"&gt;Write Ahead Logging&lt;/a&gt;&lt;/strong&gt; - faster/more-efficient database writes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attempt And Retry&lt;/strong&gt; - use &lt;a href="https://www.nuget.org/packages/Polly/"&gt;Polly&lt;/a&gt; to retry database writes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.youtube.com/watch?v=J0mcYVxJEl0"&gt;ConfigureAwait(false)&lt;/a&gt;&lt;/strong&gt; - avoid unnecessarily returning to the Main Thread&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://blogs.msdn.microsoft.com/dotnet/2018/11/07/understanding-the-whys-whats-and-whens-of-valuetask?WT.mc_id=sqlite-devto-bramin"&gt;ValueTask&lt;/a&gt; - avoid unnecessary memory allocations&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>xamarin</category>
      <category>sqlite</category>
      <category>csharp</category>
    </item>
    <item>
      <title>#25DaysOfServerless Day 18 Solution: Wrapping the Perfect Gift</title>
      <dc:creator>Brandon Minnick</dc:creator>
      <pubDate>Thu, 19 Dec 2019 01:00:08 +0000</pubDate>
      <link>https://forem.com/azure/25daysofserverless-day-18-solution-wrapping-the-perfect-gift-2542</link>
      <guid>https://forem.com/azure/25daysofserverless-day-18-solution-wrapping-the-perfect-gift-2542</guid>
      <description>&lt;p&gt;&lt;a href="https://25daysofserverless.com/calendar/18" 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%2Fres.cloudinary.com%2Fjen-looper%2Fimage%2Fupload%2Fv1576271295%2Fimages%2Fchallenge-18_hraoqx.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello Friends! &lt;/p&gt;

&lt;p&gt;The challenge on &lt;a href="https://25daysofserverless.com/calendar/18" rel="noopener noreferrer"&gt;Day 18&lt;/a&gt; of &lt;a href="https://25daysofserverless.com" rel="noopener noreferrer"&gt;#25DaysOfServerless&lt;/a&gt; is to ensure that each gift is perfectly wrapped according to the following rules&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Placed in a box&lt;/li&gt;
&lt;li&gt;Box is wrapped&lt;/li&gt;
&lt;li&gt;A bow / ribbon placed on top&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's accomplish this using &lt;a href="https://azure.microsoft.com/services/storage/blobs?WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Azure Blob Storage&lt;/a&gt;, &lt;a href="https://azure.microsoft.com/services/cognitive-services/computer-vision?WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Azure Computer Vision API&lt;/a&gt;, and &lt;a href="https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Using this &lt;a href="https://user-images.githubusercontent.com/13558917/70572373-88876980-1b54-11ea-8cd5-af07306b6d19.jpg" rel="noopener noreferrer"&gt;example of a perfectly wrapped gift&lt;/a&gt;, the Computer Vision API confirms the following &lt;strong&gt;Tags&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Box&lt;/li&gt;
&lt;li&gt;Gift Wrapping&lt;/li&gt;
&lt;li&gt;Ribbon&lt;/li&gt;
&lt;li&gt;Present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://azure.microsoft.com/services/cognitive-services/computer-vision?WT.mc_id=25daysofserverless-devto-bramin" 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%2Fuser-images.githubusercontent.com%2F13558917%2F70573740-71964680-1b57-11ea-9126-e71f2de14a45.png" alt="Computer Vision Results Example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Solution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 0: Install Tools
&lt;/h3&gt;

&lt;p&gt;In this step, we will install the necessary commandline tools in order to complete the solution.&lt;/p&gt;

&lt;p&gt;1 - Install .NET Core v3.1&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a browser, navigate to the &lt;a href="https://dotnet.microsoft.com/download/dotnet-core/3.1?WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Download .NET Core Website&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Download .NET Core Website&lt;/strong&gt;, install .NET Core 3.1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2 - Install the &lt;a href="https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest&amp;amp;WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Azure CLI&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;(Windows) &lt;a href="https://aka.ms/installazurecliwindows" rel="noopener noreferrer"&gt;Download the MSI Installer&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(macOS) In the terminal, enter the following command:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; brew &lt;span class="nb"&gt;install &lt;/span&gt;azure-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - Install &lt;a href="https://docs.microsoft.com/azure/azure-functions/functions-run-local?WT.mc_id=25daysofserverless-devto-bramin#v3" rel="noopener noreferrer"&gt;Azure Functions Core Tools v3.x&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Windows) In the terminal, enter the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; azure-functions-core-tools@3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;(macOS) In the terminal, enter the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew tap azure/functions
brew &lt;span class="nb"&gt;install &lt;/span&gt;azure-functions-core-tools@3
&lt;span class="c"&gt;# if upgrading on a machine that has 2.x installed&lt;/span&gt;
brew &lt;span class="nb"&gt;link&lt;/span&gt; &lt;span class="nt"&gt;--overwrite&lt;/span&gt; azure-functions-core-tools@3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4 - Install Git Command Line Tools&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a browser, navigate to the &lt;a href="https://git-scm.com/downloads" rel="noopener noreferrer"&gt;Git Downloads Page&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;On the &lt;strong&gt;Git Downloads Page&lt;/strong&gt;, install git for your specific operating system&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Downloading the Solution Repo
&lt;/h3&gt;

&lt;p&gt;In this step, we will fork and clone the solution repo to our local machine.&lt;/p&gt;

&lt;p&gt;0 - Star the &lt;a href="https://github.com/brminnick/Perfect-Gift" rel="noopener noreferrer"&gt;Solution Repo&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Starring the repo will help it become more discoverable, helping more devs find the solution&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;In a browser, navigate to the &lt;a href="https://github.com/brminnick/Perfect-Gift" rel="noopener noreferrer"&gt;Perfect-Gift repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In the browser, tt the top of the page, click &lt;strong&gt;Star&lt;/strong&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F13558917%2F71127002-02e06b00-219f-11ea-9c10-347049d4fcf7.png" alt="GitHub Star"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;1 - Fork the &lt;a href="https://github.com/brminnick/Perfect-Gift" rel="noopener noreferrer"&gt;Solution Repo&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In a browser, navigate to the &lt;a href="https://github.com/brminnick/Perfect-Gift" rel="noopener noreferrer"&gt;Perfect-Gift repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;In the browser, tt the top of the page, click &lt;strong&gt;Star&lt;/strong&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F13558917%2F71126991-fa883000-219e-11ea-9da5-26a6f893b439.png" alt="GitHub Fork"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2 - Clone the newly Forked Repo&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the terminal, enter the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/[your github user name]/Perfect-Gift
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Replace &lt;code&gt;[your github user name]&lt;/code&gt; with your &lt;a href="https://stackoverflow.com/a/19077217/5953643" rel="noopener noreferrer"&gt;GitHub User name&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 2: Log into Azure CLI
&lt;/h3&gt;

&lt;p&gt;1 - In the terminal, enter the following command to login into Azure CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Stand by until the Azure CLI opens your browser to the Azure Login page&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 3: Create Azure Resources
&lt;/h3&gt;

&lt;p&gt;In this step, we'll generate the following Azure Resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure Resource Group

&lt;ul&gt;
&lt;li&gt;This is a folder in azure that will hold our resources&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://azure.microsoft.com/services/storage/blobs?WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Azure Blob Storage&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;This is where we'll upload and store the images of our gifts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://azure.microsoft.com/services/cognitive-services/computer-vision?WT.mc_id=25daysofserverless-github-bramin" rel="noopener noreferrer"&gt;Computer Vision API&lt;/a&gt; Key

&lt;ul&gt;
&lt;li&gt;This API will use machine learning to confirm that our gift has been perfectly wrapped&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=25daysofserverless-devto-bramin" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;This server less function will run each time a new photo is uploaded to Azure Blob Storage to confirm that the image contains a perfectly wrapped gift&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;1 - In the terminal, enter the following command to create an Azure Resource Group&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az group create &lt;span class="nt"&gt;--name&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--location&lt;/span&gt; EastUS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - In the terminal, enter the following command to create a free Computer Vision resource&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az cognitiveservices account create &lt;span class="nt"&gt;--resource-group&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--name&lt;/span&gt; PerfectGiftComputerVision &lt;span class="nt"&gt;--sku&lt;/span&gt; F0 &lt;span class="nt"&gt;--kind&lt;/span&gt; ComputerVision &lt;span class="nt"&gt;--location&lt;/span&gt; EastUS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - In the terminal, in the JSON response, note the value of &lt;strong&gt;endpoint&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For the EastUS, the endpoint should be &lt;code&gt;https://eastus.api.cognitive.microsoft.com&lt;/code&gt;. We will use this value later in our serverless function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;4 - In the terminal, enter the following command to retrieve the newly generated Computer Vision API Key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az cognitiveservices account keys list &lt;span class="nt"&gt;--resource-group&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--name&lt;/span&gt; PerfectGiftComputerVision
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;5 - In the terminal, in the JSON response, note the value of &lt;strong&gt;key1&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The JSON response will provide two keys. Both keys are valid, and we'll be using &lt;strong&gt;key1&lt;/strong&gt; for our serverless function.&lt;/p&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;"key1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[YOUR API KEY]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[YOUR API KEY]"&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;/blockquote&gt;

&lt;p&gt;6 - In the terminal, enter the following command to create an Azure Storage account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage account create &lt;span class="nt"&gt;--name&lt;/span&gt; giftstorage[YOUR NAME] &lt;span class="nt"&gt;--location&lt;/span&gt; EastUS &lt;span class="nt"&gt;--resource-group&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--sku&lt;/span&gt; Standard_LRS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[Your Name]&lt;/code&gt; with your name to ensure the storage account name is unique, e.g. &lt;code&gt;giftstoragebrandon&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;7 - In the terminal, enter the following command retrive the Azure Storage Connection String&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage account show-connection-string &lt;span class="nt"&gt;--name&lt;/span&gt; giftstorage[YOUR NAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[Your Name]&lt;/code&gt; with your name&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;8 - In the terminal, in the JSON response, copy the value of &lt;strong&gt;connectionString&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; We will use &lt;strong&gt;connectionString&lt;/strong&gt; in the next step to create a new storage container&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;9 - In the terminal, enter the following command to create container called &lt;code&gt;gifts&lt;/code&gt; in our Azure Storage account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage container create &lt;span class="nt"&gt;--name&lt;/span&gt; gifts &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"[YOUR CONNECTION STRING]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR CONNECTION STRING]&lt;/code&gt; with the vaulue of &lt;strong&gt;connectionString&lt;/strong&gt; retreived in the previous step, e.g. az &lt;code&gt;storage container create --name gifts --connection-string "abc123def456ghi789=="&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;10 - In the terminal, enter the following command to create an Azure Function App:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp create &lt;span class="nt"&gt;--resource-group&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--consumption-plan-location&lt;/span&gt; EastUS &lt;span class="nt"&gt;--name&lt;/span&gt; PerfectGift-[Your Name] &lt;span class="nt"&gt;--storage-account&lt;/span&gt;  giftstorage[YOUR NAME] &lt;span class="nt"&gt;--runtime&lt;/span&gt; dotnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[Your Name]&lt;/code&gt; with your name to ensure the function app name is unique, e.g. &lt;code&gt;PerfectGift-Brandon&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;11 - In the terminal, enter the following to set the Azure Functions Runtime to v3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp config appsettings &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--name&lt;/span&gt; PerfectGift-Brandon &lt;span class="nt"&gt;--settings&lt;/span&gt; &lt;span class="s2"&gt;"FUNCTIONS_EXTENSION_VERSION=~3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;12 - In the terminal, enter the following to add the Computer Vision API &lt;strong&gt;key&lt;/strong&gt; and &lt;strong&gt;endpoint&lt;/strong&gt; to the newly created Azure Function App:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az functionapp config appsettings &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;--resource-group&lt;/span&gt; PerfectGift &lt;span class="nt"&gt;--name&lt;/span&gt; PerfectGift-[YOUR NAME] &lt;span class="nt"&gt;--settings&lt;/span&gt; &lt;span class="s2"&gt;"VisionApiKey=[YOUR API KEY]"&lt;/span&gt; &lt;span class="s2"&gt;"VisionApiBaseUrl=[YOUR COMPUTER VISION ENDPOINT]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR NAME]&lt;/code&gt; with your name, replace &lt;code&gt;[YOUR API KEY]&lt;/code&gt; with the value of &lt;strong&gt;key1&lt;/strong&gt; and replace &lt;code&gt;[YOUR COMPUTER VISION ENDPOINT]&lt;/code&gt; with the value of &lt;strong&gt;endpoint&lt;/strong&gt;&lt;br&gt;
e.g. &lt;code&gt;az functionapp config appsettings set --resource-group PerfectGift --name PerfectGift-Brandon --settings "VisionApiKey=abc123" "VisionApiBaseUrl=https://eastus.api.cognitive.microsoft.com"&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 4: Publish Azure Function
&lt;/h3&gt;

&lt;p&gt;In this step, we will publish the solution found in &lt;code&gt;PerfectGift.csproj&lt;/code&gt; to Azure.&lt;/p&gt;

&lt;p&gt;1 - In the terminal, enter the following command to navigate to the folder containing &lt;code&gt;PerfectGift.csproj&lt;/code&gt; in the cloned solution repo&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Windows)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Path to cloned solution repo]&lt;span class="se"&gt;\P&lt;/span&gt;erfect-Gift&lt;span class="se"&gt;\P&lt;/span&gt;erfectGift&lt;span class="se"&gt;\&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;(macOS)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;Path to cloned solution repo]/Perfect-Gift/PerfectGift
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - In the terminal, enter the following command to publish &lt;code&gt;PerfectGift.csproj&lt;/code&gt; to our Azure Function App:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;func azure functionapp publish PerfectGift-[YOUR NAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR NAME]&lt;/code&gt; with your name&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 5: Upload Perfectly Wrapped Gift Images
&lt;/h3&gt;

&lt;p&gt;Our serverless functon is now ready to verify our gift images!&lt;/p&gt;

&lt;p&gt;In this step, we will upload images to Azure Blob Storage and confirm that our serverless function automatically verifies the image is a perfectly wrapped gift. If the image is not of a perfectly wrapped gift, it will automatically be removed from Azure Blob Storage.&lt;/p&gt;

&lt;p&gt;1 - Download this sample image of a &lt;a href="https://user-images.githubusercontent.com/13558917/70572373-88876980-1b54-11ea-8cd5-af07306b6d19.jpg" rel="noopener noreferrer"&gt;perfectly wrapped gift&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2 - Move &amp;amp; rename the downloaded image of a perfectly wrapped gift:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Windows) Save the file as C:\Downloads\gift.jpg&lt;/li&gt;
&lt;li&gt;(macOS) Save the file as ~/Download/gift.jpg&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;3 - In the terminal, enter the following command to upload our image of a perfectly wrapped gift&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage blob upload &lt;span class="nt"&gt;--container-name&lt;/span&gt; gifts &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"[YOUR CONNECTION STRING]"&lt;/span&gt; &lt;span class="nt"&gt;--file&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;FILE PATH TO GIFT IMAGE] &lt;span class="nt"&gt;--name&lt;/span&gt; Gift1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR CONNECTION STRING]&lt;/code&gt; with the value of &lt;strong&gt;connectionString&lt;/strong&gt; and replace &lt;code&gt;[FILE PATH TO GIFT IMAGE]&lt;/code&gt; with the file path to your wrapped gift image&lt;br&gt;
e.g. &lt;code&gt;az storage blob upload --container-name gifts --connection-string "abc123def456ghi789==" --file cd:\Downloads\gift.jpg --name Gift1&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;4 - In the terminal, enter the following command to confirm the image has been &lt;strong&gt;not&lt;/strong&gt; been deleted from storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage blob list &lt;span class="nt"&gt;--container-name&lt;/span&gt; gifts &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"[YOUR CONNECTION STRING]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR CONNECTION STRING]&lt;/code&gt; with the value of &lt;strong&gt;connectionString&lt;/strong&gt; and replace &lt;code&gt;[FILE PATH TO GIFT IMAGE]&lt;/code&gt; with the file path to your wrapped gift image&lt;br&gt;
e.g. &lt;code&gt;az storage blob list --container-name gifts --connection-string "abc123def456ghi789=="&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;5 - In the JSON response, confirm &lt;strong&gt;"name": "Gift1"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;6 - Download this sample image of a &lt;a href="https://user-images.githubusercontent.com/13558917/71133980-696e8480-21b1-11ea-942e-93508643f1e7.jpg" rel="noopener noreferrer"&gt;wrapped gift missing a bow&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;7 - Move &amp;amp; rename the downloaded image of a wrapped gift missing a bow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;(Windows) Save the file as C:\Downloads\nobow.jpg&lt;/li&gt;
&lt;li&gt;(macOS) Save the file as ~/Download/nobow.jpg&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;In the terminal, enter the following command to upload our image of a perfectly wrapped gift
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage blob list &lt;span class="nt"&gt;--container-name&lt;/span&gt; gifts &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"[YOUR CONNECTION STRING]"&lt;/span&gt; &lt;span class="nt"&gt;--file&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;FILE PATH TO NO BOW GIFT IMAGE] &lt;span class="nt"&gt;--name&lt;/span&gt; Gift2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR CONNECTION STRING]&lt;/code&gt; with the value of &lt;strong&gt;connectionString&lt;/strong&gt; and replace &lt;code&gt;[FILE PATH TO GIFT IMAGE]&lt;/code&gt; with the file path to your wrapped gift image&lt;/p&gt;

&lt;p&gt;e.g. &lt;code&gt;az storage blob upload --container-name gifts --connection-string "abc123def456ghi789==" --file cd:\Downloads\nobow.jpg --name Gift2&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;9 - In the terminal, enter the following command to confirm the image has been &lt;strong&gt;not&lt;/strong&gt; been deleted from storage:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az storage blob list &lt;span class="nt"&gt;--container-name&lt;/span&gt; gifts &lt;span class="nt"&gt;--connection-string&lt;/span&gt; &lt;span class="s2"&gt;"[YOUR CONNECTION STRING]"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Replace &lt;code&gt;[YOUR CONNECTION STRING]&lt;/code&gt; with the value of &lt;strong&gt;connectionString&lt;/strong&gt; and replace &lt;code&gt;[FILE PATH TO GIFT IMAGE]&lt;/code&gt; with the file path to your wrapped gift image&lt;/p&gt;

&lt;p&gt;e.g. &lt;code&gt;az storage blob list --container-name gifts --connection-string "abc123def456ghi789=="&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;10 - In the JSON response, confirm that &lt;strong&gt;"name": "Gift2"&lt;/strong&gt; does &lt;strong&gt;not&lt;/strong&gt; exist&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It may take a minute for the Blob Trigger Function to analyze the uploaded image. &lt;/p&gt;

&lt;p&gt;If &lt;strong&gt;"name": "Gift2"&lt;/strong&gt; does still exist, run &lt;code&gt;az storage blob list --container-name gifts --connection-string "[YOUR CONNECTION STRING]"&lt;/code&gt; again in a few minutes &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 6: Celebrate 🎉
&lt;/h3&gt;

&lt;p&gt;We now have a working Blob Trigger that automatically verifies our gifts have been perfectly wrapped!&lt;/p&gt;

&lt;p&gt;We have successfully completed the &lt;a href="https://25daysofserverless.com/calendar/18" rel="noopener noreferrer"&gt;Day 18 Challenge&lt;/a&gt; of &lt;a href="https://25daysofserverless.com" rel="noopener noreferrer"&gt;#25DaysOfServerless&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>azure</category>
    </item>
    <item>
      <title>Introducing #25DaysOfServerless, an Azure Functions Challenge</title>
      <dc:creator>Brandon Minnick</dc:creator>
      <pubDate>Mon, 25 Nov 2019 15:23:31 +0000</pubDate>
      <link>https://forem.com/azure/introducing-25daysofserverless-an-azure-functions-challenge-6b5</link>
      <guid>https://forem.com/azure/introducing-25daysofserverless-an-azure-functions-challenge-6b5</guid>
      <description>&lt;p&gt;&lt;a href="https://gifyu.com/image/vNo5" 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%2Fs5.gifyu.com%2Fimages%2Fadvent-of-serverless.gif" alt="advent-of-serverless.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello Friends!  &lt;/p&gt;

&lt;p&gt;We are excited to announce &lt;a href="https://www.25daysofserverless.com" rel="noopener noreferrer"&gt;#25DaysOfServerless&lt;/a&gt;, a 25-day event to create a 25 new serverless workloads leveraging &lt;a href="https://azure.microsoft.com/services/functions?WT.mc_id=25daysofserverless-blog-cxa" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules
&lt;/h2&gt;

&lt;p&gt;Solve the daily challenge in the programming language of your choice. Then submit your solution via GitHub (and share it on Twitter), and we'll showcase the best solutions every week! &lt;/p&gt;

&lt;p&gt;If you're new to serverless, we'll have hints to help you! All you need is a GitHub account to post your solution and a sense of adventure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;'Tis the season for gift giving, and we need a solution to share images of our gifts! One problem though: we can only share png files.&lt;/p&gt;

&lt;p&gt;For this challenge, create an Azure Function triggered by Azure Blob Storage that will verify that each photo uploaded to our Azure Blob Storage container is a png; if it is not, delete the photo from the container.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can create a simple &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-storage-blob-triggered-function?WT.mc_id=25daysofserverless-blog-cxa" rel="noopener noreferrer"&gt;BlobTrigger in Azure Functions&lt;/a&gt; to solve this one in C#!&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="nf"&gt;FunctionName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GiftPhotoValidationFunction&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;BlobTrigger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_containerName&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="n"&gt;CloudBlockBlob&lt;/span&gt; &lt;span class="n"&gt;blockBlob&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Validating Gift Image is a PNG"&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="n"&gt;blockBlob&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;EndsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;StringComparison&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvariantCultureIgnoreCase&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Confirmed PNG"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Photo &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;blockBlob&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="s"&gt; is not a PNG"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Deleting &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;blockBlob&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="s"&gt; from container"&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;blockBlob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DeleteAsync&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Deleted &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;blockBlob&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;Starting December 1st, visit &lt;a href="https://www.25daysofserverless.com" rel="noopener noreferrer"&gt;https://www.25daysofserverless.com&lt;/a&gt; to find the daily challenge, and follow both &lt;a href="https://twitter.com/azureadvocates" rel="noopener noreferrer"&gt;@AzureAdvocates&lt;/a&gt; and &lt;a href="https://twitter.com/search?q=%2325DaysOfServerless&amp;amp;src=typed_query" rel="noopener noreferrer"&gt;#25DaysOfServerless&lt;/a&gt; on Twitter. &lt;/p&gt;

&lt;p&gt;If you're new to Azure, sign up for a &lt;a href="https://azure.microsoft.com/free/?WT.mc_id=25daysofserverless-blog-cxa" rel="noopener noreferrer"&gt;Free Azure Account&lt;/a&gt; before &lt;a href="https://twitter.com/search?q=%2325DaysOfServerless&amp;amp;src=typed_query" rel="noopener noreferrer"&gt;#25DaysOfServerless&lt;/a&gt; kicks off on December 1st!&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>azure</category>
    </item>
  </channel>
</rss>
