{"id":3339,"date":"2018-06-25T07:30:11","date_gmt":"2018-06-25T06:30:11","guid":{"rendered":"https:\/\/code-maze.com\/?p=3339"},"modified":"2021-07-26T09:44:49","modified_gmt":"2021-07-26T07:44:49","slug":"async-generic-repository-pattern","status":"publish","type":"post","link":"https:\/\/code-maze.com\/async-generic-repository-pattern\/","title":{"rendered":"Implementing Asynchronous Generic Repository in ASP.NET Core"},"content":{"rendered":"<p>In this post, we are going to convert the synchronous code to asynchronous inside ASP.NET Core. First, we are going to learn a bit about asynchronous programming and why should we write async code. Then we are going to use our project from the <a href=\"https:\/\/code-maze.com\/net-core-series\/\" target=\"_blank\" rel=\"noopener noreferrer\">.NET Core series<\/a> and rewrite it in an async manner.<\/p>\n<p>In <a href=\"https:\/\/code-maze.com\/net-core-web-development-part4\/\" target=\"_blank\" rel=\"noopener noreferrer\">Part 4<\/a> of the series, we have created <a href=\"https:\/\/code-maze.com\/net-core-web-development-part4\/\" target=\"_blank\" rel=\"noopener noreferrer\">Generic Repository Pattern<\/a> and in <a href=\"https:\/\/code-maze.com\/net-core-web-development-part5\/\" target=\"_blank\" rel=\"noopener noreferrer\">Part 5<\/a> and <a href=\"https:\/\/code-maze.com\/net-core-web-development-part6\/\" target=\"_blank\" rel=\"noopener noreferrer\">Part 6<\/a> the Controller with Actions that consumes that repository. We\u00a0recommend reading those articles\u00a0if you are not familiar with Generic Repository Pattern or if you find any of the concepts in this article hard to understand. Those articles will help you follow along with this article much easier because we won\u2019t dive into its business logic.<\/p>\n<p>We are going to modify the code, step by step, to show you how easy is to convert the synchronous code to an asynchronous one. Hopefully, this will help you understand how asynchronous code works and how to write it from scratch in your applications.<\/p>\n<ul id=\"series_parts\" style=\"display: none;\">\n<li><a href=\"https:\/\/code-maze.com\/csharp-intermediate-tutorial-oop\/\" target=\"_blank\" rel=\"noopener noreferrer\">C# Intermediate Tutorial<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/global-error-handling-aspnetcore\/\" target=\"_blank\" rel=\"noopener noreferrer\">Global Error Handling in .NET Core Web API<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/authentication-aspnetcore-jwt-1\/\" target=\"_blank\" rel=\"noopener noreferrer\">ASP.NET Core Authentication with JWT and Angular<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/create-pdf-dotnetcore\/\" target=\"_blank\" rel=\"noopener noreferrer\">Create PDF in .NET Core Web API<\/a><\/li>\n<li><a href=\"https:\/\/code-maze.com\/net-core-web-api-ef-core-code-first\/\" target=\"_blank\" rel=\"noopener noreferrer\">ASP.NET Core Web API with EF Core Code-First Approach<\/a><\/li>\n<\/ul>\n<div class=\"wrap-collabsible\">\r\n    <input id=\"collapsible\" class=\"toggle\" type=\"checkbox\">\r\n    <label for=\"collapsible\" class=\"lbl-toggle\" onclick=\"writeContent()\">Recommended Articles<\/label>\r\n    <div class=\"collapsible-content\">\r\n      <div class=\"content-inner\">\r\n        <p class=\"innerContent\" id=\"innerContent\"><\/p>\r\n        <script>\r\n           function writeContent(){\r\n               var links= document.getElementById(\"series_parts\").innerHTML;\r\n               document.getElementById(\"innerContent\").innerHTML = links;\r\n           }\r\n       <\/script>\r\n      <\/div>\r\n    <\/div>\r\n<\/div>\r\n\n<p>To download the source code for our starting project, you can visit <a href=\"https:\/\/github.com\/CodeMazeBlog\/async-repository-dotnetcore-webapi\/tree\/master\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">our GitHub repo for the starting project.<\/a><\/p>\n<p>For the finished project refer to <a href=\"https:\/\/github.com\/CodeMazeBlog\/async-repository-dotnetcore-webapi\/tree\/async-repository-end-branch\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">our GitHub repo for the finished project.<\/a><\/p>\n<p>We are going to cover the following sections in this article:<\/p>\n<ul>\n<li><a href=\"#asyncprogramming\">What is Asynchronous Programming<\/a><\/li>\n<li><a href=\"#asyncawait\">Async, Await Keywords and Return Types<\/a><\/li>\n<li><a href=\"#repositorybasemodification\">Overview of the IRepositoryBase Interface and the RepositoryBase Class<\/a><\/li>\n<li><a href=\"#ownerrepositorymodification\">Modifying the IOwnerRepository Interface and the OwnerRepository Class<\/a><\/li>\n<li><a href=\"#controllermodification\">Controller Modification<\/a><\/li>\n<li><a href=\"#conclusion\">Conclusion<\/a><\/li>\n<\/ul>\n<h2 id=\"asyncprogramming\">What is Asynchronous Programming<\/h2>\n<p>Async programming is a parallel programming technique, which allows the working process to run\u00a0separately from the main application thread. As soon as the work completes, it informs the main thread about the result, whether it was successful or not.<\/p>\n<p>By using async programming, we can avoid performance bottlenecks and enhance the responsiveness of our application.<\/p>\n<p>How so?<\/p>\n<p>Because we are not sending requests to the server and blocking it while waiting for the responses anymore (as long as it takes). Now, when we send a request to the server, the thread pool delegates a thread to that request. Eventually, that thread finishes its job and returns to the thread pool freeing itself for the next request. At some point, the data will be fetched from the database and the result needs to be sent to the requester. At that time, the thread pool provides another thread to handle that work. Once the work is done, a thread is going back to the thread pool.<\/p>\n<p>It is very important to understand that if we send a request to an endpoint and\u00a0it takes\u00a0the application three or more seconds to process that request, we probably won&#8217;t be able to execute this request any faster in async mode. It is going to take the same amount of time as\u00a0the sync request.<\/p>\n<p>The only advantage is that in the async mode the thread won\u2019t be blocked three or more seconds, and thus it will be able to process other requests. This is what makes our solution scalable.<\/p>\n<p>Here is the visual representation of the asynchronous workflow:<\/p>\n<p><a href=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/Async-Threads.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-53567 size-full\" src=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/Async-Threads.png\" alt=\"Asynchronous Generic Pattern\" width=\"883\" height=\"481\" srcset=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/Async-Threads.png 883w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/Async-Threads-300x163.png 300w, https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/Async-Threads-768x418.png 768w\" sizes=\"auto, (max-width: 883px) 100vw, 883px\" \/><\/a><\/p>\n<p>Now that we cleared that out we can learn how to implement the asynchronous code in .NET Core.<\/p>\n<h2 id=\"asyncawait\">Async, Await Keywords and Return Types<\/h2>\n<p>The <code>async<\/code> and <code>await<\/code> keywords play a crucial part in asynchronous programming. By using those keywords, we can easily write asynchronous methods without too much effort.<\/p>\n<p>For example, if we want to create a method in an asynchronous manner, we need to add the\u00a0<code>async<\/code> keyword next to the method\u2019s return type:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">async Task&lt;IEnumerable&lt;Owner&gt;&gt; GetAllOwnersAsync()<\/pre>\n<p>By using the <code>async<\/code> keyword, we are enabling the <code>await<\/code> keyword and modifying the way of how method results are handled (from synchronous to asynchronous):<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">await FindAllAsync();<\/pre>\n<p>In asynchronous programming we have three return types:<\/p>\n<ul>\n<li><code>Task&lt;TResult&gt;<\/code>, for an async method that returns a value<\/li>\n<li><code>Task<\/code>, to use it for an async method that does not return a value<\/li>\n<li><code>void<\/code>, which we can use for an event handler<\/li>\n<\/ul>\n<p>What does this mean?<\/p>\n<p>Well, we can look at this through the synchronous programming glasses. If our sync method returns \u00a0<code>int<\/code> then in the async mode, it should return <code>Task&lt;int&gt;<\/code>, or if sync method returns <code>IEnumerable&lt;string&gt;<\/code> then the async method should return <code>Task&lt;IEnumerable&lt;string&gt;&gt;<\/code>.<\/p>\n<p>But if our sync method returns no value (has a <code>void<\/code> for the return type), then our async method should usually\u00a0return<code>Task<\/code>. This means that we can use the\u00a0<code>await<\/code> keyword inside that method but without the\u00a0<code>return<\/code> keyword.<\/p>\n<p>You may wonder, why not returning <code>Task<\/code> all the time? Well, we should use void only for the asynchronous event handlers which require a <code>void<\/code> return type. Other than that, we should always return a <code>Task.<\/code><\/p>\n<p>From C# 7.0 onward, we can specify any other return type, if that type includes <code>GetAwaiter<\/code> method.<\/p>\n<p>Now, when we have all the information, let&#8217;s do some refactoring in our completely synchronous code.<\/p>\n<h2 id=\"repositorybasemodification\">Overview of the IRepositoryBase Interface and the RepositoryBase Class<\/h2>\n<p>Our complete repository is interface based, so let&#8217;s take a look at our base interface. In the <code>Contracts<\/code> project open the<code> IRepositoryBase.cs<\/code> file. We can see different method signatures:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public interface IRepositoryBase&lt;T&gt;\r\n{\r\n    IQueryable&lt;T&gt; FindAll();\r\n    IQueryable&lt;T&gt; FindByCondition(Expression&lt;Func&lt;T, bool&gt;&gt; expression);\r\n    void Create(T entity);\r\n    void Update(T entity);\r\n    void Delete(T entity);\r\n}\r\n<\/pre>\n<p>It is important to notice the <code>FindAll<\/code> and <code>FindByCondition<\/code> method signatures. Both of them return IQueryable that allows us to attach async calls to them.<\/p>\n<p>The <code>Create<\/code>, <code>Update<\/code>, and <code>Delete<\/code> methods\u00a0 don\u2019t modify any data, they just track changes to an entity and wait for the EF Core\u2019s <code>SaveChanges<\/code> method to execute. So, they stay unchanged as well.<\/p>\n<p>Let&#8217;s just take a look at the <code>RepositoryBase<\/code> class:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public abstract class RepositoryBase&lt;T&gt; : IRepositoryBase&lt;T&gt; where T : class\r\n{\r\n    protected RepositoryContext RepositoryContext { get; set; }\r\n\r\n    public RepositoryBase(RepositoryContext repositoryContext)\r\n    {\r\n        this.RepositoryContext = repositoryContext;\r\n    }\r\n\r\n    public IQueryable&lt;T&gt; FindAll()\r\n    {\r\n        return this.RepositoryContext.Set&lt;T&gt;().AsNoTracking();\r\n    }\r\n\r\n    public IQueryable&lt;T&gt; FindByCondition(Expression&lt;Func&lt;T, bool&gt;&gt; expression)\r\n    {\r\n        return this.RepositoryContext.Set&lt;T&gt;()\r\n            .Where(expression).AsNoTracking();\r\n    }\r\n\r\n    public void Create(T entity)\r\n    {\r\n        this.RepositoryContext.Set&lt;T&gt;().Add(entity);\r\n    }\r\n\r\n    public void Update(T entity)\r\n    {\r\n        this.RepositoryContext.Set&lt;T&gt;().Update(entity);\r\n    }\r\n\r\n    public void Delete(T entity)\r\n    {\r\n        this.RepositoryContext.Set&lt;T&gt;().Remove(entity);\r\n    }\r\n}\r\n<\/pre>\n<p>This class is the implementation of the previous interface and it is a base class for accessing the data from the database.<\/p>\n<h2 id=\"ownerrepositorymodification\">Modifying the IOwnerRepository Interface and the OwnerRepository Class<\/h2>\n<p>Now, let\u2019s continue on the other parts of our repository. In the <code>Contracts<\/code> project,\u00a0there is also\u00a0the <code>IOwnerRepository<\/code> interface with all the synchronous method signatures which we should change too.<\/p>\n<p>So let&#8217;s do that:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"3-5\" data-enlighter-title=\"\">public interface IOwnerRepository : IRepositoryBase&lt;Owner&gt;\r\n{\r\n    Task&lt;IEnumerable&lt;Owner&gt;&gt; GetAllOwnersAsync();\r\n    Task&lt;Owner&gt; GetOwnerByIdAsync(Guid ownerId);\r\n    Task&lt;Owner&gt; GetOwnerWithDetailsAsync(Guid ownerId);\r\n    void CreateOwner(Owner owner);\r\n    void UpdateOwner(Owner owner);\r\n    void DeleteOwner(Owner owner);\r\n}\r\n<\/pre><\/p>\n<p>So, we just change signatures of the first three GET methods by assigning the <code>Task&lt;TResult&gt;<\/code> to the return type. We don&#8217;t have to change the other three methods because, as we said, they just change the state of the entity and wait for the <code>SaveChanges<\/code> to execute.<\/p>\n<p>Now, we have to implement this interface by using the <code>async<\/code> and <code>await<\/code> keywords. Using the <code>await<\/code> keyword is not mandatory though. Of course, if we don\u2019t use it, our async methods will execute synchronously, and that is not our goal here.<\/p>\n<p>So, in accordance with the interface changes, let\u2019s modify our <code>OwnerRepository.cs<\/code> class, that we may find in the <code>Repository<\/code> project:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"8,10,12,15,17-18,21,23,25\" data-enlighter-title=\"\">public class OwnerRepository : RepositoryBase&lt;Owner&gt;, IOwnerRepository \r\n{ \r\n    public OwnerRepository(RepositoryContext repositoryContext) \r\n        : base(repositoryContext) \r\n    { \r\n    }\r\n\r\n    public async Task&lt;IEnumerable&lt;Owner&gt;&gt; GetAllOwnersAsync() \r\n    { \r\n         return await FindAll()\r\n            .OrderBy(ow =&gt; ow.Name)\r\n            .ToListAsync(); \r\n    }\r\n\r\n    public async Task&lt;Owner&gt; GetOwnerByIdAsync(Guid ownerId)\r\n    {\r\n        return await FindByCondition(owner =&gt; owner.Id.Equals(ownerId))\r\n            .FirstOrDefaultAsync();\r\n    }\r\n\r\n    public async Task&lt;Owner&gt; GetOwnerWithDetailsAsync(Guid ownerId)\r\n    {\r\n        return await FindByCondition(owner =&gt; owner.Id.Equals(ownerId))\r\n            .Include(ac =&gt; ac.Accounts)\r\n            .FirstOrDefaultAsync();\r\n    }\r\n\r\n    public void CreateOwner(Owner owner)\r\n    {\r\n        Create(owner);\r\n    }\r\n\r\n    public void UpdateOwner(Owner owner)\r\n    {\r\n        Update(owner);\r\n    }\r\n\r\n    public void DeleteOwner(Owner owner)\r\n    {\r\n        Delete(owner);\r\n    }\r\n}<\/pre><\/p>\n<h2>IRepositoryWrapper and RepositoryWrapper Changes<\/h2>\n<p>We have to modify the Save method in the mentioned interface and the class as well:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"5\" data-enlighter-title=\"\">public interface IRepositoryWrapper \r\n{ \r\n    IOwnerRepository Owner { get; } \r\n    IAccountRepository Account { get; } \r\n    Task SaveAsync(); \r\n}<\/pre><\/p>\n<p>And let&#8217;s just modify the Save method in the RepositoryWrapper class:<\/p>\n<pre  class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\">public async Task SaveAsync() \r\n{\r\n    await _repoContext.SaveChangesAsync();\r\n}<\/pre>\n<p>Now, we can continue to the controller modification.<\/p>\n<h2 id=\"controllermodification\">Controller Modification<\/h2>\n<p>Finally, we need to modify all of our actions in the <code>OwnerController<\/code> to work\u00a0asynchronously.<\/p>\n<p>So, let\u2019s first start with the <strong>GetAllOwners<\/strong> method:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"2,6\" data-enlighter-title=\"\">[HttpGet] \r\npublic async Task&lt;IActionResult&gt; GetAllOwners() \r\n{ \r\n    try \r\n    { \r\n        var owners = await _repository.Owner.GetAllOwnersAsync(); \r\n        _logger.LogInfo($&quot;Returned all owners from database.&quot;);\r\n\r\n        var ownersResult = _mapper.Map&lt;IEnumerable&lt;OwnerDto&gt;&gt;(owners);\r\n        return Ok(ownersResult); \r\n    } \r\n    catch (Exception ex) \r\n    { \r\n        _logger.LogError($&quot;Something went wrong inside GetAllOwners action: {ex.Message}&quot;); \r\n        return StatusCode(500, &quot;Internal server error&quot;); \r\n    } \r\n }\r\n<\/pre><\/p>\n<p>We\u00a0haven&#8217;t changed much in this action. We&#8217;ve just changed the return type and added the async keyword to the method signature. In the method body, we can now await the <code>GetAllOwnersAsync()<\/code> method. And that is pretty much what we should do in\u00a0all the actions in our controller.<\/p>\n<p>So let\u2019s modify all the other actions.<\/p>\n<p><strong>GetOwnerById<\/strong>:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"2,6\" data-enlighter-title=\"\">[HttpGet(&quot;{id}&quot;, Name = &quot;OwnerById&quot;)] \r\npublic async Task&lt;IActionResult&gt; GetOwnerById(Guid id) \r\n{ \r\n    try \r\n    { \r\n        var owner = await _repository.Owner.GetOwnerByIdAsync(id); \r\n        if (owner == null) \r\n        { \r\n            _logger.LogError($&quot;Owner with id: {id}, hasn&#039;t been found in db.&quot;); \r\n            return NotFound(); \r\n        } \r\n        else \r\n        { \r\n            _logger.LogInfo($&quot;Returned owner with id: {id}&quot;);\r\n\r\n            var ownerResult = _mapper.Map&lt;OwnerDto&gt;(owner);\r\n            return Ok(ownerResult); \r\n        } \r\n    } \r\n    catch (Exception ex) \r\n    { \r\n        _logger.LogError($&quot;Something went wrong inside GetOwnerById action: {ex.Message}&quot;); \r\n        return StatusCode(500, &quot;Internal server error&quot;); \r\n    } \r\n}\r\n<\/pre><\/p>\n<p><strong>GetOwnerWithDetails<\/strong>:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"2,6\" data-enlighter-title=\"\">[HttpGet(&quot;{id}\/account&quot;)] \r\npublic async Task&lt;IActionResult&gt; GetOwnerWithDetails(Guid id) \r\n{ \r\n    try \r\n    { \r\n\tvar owner = await _repository.Owner.GetOwnerWithDetailsAsync(id); \r\n\tif (owner == null) \r\n\t{ \r\n\t    _logger.LogError($&quot;Owner with id: {id}, hasn&#039;t been found in db.&quot;); \r\n\t    return NotFound(); \r\n\t} \r\n\telse \r\n\t{ \r\n\t    _logger.LogInfo($&quot;Returned owner with details for id: {id}&quot;);\r\n\r\n\t    var ownerResult = _mapper.Map&lt;OwnerDto&gt;(owner);\r\n\t    return Ok(ownerResult); \r\n\t} \r\n} \r\n    catch (Exception ex) \r\n    { \r\n        _logger.LogError($&quot;Something went wrong inside GetOwnerWithDetails action: {ex.Message}&quot;); \r\n\treturn StatusCode(500, &quot;Internal server error&quot;); \r\n    }\r\n}\r\n<\/pre><\/p>\n<p><strong>CreateOwner<\/strong>:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"2,21\" data-enlighter-title=\"\">[HttpPost]\r\npublic async Task&lt;IActionResult&gt; CreateOwner([FromBody]OwnerForCreationDto owner)\r\n{\r\n    try\r\n    {\r\n\tif (owner == null)\r\n\t{\r\n\t    _logger.LogError(&quot;Owner object sent from client is null.&quot;);\r\n\t    return BadRequest(&quot;Owner object is null&quot;);\r\n\t}\r\n\r\n\tif (!ModelState.IsValid)\r\n\t{\r\n\t    _logger.LogError(&quot;Invalid owner object sent from client.&quot;);\r\n\t    return BadRequest(&quot;Invalid model object&quot;);\r\n\t}\r\n\r\n\tvar ownerEntity = _mapper.Map&lt;Owner&gt;(owner);\r\n\r\n\t_repository.Owner.CreateOwner(ownerEntity);\r\n\tawait _repository.SaveAsync();\r\n\r\n\tvar createdOwner = _mapper.Map&lt;OwnerDto&gt;(ownerEntity);\r\n\r\n\treturn CreatedAtRoute(&quot;OwnerById&quot;, new { id = createdOwner.Id }, createdOwner);\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n    \t_logger.LogError($&quot;Something went wrong inside CreateOwner action: {ex.Message}&quot;);\r\n\treturn StatusCode(500, &quot;Internal server error&quot;);\r\n    }\r\n}<\/pre><\/p>\n<p><strong>UpdateOwner<\/strong>:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"2,18,28\" data-enlighter-title=\"\">[HttpPut(&quot;{id}&quot;)]\r\npublic async Task&lt;IActionResult&gt; UpdateOwner(Guid id, [FromBody]OwnerForUpdateDto owner)\r\n{\r\n    try\r\n    {\r\n        if (owner == null)\r\n\t{\r\n            _logger.LogError(&quot;Owner object sent from client is null.&quot;);\r\n\t    return BadRequest(&quot;Owner object is null&quot;);\r\n\t}\r\n\r\n\tif (!ModelState.IsValid)\r\n\t{\r\n\t    _logger.LogError(&quot;Invalid owner object sent from client.&quot;);\r\n\t    return BadRequest(&quot;Invalid model object&quot;);\r\n\t}\r\n\r\n\tvar ownerEntity = await _repository.Owner.GetOwnerByIdAsync(id);\r\n\tif (ownerEntity == null)\r\n\t{\r\n\t    _logger.LogError($&quot;Owner with id: {id}, hasn&#039;t been found in db.&quot;);\r\n\t    return NotFound();\r\n\t}\r\n\r\n\t_mapper.Map(owner, ownerEntity);\r\n\r\n\t_repository.Owner.UpdateOwner(ownerEntity);\r\n\tawait _repository.SaveAsync();\r\n\r\n\treturn NoContent();\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n  \t_logger.LogError($&quot;Something went wrong inside UpdateOwner action: {ex.Message}&quot;);\r\n\treturn StatusCode(500, &quot;Internal server error&quot;);\r\n    }\r\n}\r\n<\/pre><\/p>\n<p><strong>DeleteOwner<\/strong>:<\/p>\n<p><pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-highlight=\"2,6,20\" data-enlighter-title=\"\">[HttpDelete(&quot;{id}&quot;)]\r\npublic async Task&lt;IActionResult&gt; DeleteOwner(Guid id)\r\n{\r\n    try\r\n    {\r\n        var owner = await _repository.Owner.GetOwnerByIdAsync(id);\r\n        if (owner == null)\r\n        {\r\n            _logger.LogError($&quot;Owner with id: {id}, hasn&#039;t been found in db.&quot;);\r\n            return NotFound();\r\n        }\r\n\r\n        if (_repository.Account.AccountsByOwner(id).Any()) \r\n        {\r\n            _logger.LogError($&quot;Cannot delete owner with id: {id}. It has related accounts. Delete those accounts first&quot;); \r\n            return BadRequest(&quot;Cannot delete owner. It has related accounts. Delete those accounts first&quot;); \r\n        }\r\n\r\n        _repository.Owner.DeleteOwner(owner);\r\n        await _repository.SaveAsync();\r\n\r\n        return NoContent();\r\n    }\r\n    catch (Exception ex)\r\n    {\r\n        _logger.LogError($&quot;Something went wrong inside DeleteOwner action: {ex.Message}&quot;);\r\n        return StatusCode(500, &quot;Internal server error&quot;);\r\n    }\r\n}\r\n<\/pre><\/p>\n<p>Excellent. Now we are talking async \ud83d\ude00<\/p>\n<p>We can make our actions even more maintainable and readable by implementing <a href=\"https:\/\/code-maze.com\/global-error-handling-aspnetcore\/\" target=\"_blank\" rel=\"noopener noreferrer\">Global Error Handling<\/a> to remove try-catch blocks and <a href=\"https:\/\/code-maze.com\/action-filters-aspnetcore\/\" target=\"_blank\" rel=\"noopener noreferrer\">Action Filters<\/a> as well to remove validation code repetitions.<\/p>\n<p>Also, in this article, we are not using the service layer because we didn&#8217;t want to make things more complicated for this small project. But if you want to use it in your projects, which we strongly recommend, please read <a href=\"https:\/\/code-maze.com\/onion-architecture-in-aspnetcore\/\" target=\"_blank\" rel=\"noopener\">our Onion Architecture article<\/a> to see how it should be done.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>There you go. We have seen how easy is to convert the synchronous repository to asynchronous and how easy is to write async code overall. With a couple of changes, we gave more breathing space to our API and created a more responsive application.<\/p>\n<p>It is a good practice to write async methods (when we have an opportunity) that handles the I\/O actions because it is easy to write those methods and the benefits are indisputable.<\/p>\n<p>Thank you for reading the article and\u00a0we hope you found something useful in it.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, we are going to convert the synchronous code to asynchronous inside ASP.NET Core. First, we are going to learn a bit about asynchronous programming and why should we write async code. Then we are going to use our project from the .NET Core series and rewrite it in an async manner. In [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":54964,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_et_pb_use_builder":"","_et_pb_old_content":"","_et_gb_content_width":"","footnotes":""},"categories":[12],"tags":[22,160,159,158,161,50,162,130],"class_list":["post-3339","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-csharp","tag-net-core","tag-async","tag-async-programming","tag-asynchronous","tag-await","tag-repository-pattern","tag-task","tag-web-api","et-has-post-format-content","et_post_format-et-post-format-standard"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.7 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Asynchronous Generic Repository in ASP.NET Core Web API - Code Maze<\/title>\n<meta name=\"description\" content=\"In this post, we are going to convert an existing Generic Repository Pattern implemented in ASP.NET Core to an asynchronous one.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Asynchronous Generic Repository in ASP.NET Core Web API - Code Maze\" \/>\n<meta property=\"og:description\" content=\"In this post, we are going to convert an existing Generic Repository Pattern implemented in ASP.NET Core to an asynchronous one.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\" \/>\n<meta property=\"og:site_name\" content=\"Code Maze\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-25T06:30:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-07-26T07:44:49+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1100\" \/>\n\t<meta property=\"og:image:height\" content=\"620\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Marinko Spasojevi\u0107\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/CodeMazeBlog\" \/>\n<meta name=\"twitter:site\" content=\"@CodeMazeBlog\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Marinko Spasojevi\u0107\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":[\"Article\",\"BlogPosting\"],\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\"},\"author\":{\"name\":\"Marinko Spasojevi\u0107\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\"},\"headline\":\"Implementing Asynchronous Generic Repository in ASP.NET Core\",\"datePublished\":\"2018-06-25T06:30:11+00:00\",\"dateModified\":\"2021-07-26T07:44:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\"},\"wordCount\":1422,\"commentCount\":64,\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png\",\"keywords\":[\".NET CORE\",\"async\",\"Async programming\",\"Asynchronous\",\"await\",\"repository pattern\",\"Task\",\"Web API\"],\"articleSection\":[\"C#\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\",\"url\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\",\"name\":\"Asynchronous Generic Repository in ASP.NET Core Web API - Code Maze\",\"isPartOf\":{\"@id\":\"https:\/\/code-maze.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png\",\"datePublished\":\"2018-06-25T06:30:11+00:00\",\"dateModified\":\"2021-07-26T07:44:49+00:00\",\"description\":\"In this post, we are going to convert an existing Generic Repository Pattern implemented in ASP.NET Core to an asynchronous one.\",\"breadcrumb\":{\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/code-maze.com\/async-generic-repository-pattern\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png\",\"width\":1100,\"height\":620,\"caption\":\"generic repository\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/code-maze.com\/async-generic-repository-pattern\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/code-maze.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Implementing Asynchronous Generic Repository in ASP.NET Core\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/code-maze.com\/#website\",\"url\":\"https:\/\/code-maze.com\/\",\"name\":\"Code Maze\",\"description\":\"Learn. Code. Succeed.\",\"publisher\":{\"@id\":\"https:\/\/code-maze.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/code-maze.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/code-maze.com\/#organization\",\"name\":\"Code Maze\",\"url\":\"https:\/\/code-maze.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png\",\"width\":3511,\"height\":3510,\"caption\":\"Code Maze\"},\"image\":{\"@id\":\"https:\/\/code-maze.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/CodeMazeBlog\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533\",\"name\":\"Marinko Spasojevi\u0107\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/code-maze.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"contentUrl\":\"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg\",\"caption\":\"Marinko Spasojevi\u0107\"},\"description\":\"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/\",\"https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog\"],\"url\":\"https:\/\/code-maze.com\/author\/marinko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Asynchronous Generic Repository in ASP.NET Core Web API - Code Maze","description":"In this post, we are going to convert an existing Generic Repository Pattern implemented in ASP.NET Core to an asynchronous one.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/code-maze.com\/async-generic-repository-pattern\/","og_locale":"en_US","og_type":"article","og_title":"Asynchronous Generic Repository in ASP.NET Core Web API - Code Maze","og_description":"In this post, we are going to convert an existing Generic Repository Pattern implemented in ASP.NET Core to an asynchronous one.","og_url":"https:\/\/code-maze.com\/async-generic-repository-pattern\/","og_site_name":"Code Maze","article_published_time":"2018-06-25T06:30:11+00:00","article_modified_time":"2021-07-26T07:44:49+00:00","og_image":[{"width":1100,"height":620,"url":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png","type":"image\/png"}],"author":"Marinko Spasojevi\u0107","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/CodeMazeBlog","twitter_site":"@CodeMazeBlog","twitter_misc":{"Written by":"Marinko Spasojevi\u0107","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":["Article","BlogPosting"],"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#article","isPartOf":{"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/"},"author":{"name":"Marinko Spasojevi\u0107","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533"},"headline":"Implementing Asynchronous Generic Repository in ASP.NET Core","datePublished":"2018-06-25T06:30:11+00:00","dateModified":"2021-07-26T07:44:49+00:00","mainEntityOfPage":{"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/"},"wordCount":1422,"commentCount":64,"publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"image":{"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png","keywords":[".NET CORE","async","Async programming","Asynchronous","await","repository pattern","Task","Web API"],"articleSection":["C#"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/code-maze.com\/async-generic-repository-pattern\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/","url":"https:\/\/code-maze.com\/async-generic-repository-pattern\/","name":"Asynchronous Generic Repository in ASP.NET Core Web API - Code Maze","isPartOf":{"@id":"https:\/\/code-maze.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage"},"image":{"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage"},"thumbnailUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png","datePublished":"2018-06-25T06:30:11+00:00","dateModified":"2021-07-26T07:44:49+00:00","description":"In this post, we are going to convert an existing Generic Repository Pattern implemented in ASP.NET Core to an asynchronous one.","breadcrumb":{"@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/code-maze.com\/async-generic-repository-pattern\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#primaryimage","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2018\/06\/generic-repository.png","width":1100,"height":620,"caption":"generic repository"},{"@type":"BreadcrumbList","@id":"https:\/\/code-maze.com\/async-generic-repository-pattern\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/code-maze.com\/"},{"@type":"ListItem","position":2,"name":"Implementing Asynchronous Generic Repository in ASP.NET Core"}]},{"@type":"WebSite","@id":"https:\/\/code-maze.com\/#website","url":"https:\/\/code-maze.com\/","name":"Code Maze","description":"Learn. Code. Succeed.","publisher":{"@id":"https:\/\/code-maze.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/code-maze.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/code-maze.com\/#organization","name":"Code Maze","url":"https:\/\/code-maze.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/Code-Maze-Only-Logo-Transparent-HRez.png","width":3511,"height":3510,"caption":"Code Maze"},"image":{"@id":"https:\/\/code-maze.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/CodeMazeBlog"]},{"@type":"Person","@id":"https:\/\/code-maze.com\/#\/schema\/person\/d6fa06e66820968d19b39fb63cff2533","name":"Marinko Spasojevi\u0107","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/code-maze.com\/#\/schema\/person\/image\/","url":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","contentUrl":"https:\/\/code-maze.com\/wp-content\/uploads\/2020\/01\/marinko-1x1-3-150x150.jpg","caption":"Marinko Spasojevi\u0107"},"description":"Hi, my name is Marinko Spasojevic. Currently, I work as a full-time .NET developer and my passion is web application development. Just getting something to work is not enough for me. To make it just how I like it, it must be readable, reusable, and easy to maintain. Prior to being an author on the CodeMaze blog, I had been working as a professor of Computer Science for several years. So, sharing knowledge while working as a full-time developer comes naturally to me.","sameAs":["https:\/\/www.linkedin.com\/in\/marinko-spasojevic\/","https:\/\/x.com\/https:\/\/twitter.com\/CodeMazeBlog"],"url":"https:\/\/code-maze.com\/author\/marinko\/"}]}},"_links":{"self":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/3339","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/comments?post=3339"}],"version-history":[{"count":2,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/3339\/revisions"}],"predecessor-version":[{"id":58895,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/posts\/3339\/revisions\/58895"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media\/54964"}],"wp:attachment":[{"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/media?parent=3339"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/categories?post=3339"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code-maze.com\/wp-json\/wp\/v2\/tags?post=3339"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}