<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Brandon Tillman</title>
    <description>The latest articles on DEV Community by Brandon Tillman (@tillman32).</description>
    <link>https://dev.to/tillman32</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%2F177518%2Fbe4d790d-fd07-482d-8276-82dfcd3088bc.jpeg</url>
      <title>DEV Community: Brandon Tillman</title>
      <link>https://dev.to/tillman32</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tillman32"/>
    <language>en</language>
    <item>
      <title>Clean Architecture | Creating Maintainable Software using .NET Core</title>
      <dc:creator>Brandon Tillman</dc:creator>
      <pubDate>Thu, 02 May 2019 09:00:57 +0000</pubDate>
      <link>https://dev.to/tillman32/clean-architecture-creating-maintainable-software-using-net-core-5al6</link>
      <guid>https://dev.to/tillman32/clean-architecture-creating-maintainable-software-using-net-core-5al6</guid>
      <description>&lt;h3&gt;
  
  
  &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rf25UgJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.brandontillman.com/wp-content/uploads/2018/05/CleanArchitectureScreenShot-600x468.png" width="600" height="468"&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Intro
&lt;/h3&gt;

&lt;p&gt;This is one of my favorite topics as of late – Clean Architecture, the Do’s and Don’ts and how to write awesome software. At some point in your software development career, you’ll want to start taking things to the next level. That one liner might not be as magical anymore; or maybe you’re hazed from maintaining a production application, where its source is all in one file.&lt;/p&gt;

&lt;p&gt;Either way, you’ve seen 1000’s of tutorials on how to write MVC applications, Web API’s and more; but most of them focus on teaching the framework/tooling and not the big picture. You’re left wondering how it all pieces together cleanly, in a way that you would actually want to bring it back to the workplace and share with your colleagues. If this sounds like you, then you’ve come to the right place.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bob Ross
&lt;/h3&gt;

&lt;p&gt;Who could be better to showcase clean software architecture, other than Bob Ross? It’s all about drawing lines, and trying not to make mistakes… but if you do, make the best of them!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We don’t make mistakes, just happy little accidents&lt;/em&gt; – &lt;strong&gt;Bob Ross&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Project
&lt;/h3&gt;

&lt;p&gt;Introducing my latest open source example project, Clean Architecture! It can be found on &lt;a href="https://github.com/Tillman32/CleanArchitecture" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and its also hosted for you to test out live &lt;a href="https://cleanarchitecture.brandontillman.com" rel="noopener noreferrer"&gt;right here.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clean Architecture, is an example project to showcase how you would piece together different layers in a small, medium and even large sized application. It makes an attempt to adhere to recommended software architecture principles, such as &lt;a href="https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design" rel="noopener noreferrer"&gt;DDD&lt;/a&gt;. You’ll notice the application is split into a classic 3 Tier, &lt;a href="https://en.wikipedia.org/wiki/Multitier_architecture" rel="noopener noreferrer"&gt;Multi-Layer application&lt;/a&gt; which draws the lines between each major component of the application.&lt;/p&gt;

&lt;p&gt;Rather than a task list, or to-do application, I went with a simple blog example. In the app, you can view a list of article excerpts, read the full article, and even create new articles… with images and categories.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;

&lt;p&gt;The application features 3 layers – &lt;strong&gt;ClientWeb&lt;/strong&gt; , a Razor Pages web application, &lt;strong&gt;Core&lt;/strong&gt;  contains the business logic, all the models and interfaces. Lastly,  *&lt;em&gt;Infrastructure *&lt;/em&gt; is our &lt;a href="https://en.wikipedia.org/wiki/Object-relational_mapping" rel="noopener noreferrer"&gt;ORM&lt;/a&gt; and Logging implementations.&lt;/p&gt;

&lt;p&gt;Below is the overall structure of the application:&lt;br&gt;&lt;br&gt;
 &lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zvy81s92ukx7q06xkae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zvy81s92ukx7q06xkae.png" width="479" height="552"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Data Flow
&lt;/h3&gt;

&lt;p&gt;Like most examples you see online, the database implementation and classes are mixed together with the rest of the business logic. This violates the &lt;a href="https://en.wikipedia.org/wiki/Single_responsibility_principle" rel="noopener noreferrer"&gt;Single Responsibility Principle&lt;/a&gt; and should be moved into its own project.&lt;/p&gt;

&lt;p&gt;Another issue with the example style approach, is that the database models are used in the UI and services – this can cause issues when you want change the database schema, or even the UI. Instead, utilize View Models, DTO, and Entity objects. This way both the UI and the data layer can be changed independently from each other, they are no longer tightly coupled.&lt;/p&gt;

&lt;p&gt;I find this part initially leaves people feeling like it’s a lot of extra work, and they don’t want to have multiple classes for a single object, etc. I get it, however it comes with great benefits that should be considered. Having the models compartmentalized into their respective use cases will simplify the code and allow for greater flexibility in the long run.&lt;/p&gt;
&lt;h3&gt;
  
  
  Mapping
&lt;/h3&gt;

&lt;p&gt;To make mapping between our various models a breeze, &lt;a href="https://automapper.org/" rel="noopener noreferrer"&gt;AutoMapper&lt;/a&gt; was added to the application. AutoMapper uses reflection to map values from one object to another, without having to know each property beforehand. This saves me from otherwise writing a ton of boilerplate code, mapping our entities to our DTO’s.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependency Injection and IoC
&lt;/h3&gt;

&lt;p&gt;Every single dependency is injected via constructor injection. This means, every single dependency has its life cycle managed by the framework, and can be swapped out with test/mock versions. The application is now decoupled and inherently more flexible.&lt;/p&gt;

&lt;p&gt;Combining this with the use of interfaces, I can define the inputs and outputs of the application. With this amount of control, I am able to swap out entire implementations without affecting the rest of the code base. The application’s maintainability has now increased two fold.&lt;/p&gt;

&lt;p&gt;I’m making use of the built-in dependency injection container, provided by &lt;code&gt;Microsoft.Extensions.DependencyInjection&lt;/code&gt;. Dependencies and their life cycle are managed by the framework and defined in the Startup.cs class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// Repositories&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleCategoryEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleCategoryEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Services&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IArticleService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ArticleService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddScoped&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IArticleCategoryService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ArticleCategoryService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Code omitted for brevity &lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The IServiceCollection.AddScoped() method call creates a dependency with a “scoped” lifecycle. This means the object gets created a reused for each request made within that session. The interface is defined followed by the concrete implementation doing the actual heavy lifting. More information about this particular topic can be found &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constructor Injection
&lt;/h3&gt;

&lt;p&gt;Consumers then simply utilize constructor injection; the dependencies are passed in through the parameters and mapped to private readonly variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ArticleService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IArticleService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IHostingEnvironment&lt;/span&gt; &lt;span class="n"&gt;_hostingEnvironment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IMapper&lt;/span&gt; &lt;span class="n"&gt;_mapper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_logger&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;ArticleService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;IHostingEnvironment&lt;/span&gt; &lt;span class="n"&gt;hostingEnvironment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IMapper&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ILogger&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ArticleService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_hostingEnvironment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hostingEnvironment&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_mapper&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mapper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logger&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;
  
  
  Generic Repository
&lt;/h3&gt;

&lt;p&gt;The repository is meant to draw a line, and decouple the database implementation (EF Core) from the applications business logic. By doing so, I can freely “swap” the data store mechanism. In fact, I could build the entire application without a database and use flat file storage if I wanted to – it’s now completely “pluggable”. The point being that the application should not care how data is retrieved or stored. By mixing the database implementation details, I would be creating what is called a &lt;a href="https://en.wikipedia.org/wiki/Leaky_abstraction" rel="noopener noreferrer"&gt;“Leaky Abstraction”&lt;/a&gt; – tightly coupling the application to the database once again. A great example of a real life scenario, would be software that allows you to choose your own database implementation when you install it.&lt;/p&gt;

&lt;p&gt;The repository also has a generic interface, with a generic implementation. By doing so, I no longer have to create a repository for each entity. Duplicate code is also avoided by having one set of CRUD operations against the dataset. Let me show you what I mean by that – lets first have a closer look at how I implemented the database.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;IGenericRepository&lt;/code&gt; resides in the &lt;code&gt;CleanArchitecture.Core&lt;/code&gt; project, the central business logic that does not rely on any other project within the solution. This interface defines the input and output of how data flows to/from the application’s core layer. I implement this interface in the &lt;code&gt;GenericRepository&lt;/code&gt; class within the &lt;code&gt;CleanArchitecture.Infrastructure&lt;/code&gt; project. Outlined below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;IDisposable&lt;/span&gt;
    &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;IEntity&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;ApplicationDbContext&lt;/span&gt; &lt;span class="n"&gt;_dbContext&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;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ApplicationDbContext&lt;/span&gt; &lt;span class="n"&gt;dbContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_dbContext&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dbContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Returns Queryable interface for retrieving all entities.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetAll&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;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Returns a single entity by Id.&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;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetById&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;id&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="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AsNoTracking&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefaultAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Inserts an entity.&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="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&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;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;AddAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&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;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Updates an entity.&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="nf"&gt;Update&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;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;Update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&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;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Deletes an entity.&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="nf"&gt;Delete&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;id&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;entity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TEntity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&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;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SaveChangesAsync&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="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Dispose&lt;/span&gt;&lt;span class="p"&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;_dbContext&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;_dbContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Dispose&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;p&gt;This one class now handles all Create, Read, Update, Delete (CRUD) operations against our dataset. Without this, I would need a repository for each entity/table I intend to utilize – the benefits scale! This is extremely powerful stuff.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibtqfrud04axa1tjz9db.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibtqfrud04axa1tjz9db.jpg" width="620" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging
&lt;/h3&gt;

&lt;p&gt;Logging is even decoupled from the application, and pluggable for all the same reasons. Right now it uses &lt;a href="https://nlog-project.org/" rel="noopener noreferrer"&gt;NLog&lt;/a&gt; for its implementation, but I could easily add another specialized logger or switch entirely.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;I had a blast working on this, and have already used it as a base for other new projects. There is no reason to start from “File -&amp;gt; New” every time, and I encourage you to do yourself a favor – build your base toolset. I also hope you learned something new about clean architecture, I know I did while making this. I’m going to continue to add features that belong in a base project as necessary, so &lt;strong&gt;make sure to watch/star the &lt;a href="https://github.com/Tillman32/CleanArchitecture" rel="noopener noreferrer"&gt;project on github&lt;/a&gt; for updates.&lt;/strong&gt; Even feel free to suggest your own!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Talent is a pursued interest. Anything that you’re willing to practice, you can do&lt;/em&gt; – &lt;strong&gt;Bob Ross&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thank you for reading! Please feel free to reach out with any questions, or just to say hi! &lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3weqd4n5mfl7oao2qrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn3weqd4n5mfl7oao2qrw.png" alt="🙂" width="72" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.brandontillman.com/clean-architecture-dot-net-core/" rel="noopener noreferrer"&gt;Clean Architecture | Creating Maintainable Software using .NET Core&lt;/a&gt; appeared first on &lt;a href="https://www.brandontillman.com" rel="noopener noreferrer"&gt;Brandon Tillman&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>aspnetcore</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
