ATech.Repository 2.0.4

dotnet add package ATech.Repository --version 2.0.4                
NuGet\Install-Package ATech.Repository -Version 2.0.4                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ATech.Repository" Version="2.0.4" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add ATech.Repository --version 2.0.4                
#r "nuget: ATech.Repository, 2.0.4"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install ATech.Repository as a Cake Addin
#addin nuget:?package=ATech.Repository&version=2.0.4

// Install ATech.Repository as a Cake Tool
#tool nuget:?package=ATech.Repository&version=2.0.4                

ATech.Repository

Developing modern applications frequently requires some kind of data handling. Whether the application is sized to fit the resources of a tiny microcontroller to collect some IoT data, or implements a more sophisticated microservice or a big enterprise business application, it will always require some kind of data storage or retrieval, in other words, needs some CRUD operations. Achieving such a goal is possible in many ways. We can interact with the data storage (whether it's a database or not) directly with a dedicated controller, ORM or Micro ORM, or we can use a dedicated layer to abstract data access from the implementation logic implementing a Repository Pattern.

As stated by Martin Fowler a Repository Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects, The repository should look like an in-memory collection and should have generic methods like Add, Remove or FindById. With such generic methods, the repository can be easily reused in different applications.

Repository Pattern

This project is my own interpretation of this particular design pattern resumes many of the articles I've read on the subject, and it's available as a set of nuget packages https://www.nuget.org/packages?q=ATech.Repository

ATech.Repository.EntityFrameworkCore

The natural solution for relational databases integration in a .NET Core application is, without any doubt, Entity Framework Core.

Like everything, EF core also has its strengths and weaknesses. It is certainly not the lightest of the solutions available nor the fastest, but the possibility of adopting a code first approach is for me a plus in the early stages of a project, allowing to focus on the architectural aspects of the solution.

The EF Core version of this pattern is used in ATech.ContactFormServer service in which the Domain project contains the interfaces of two concrete POCO classes, while the Infrastructure project contains the Implementations.

References

ATech.Repository.Dapper

Remaining in the field of relational databases, Dapper is one of the undisputed protagonists in the dotnet community. It's lightweight, it's much faster than EF Core (at least in reading operations), but in my opinion, using it as it comes has an unacceptable cost. Writing SQL statements directly into code even for simple operations will significantly slow down the development phase. This is my attempt to implement the repository model and add some layers of abstraction to this remarkable tool.

Mimicking EF Core, I assumed that each entity class has a corresponding table with the same name in the database and, for simplicity (perhaps oversimplified), that each table has a primary key column named Id.

The core of the repository implementation consists of a number of IDbConnection extension methods, contained in DapperExtensions.cs file, each of which creates and executes a corresponding parameterized SQL query.

    /// <summary>
    /// Generic asynchronous Read extension method
    /// </summary>        
    /// <param name="id">Unique id</param>        
    /// <returns>The item corresponding to the given id if exists</returns>
    public static async Task<TEntity> GetAsync<TEntity>(this IDbConnection connection, int id,      CancellationToken cancellationToken)
            => await connection.QuerySingleOrDefaultAsync<TEntity>($"SELECT * FROM {typeof(TEntity).Name} WHERE Id=@Id", new { Id = id });

An example of how the use of the class is contained in the ATech.Repository.Test project. it's made up of three domain entities (POCO Classes), each with its concrete repository interface and implementation. As it almost always happens repositories comes with unit of work that, as stated by Martin Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

            var unitOfWork = new IoTDataMartDbUnitOfWork(ref connection);

            var rows = await unitOfWork
                .PhysicalDimensions
                .GetAllAsync(default)
                .ConfigureAwait(false);

            unitOfWork
                .PhysicalDimensions
                .RemoveRange(rows);

            // Count the rows before Create operation
            var before = unitOfWork
                .PhysicalDimensions
                .Count();

            // Adds a new row
            unitOfWork
                .PhysicalDimensions
                .Add(new Entities.PhysicalDimension
                {
                    Name = "Humidity",
                    Scale = "%",
                    Created = DateTime.UtcNow,
                    CreatedBy = "atech"
                });

            var after = unitOfWork
                .PhysicalDimensions
                .Count();

            Assert.True(after == before + 1);

            rows = await unitOfWork
                   .PhysicalDimensions
                   .GetAllAsync(default)
                   .ConfigureAwait(false);

            var row = rows.ToArray()[0];

            var retrieved = await unitOfWork
                .PhysicalDimensions
                .GetAsync(row.Id, default)
                .ConfigureAwait(false);

            retrieved.Name = "Humidity0123";

            await unitOfWork
                .PhysicalDimensions
                .UpdateAsync(retrieved, default)
                .ConfigureAwait(false);

            var dimension = unitOfWork.PhysicalDimensions.Find(d => d.Name.ToLower() == "humidity0123").FirstOrDefault();

            Assert.True((dimension != null) && (dimension.Name == "Humidity0123"));

            rows = await unitOfWork
                   .PhysicalDimensions
                   .GetAllAsync(default)
                   .ConfigureAwait(false);

            foreach (var r in rows)
            {
                unitOfWork
                   .PhysicalDimensions
                   .Remove(r);
            }

            after = unitOfWork
                    .PhysicalDimensions
                    .Count();

            Assert.True(after == 0);

References

Releases

  • 2.0.0.0 - 2.0 package refactoring
  • 1.3.0.0 - Migration to .NET 8
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on ATech.Repository:

Package Downloads
ATech.Repository.EntityFrameworkCore

Entity framework core implementation for the repository pattern

ATech.Repository.Dapper

Dapper implementation for the repository pattern

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
2.0.4 132 9/13/2024
2.0.3 130 9/4/2024
2.0.2.1 104 9/4/2024
2.0.2 129 5/4/2024
2.0.1 114 4/25/2024
2.0.0.1 119 4/25/2024
2.0.0 120 4/25/2024
1.3.0 147 3/6/2024
1.2.0 308 2/14/2023
1.1.0 567 11/12/2021
1.0.4.2 781 5/10/2021
1.0.3 431 4/24/2021
1.0.2.1 419 1/31/2021
1.0.2 570 9/9/2020
1.0.1 534 9/9/2020
1.0.0 724 9/9/2020

GetAll methods fix