<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Nolan Bradshaw]]></title><description><![CDATA[Backend software engineer with a love for .NET]]></description><link>https://www.nolanbradshaw.ca</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 21:21:45 GMT</lastBuildDate><atom:link href="https://www.nolanbradshaw.ca/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Creating the .NET React template with TypeScript]]></title><description><![CDATA[When creating a .NET project you have the option of using a React template. Using this project template is extremely useful when trying to get a project up and running quickly. Out of the box, this template allows us to run the npm server on build, p...]]></description><link>https://www.nolanbradshaw.ca/net-react-typescript-template</link><guid isPermaLink="true">https://www.nolanbradshaw.ca/net-react-typescript-template</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[React]]></category><category><![CDATA[.NET]]></category><category><![CDATA[Tutorial]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Nolan Bradshaw]]></dc:creator><pubDate>Wed, 08 Dec 2021 16:33:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638980393852/v8BOA13dq.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When creating a .NET project you have the option of using a React template. Using this project template is extremely useful when trying to get a project up and running quickly. Out of the box, this template allows us to run the npm server on build, proxy requests to the backend, and have our frontend hosted on HTTPS (for development) by using the .NET local certificate.</p>
<p>TLDR: Download the template created in this article from:  <a target="_blank" href="https://github.com/nolanbradshaw/ReactTypeScript.NET">ReactTypeScript.NET</a> </p>
<h1 id="heading-creating-the-project">Creating the project</h1>
<p>First thing we need to do is create the project. We are still going to use the React template, but we will modify it later to use TypeScript.</p>
<p>Open Visual Studio and create a new project. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638892236695/fKKfUZ6Ur.png" alt="select-template.PNG" /></p>
<p>Select the .NET Core with React template. Next, give your project a name and select your framework (I will be using .NET 6).</p>
<p>You should now have a .NET project that contains a folder called ClientApp. This is the folder where your React code sits. Since we aren't going to be using the JavaScript code that comes with this template we can go ahead and delete this folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638892554146/orXXcaE6N.png" alt="folder-structure.PNG" /></p>
<p>Now that the JavaScript code is gone we can create our TypeScript React project. Open up the command line and navigate to the directory of your .NET project (where the ClientApp folder used to be) and run 
<code>npx create-react-app client-app --template typescript</code> .</p>
<p>Finally, inside your projects .csproj file update SpaRoot to the folder name of your react-app (I used client-app). </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638918320477/nIcFb_UuF.png" alt="Csproj-File.PNG" /></p>
<h1 id="heading-installing-dependencies">Installing Dependencies</h1>
<p>There are a few things we need to make sure everything goes smoothly.</p>
<p>Make sure you have a modern version of node (I'm using 16.13.1 for this article). You can run <code>node -v</code> to check the version you are using.</p>
<p>You will also need <code>ts-node</code> installed, if you don't have it already you can run 
<code>npm install ts-node</code> in your react apps root directory or <code>npm install -g ts-node</code> if you would like to install it globally. </p>
<p>Lastly, navigate to the react app you created before and run <code>npm install @types/node --save-dev</code> this will help you avoid any issues with importing modules.</p>
<h1 id="heading-configuring-the-proxy">Configuring the proxy</h1>
<p>Now that we have the TypeScript React project created inside our .NET project we want to make it easy to proxy requests to the backend. This is optional, just know that if you don't do this you will have to specify where to send requests (https://localhost:44388/api/request for example).</p>
<p>Open up your launchSettings.json file inside the Properties folder and take note of the application URL and SSL port.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638898059825/8zTrQtD0I.png" alt="launchsettings.PNG" /></p>
<p>Next, open your package.json file inside the client-app folder you created and set the proxy property to the URL from the launchSettings file. While we haven't set up HTTPS quite yet we will do that later so we should set it to the HTTPS URL.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638979272615/K0Jx89vuB.png" alt="proxy-package.PNG" /></p>
<p>While we're in the package.json we will also add <code>"type": "module"</code> which you can read more about  <a target="_blank" href="https://blog.logrocket.com/es-modules-in-node-today/">here</a>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638979281634/31yBHlvjr.png" alt="setting-type.PNG" /></p>
<h1 id="heading-setting-up-https">Setting up HTTPS</h1>
<p>There are two main files that the .NET React template uses to configure HTTPS, we are going to create those files manually but in TypeScript rather than JavaScript.</p>
<p>Inside the client-app/src folder create two files called aspnetcore-https.ts and aspnetcore-react.ts. Below is what my folder structure looks like after creating those two files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638898762860/OMBy2iF9o.png" alt="https-files.PNG" /></p>
<p>Now we actually have to write some code. Open the aspnetcore-https.ts file you just created and add this code (or you can copy it from <a target="_blank" href="https://github.com/nolanbradshaw/ReactTypeScript.NET/blob/master/TypescriptReact/client-app/src/aspnetcore-https.ts">here</a>). </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638914442138/4zSpcmrpJ.png" alt="aspnetcore-https.PNG" /></p>
<p>This is going to allow your frontend to use the .NET HTTPS development certificate. </p>
<p>You can now open the aspnetcore-react.ts file and add this code (or copy it from  <a target="_blank" href="https://github.com/nolanbradshaw/ReactTypeScript.NET/blob/master/TypescriptReact/client-app/src/aspnetcore-react.ts">here</a>).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638915638226/Xi1XMeD--.png" alt="aspnetcore-react.PNG" /></p>
<p>The aspnetcore-react.ts file sets up the .env.development.local file with environment variables to configure HTTPS.</p>
<p>To finish setting up HTTPS locally we need to have these two scripts run on build. This is pretty simple to do by modifying your package.json script section. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638915884091/tkiEfKvC0.png" alt="prestart-script.PNG" /></p>
<p>You can test that everything is working as expected now by running <code>npm run prestart</code> or by running the whole app with IIS.</p>
<h1 id="heading-troubleshooting">Troubleshooting</h1>
<p>If your app isn't running properly there are a few key areas to check. </p>
<ul>
<li>Verify your node version by running <code>node -v</code> (I'm using 16.13.1)</li>
<li>Verify ts-node and <code>@types/node</code> are installed</li>
<li>Check that <code>"target": "ES6"</code> and <code>"module": "ESNext"</code> is set in tsconfig.json</li>
<li>In the package.json file make sure that <code>"type": "module"</code> is set</li>
</ul>
<h1 id="heading-finishing-up">Finishing up</h1>
<p>At this point, you should have all the features of the .NET React JS template but with TypeScript. Hopefully, one-day Visual Studio will come with an option on top of the React template that lets you select between JavaScript and TypeScript.</p>
<p>You can look at the project created in this article here:  <a target="_blank" href="https://github.com/nolanbradshaw/ReactTypeScript.NET">ReactTypeScript.NET</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How To Upload, Download, Delete Files In AWS S3 With .NET Core]]></title><description><![CDATA[Recently I have been working on a project that works with a lot of files. I ended up choosing Amazon's S3 for storing the files for various reasons, but I won't get into that for this article.
While doing research on working with S3 in .NET Core I di...]]></description><link>https://www.nolanbradshaw.ca/how-to-upload-download-delete-files-in-aws-s3-with-net-core</link><guid isPermaLink="true">https://www.nolanbradshaw.ca/how-to-upload-download-delete-files-in-aws-s3-with-net-core</guid><category><![CDATA[AWS]]></category><category><![CDATA[Amazon S3]]></category><category><![CDATA[.NET]]></category><category><![CDATA[C#]]></category><category><![CDATA[files]]></category><dc:creator><![CDATA[Nolan Bradshaw]]></dc:creator><pubDate>Fri, 16 Apr 2021 00:28:51 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618583073308/vPmr8x84V.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Recently I have been working on a project that works with a lot of files. I ended up choosing Amazon's S3 for storing the files for various reasons, but I won't get into that for this article.</p>
<p>While doing research on working with S3 in .NET Core I didn't find much beyond a couple of articles that work with an older version of the AWS SDK, and some stack overflow posts. After figuring out some of the functionality I needed, I decided to write an article to help others get started with the AWS SDK and S3.</p>
<h1 id="pre-requisites">Pre-requisites</h1>
<ul>
<li>You should have an AWS account.</li>
<li>You should have a bucket set up in S3.</li>
<li>You should know your AWS access key and secret</li>
</ul>
<p><a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html">Amazon S3 creating a bucket</a> </p>
<p><a target="_blank" href="https://docs.aws.amazon.com/general/latest/gr/aws-sec-cred-types.html">Understanding and getting your AWS credentials</a> </p>
<h1 id="dependencies">Dependencies</h1>
<p>To get started we have to install some dependencies. There is only one dependency if all you need from the AWS SDK is functionality for S3.</p>
<ul>
<li>AWSSDK.S3</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618509455737/xIVdnzhzO.png" alt="s3-package.PNG" /></p>
<p>You can install this package from NuGet. At the time of writing this article, the current version is 3.7.0.13.</p>
<h2 id="basicawscredentials">BasicAWSCredentials</h2>
<p>To authenticate yourself with the AWS SDK we need to create an instance of BasicAWSCredentials.</p>
<p>We can create a Singleton on startup to get the credentials through dependency injection and read our keys from the appsettings.json file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618510666972/lBCijBf9n.png" alt="s3-startup.PNG" /></p>
<h1 id="upload-a-file">Upload a file</h1>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AmazonS3</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> BasicAWSCredentials _awsCredentials;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AmazonS3</span>(<span class="hljs-params">BasicAWSCredentials awsCredentials</span>)</span>
    {
        _awsCredentials = awsCredentials;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">UploadFileAsync</span>(<span class="hljs-params">IFormFile file, <span class="hljs-keyword">string</span> fileName</span>)</span>
    {
        <span class="hljs-comment">// Set RegionEndpoint to your AWS region.</span>
        AmazonS3Config config = <span class="hljs-keyword">new</span>()
        {
            RegionEndpoint = Amazon.RegionEndpoint.USEast2
        };

        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> AmazonS3Client(_awsCredentials, config);

        <span class="hljs-keyword">await</span> <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> memStream = <span class="hljs-keyword">new</span> MemoryStream();
        <span class="hljs-keyword">await</span> file.CopyToAsync(memStream);

        <span class="hljs-keyword">var</span> uploadRequest = <span class="hljs-keyword">new</span> TransferUtilityUploadRequest
        {
            InputStream = memStream,
            Key = fileName,
            BucketName = <span class="hljs-string">"your-bucket-name"</span>,
            CannedACL = S3CannedACL.Private
        };

        <span class="hljs-keyword">var</span> fileTransferUtil = <span class="hljs-keyword">new</span> TransferUtility(client);
        <span class="hljs-keyword">await</span> fileTransferUtil.UploadAsync(uploadRequest);
    }
}
</code></pre><p>The code for uploading a file is quite simple once you understand a bit about the AWS SDK and how S3 works. </p>
<p>First, we set up a configuration for what region we are in. Next, we create an S3 client and copy our file over to a MemoryStream. Finally, we pass our stream, file name, S3 bucket name, and our access control permissions to a TransferUtilityUploadRequest and call UploadAsync to upload the file to S3.</p>
<p>If you aren't sure about access control permissions (or ACL) you can read more here:  <a target="_blank" href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html">Access Control List Overview</a> </p>
<h1 id="get-a-file">Get a file</h1>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AmazonS3</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> BasicAWSCredentials _awsCredentials;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AmazonS3</span>(<span class="hljs-params">BasicAWSCredentials awsCredentials</span>)</span>
    {
        _awsCredentials = awsCredentials;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;GetObjectResponse&gt; <span class="hljs-title">GetFileAsync</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> fileName</span>)</span>
    {
         <span class="hljs-comment">// Set RegionEndpoint to your AWS region.</span>
        AmazonS3Config config = <span class="hljs-keyword">new</span>()
        {
            RegionEndpoint = Amazon.RegionEndpoint.USEast2
        };

        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> AmazonS3Client(_awsCredentials, config);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> client.GetObjectAsync(<span class="hljs-string">"your-bucket-name"</span>, fileName);
    }
}
</code></pre><p>To get a file from S3 the only thing we need is the name of the file. Just like before we set a configuration for the region we're in and create an instance of AmazonS3Client. We can then call GetObjectAsync with the name of our bucket and the name of the file. </p>
<p>The response is an instance of GetObjectResponse. This object has a ResponseStream property that is a stream of the file, which you can use to write the file to disk (or whatever else you need to do).</p>
<h1 id="delete-a-file">Delete a file</h1>
<pre><code><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AmazonS3</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> BasicAWSCredentials _awsCredentials;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AmazonS3</span>(<span class="hljs-params">BasicAWSCredentials awsCredentials</span>)</span>
    {
        _awsCredentials = awsCredentials;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">DeleteFileAsync</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> fileName</span>)</span>
    {
         <span class="hljs-comment">// Set RegionEndpoint to your AWS region.</span>
        AmazonS3Config config = <span class="hljs-keyword">new</span>()
        {
            RegionEndpoint = Amazon.RegionEndpoint.USEast2
        };

        <span class="hljs-keyword">using</span> <span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> AmazonS3Client(_awsCredentials, config);
        <span class="hljs-keyword">await</span> client.DeleteObjectAsync(<span class="hljs-string">"your-bucket-name"</span>, fileName);
    }
}
</code></pre><p>Deleting a file is the same as retrieving a file as we did above but this time we make a call to DeleteObjectAsync. This method returns an instance of DeleteObjectResponse that gives us some information about the delete request but in this case, we just ignore the response.</p>
<h1 id="conclusion">Conclusion</h1>
<p>AWS S3 is a highly scalable and performant solution for storing simple objects like files. Working with it in .NET Core is quite simple once you get the basics of the AWS SDK. </p>
<p>If you want to learn more:</p>
<ul>
<li><a target="_blank" href="https://aws.amazon.com/s3/">AWS S3</a> </li>
<li><a target="_blank" href="https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/quick-start.html">AWS SDK for .NET</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Working with Dapper in .NET Core]]></title><description><![CDATA[I have been using Dapper for some time now (a year or so) and it doesn't get nearly enough love. While Entity Framework is an incredible ORM it introduces a lot of overhead. 
What exactly is Dapper?
Dapper is a lightweight open-source micro-ORM that ...]]></description><link>https://www.nolanbradshaw.ca/working-with-dapper-in-net-core</link><guid isPermaLink="true">https://www.nolanbradshaw.ca/working-with-dapper-in-net-core</guid><category><![CDATA[.NET]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[orm]]></category><category><![CDATA[SQL]]></category><dc:creator><![CDATA[Nolan Bradshaw]]></dc:creator><pubDate>Wed, 14 Apr 2021 17:32:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618422186405/WRuf5PTyG.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have been using Dapper for some time now (a year or so) and it doesn't get nearly enough love. While Entity Framework is an incredible ORM it introduces a lot of overhead. </p>
<h2 id="what-exactly-is-dapper">What exactly is Dapper?</h2>
<p>Dapper is a lightweight open-source micro-ORM that holds the title for the king of performance (in terms of micro-ORMs). It makes it easy to map objects to and from your database. It is also very easy to learn, and you can get a project up and running with Dapper in no time.</p>
<p>While this all sounds great, there are some drawbacks compared to Entity Framework. Dapper isn't going to generate any SQL queries or class models for you, doesn't come out of the box with CRUD functionality (can easily install the Contrib package to get those features), and you lose some advanced features like change tracking.</p>
<h2 id="why-use-dapper">Why use Dapper?</h2>
<p>Entity Framework can often just become the default choice. Most developers already know about it, have used it, and are comfortable with it.</p>
<p>In situations where you need the performance of raw SQL queries or don't need the advanced Entity Framework features, Dapper should be the choice. It affords you a great deal of control and is very easy to use.</p>
<p>I have also seen Dapper used as a read-only ORM. You use it to do all the reads in your database, and use another ORM (Entity) to do all of your writes. This approach can be really nice if you decouple your data access layer properly. Otherwise, it can get quite messy.</p>
<h2 id="how-to-use-it">How to use it</h2>
<p>Dapper is easy to use and learn. Going from not knowing about Dapper at all to understanding the very basics shouldn't take more than 30 minutes.</p>
<h3 id="query-for-a-list-of-items">Query for a list of items</h3>
<pre><code><span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IConnectionProvider _connectionProvider;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CarRepository</span>(<span class="hljs-params">IConnectionProvider connectionProvider</span>)</span>
{
    _connectionProvider = connectionProvider;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;IEnumerable&lt;Car&gt;&gt; GetListAsync()
{
    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> connection = _connectionProvider.Create())
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> connection.QueryAsync&lt;Car&gt;(<span class="hljs-string">"select * from cars"</span>);
    }
 }
</code></pre><p>First, we receive a connection provider from dependency injection. The provider is just an abstraction on creating a database connection (SqlConnection) and returns an IDbConnection.</p>
<p>We use that connection to call the QueryAsync method. QueryAsync is exactly what it sounds like, it asynchronously queries your database and maps it back to an object (in this case a Car object).</p>
<h3 id="query-for-a-single-item">Query for a single item</h3>
<pre><code><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;Car&gt; <span class="hljs-title">GetByIdAsync</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> carId</span>)</span>
{
    <span class="hljs-keyword">string</span> sql = <span class="hljs-string">"select * from cars where id = @car_id"</span>;
    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> connection = _connectionProvider.Create())
    {
        <span class="hljs-keyword">var</span> parameters = <span class="hljs-keyword">new</span> 
        {
            car_id = carId
        };

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> connection.QueryFirstAsync&lt;Car&gt;(sql, parameters);
    }
 }
</code></pre><p>QueryFirstAsync maps the first element returned in the sequence. There is also a QueryFirstOrDefaultAsync method that returns a default value if no element is returned.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;Car&gt; <span class="hljs-title">GetByIdAsync</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> carId</span>)</span>
{
    <span class="hljs-keyword">string</span> sql = <span class="hljs-string">"select * from cars where id = @car_id"</span>;
    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> connection = _connectionProvider.Create())
    {
        <span class="hljs-keyword">var</span> parameters = <span class="hljs-keyword">new</span> 
        {
            car_id = carId
        };

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> connection.QuerySingleAsync&lt;Car&gt;(sql, parameters);
    }
 }
</code></pre><p>QuerySingleAsync will map a single item returned from your database but will throw an exception if there isn't <strong>exactly</strong> one element returned. Dapper also has a QuerySingleOrDefaultAsync that returns a default value if there are no elements, but will still throw an exception if there is more than one element.</p>
<h3 id="querying-stored-procedures">Querying stored procedures</h3>
<pre><code><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;Car&gt; <span class="hljs-title">GetByIdAsync</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> carId</span>)</span>
{
    <span class="hljs-keyword">string</span> procedure = <span class="hljs-string">"sp_get_car_by_id"</span>;
    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> connection = _connectionProvider.Create())
    {
        <span class="hljs-keyword">var</span> parameters = <span class="hljs-keyword">new</span> 
        {
            car_id = carId
        };

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> connection.QueryFirstAsync&lt;Car&gt;(procedure, parameters, 
            commandType: CommandType.StoredProcedure);
    }
 }
</code></pre><p>We can query using stored procedures by passing in a procedure name, parameters (if any), and telling Dapper that the command is a stored procedure.</p>
<h3 id="executing-stored-procedures">Executing stored procedures</h3>
<p>Dapper also comes with an ExecuteAsync method that allows us to execute SQL and return the number of rows affected rather than mapping data. </p>
<pre><code><span class="hljs-comment">// Returns the number of rows affected.</span>
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;<span class="hljs-keyword">int</span>&gt; <span class="hljs-title">UpdateAsync</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> carId, <span class="hljs-keyword">string</span> color</span>)</span>
{
    <span class="hljs-keyword">string</span> procedure= <span class="hljs-string">"sp_update_car_color"</span>;
    <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> connection = _connectionProvider.Create())
    {
        <span class="hljs-keyword">var</span> parameters = <span class="hljs-keyword">new</span> 
        {
            car_id = carId,
            color
        };

        <span class="hljs-keyword">return</span> <span class="hljs-keyword">await</span> connection.ExecuteAsync(procedure, parameters, 
            commandType: CommandType.StoredProcedure);
    }
 }
</code></pre><p>ExecuteAsync looks the same as QueryAsync, the only difference in the call being we don't pass a class to map data back to since it will only return the number of rows affected.  </p>
<h2 id="closing">Closing</h2>
<p>Dapper is an extremely performant micro-ORM that is great for situations that you have large domain models, need extreme performance, or don't need some of the more advanced features of Entity Framework.</p>
<p>While it is less known than Entity Framework, it is the most popular choice for micro-ORMs.</p>
<p>Learn more Dapper:</p>
<ul>
<li><a target="_blank" href="https://dapper-tutorial.net/">Dapper Tutorial</a></li>
<li><a target="_blank" href="https://github.com/StackExchange/Dapper">Dapper GitHub</a> </li>
<li><a target="_blank" href="https://gunnarpeipman.com/aspnet-core-dapper/">Using Dapper in ASP.NET Core applications</a></li>
</ul>
]]></content:encoded></item></channel></rss>