Defining the repository pattern and unit of work

Before we start, we need to define some interfaces in the Catalog.Domain project. Let's proceed by setting a generic interface to determine the unit of work of our repository:

using System;
using System.Threading;
using System.Threading.Tasks;

namespace Catalog.Domain.Repositories
{
public interface IUnitOfWork : IDisposable
{
Task<int> SaveChangesAsync(CancellationToken cancellationToken =
default(CancellationToken));
Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken =
default(CancellationToken));
}
}

IUnitOfWork defines two methods: SaveChangesAsync and SaveEntitiesAsync. These two methods are used to save changes in our collection to the database effectively. These methods are both asynchronous: they return a Task type and they accept a CancellationToken type as a parameter. The CancellationToken parameter provides a way to stop pending asynchronous operations.

In some cases, the repository pattern is implemented in such a way that, when you update or create new elements in a collection, those changes are automatically saved to the database. I prefer to keep the effective saving operation separate from the reading and writing part. This can be achieved using the unit of work approach. Therefore, the repository allows the higher layers to perform get, create, and update operations on the memory collection, while the unit of work implements a way to transfer those changes to the database.

Let's proceed by defining an IRepository interface at the same folder level as the IUnitOfWork interface defined previously:

namespace Catalog.Domain.Repositories
{
public interface IRepository
{
IUnitOfWork UnitOfWork { get; }
}
}

As you can see, IRepository does not implicitly use the IUnitOfWork interface. Additionally, it exposes the UnitOfWork instance as a property of the class. This approach guarantees that all the consumers of the IRepository interface must explicitly update the database by calling the SaveChangesAsync or SaveEntitiesAsync methods. 

The final step is to define the IItemRepository interface, as follows:

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Catalog.Domain.Entities;

namespace Catalog.Domain.Repositories
{
public interface IItemRepository : IRepository
{
Task<IEnumerable<Item>> GetAsync();
Task<Item> GetAsync(Guid id);
Item Add(Item item);
Item Update(Item item);
}
}

The interface extends the IRepository class and refers to the Item entity that was defined previously. IItemRepository defines reading and writing operations over our data source. You may notice that the Add, Update. This is because they only act on the collection stored in the memory of the application, and the effective saving operation is performed by the unit of work.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.27.232