AuxiliaryLibraries.GenericRepository.Core
1.0.3
See the version list below for details.
dotnet add package AuxiliaryLibraries.GenericRepository.Core --version 1.0.3
NuGet\Install-Package AuxiliaryLibraries.GenericRepository.Core -Version 1.0.3
<PackageReference Include="AuxiliaryLibraries.GenericRepository.Core" Version="1.0.3" />
paket add AuxiliaryLibraries.GenericRepository.Core --version 1.0.3
#r "nuget: AuxiliaryLibraries.GenericRepository.Core, 1.0.3"
// Install AuxiliaryLibraries.GenericRepository.Core as a Cake Addin #addin nuget:?package=AuxiliaryLibraries.GenericRepository.Core&version=1.0.3 // Install AuxiliaryLibraries.GenericRepository.Core as a Cake Tool #tool nuget:?package=AuxiliaryLibraries.GenericRepository.Core&version=1.0.3
There might be no project that doesn't need this library. With the help of this library you are able to get rid of implementing CRUD operations for all of you entities. You should just configure a few lines for every enity and that's it, you have implemented all of CRUD operations along with lots of other useful functions.
Besides, as this library use AuxiliaryLibraries.CacheManager, if you configure CacheManager, you will access a very handy feature which is caching with no extra effort.
This use generic repository and unit of work design patterns for implementing all of its functions. Furtheremore, CacheManager uses Redis.
Table of Contents
- About The Library
- How it works
- How to use
- What do you have now
- Easy Peasy caching
- Configuration
About The Library
This library helps you to implement your projects faster than usual, becuase you can focus on implementing logic of your project and leave the Data Access Layar to this library. You have to do a few steps as describes below. EntityFramewok Core is used in this library and if you choose another types of ORM this library might not usefull fore you.
How it works
There are a few base classes inside the library, you should create one interface and one repository class fr each entity, and inherit them from those base classes. If you need to change the functionality of any of default functions, you can simply override them. Or you can add any other functionality to your repositorties. After that you must register your classes to your IOC container.
How to use
Lets imagine we have one entity. In real projects yo will have more than that. Do these steps for all of them.
Table - Entity
public partial class Currency
{
public long Id { get; set; }
public string Title { get; set; } = null!;
public string Abbreviation { get; set; } = null!;
public DateTime CreateDate { get; set; }
public DateTime LastModifiedDate { get; set; }
}
Repository
Now you should create one interface and one Repository class as follows:
Currency Repository Interface
There is a base interface called IRepository. Create an interface and inherit it from IRepository<TEntity>:
public interface ICurrencyRepository : IRepository<Currency>
{
// For default you do not need to add anything here.
}
Currency Repository
There is a base interface called Repository. Create a class and inherit it from Repository<TEntity> and ICurrencyRepository:
public class CurrencyRepository : Repository<Currency>, ICurrencyRepository
{
// TestDbContext is the name of your DbContext, Replace it with your own DbContext name
private TestDbContext TestDbContext => Context as TestDbContext;
public CurrencyRepository(TestDbContext context, ICacheService cacheService) : base(context, cacheService)
{
// For default you do not need to add anything here.
}
}
If you need to add any other functionality to your repositoreis you can do like this
Currency Repository Interface
public interface ICurrencyRepository : IRepository<Currency>
{
Task<Currency> GetLastSourceAsync(bool setCache = false);
}
Currency Repository
public class CurrencyRepository : Repository<Currency>, ICurrencyRepository
{
// TestDbContext is the name of your DbContext, Replace it with your own DbContext name
private TestDbContext TestDbContext => Context as TestDbContext;
public CurrencyRepository(TestDbContext context, ICacheService cacheService) : base(context, cacheService)
{
public virtual async Task<Currency> GetLastSourceAsync(bool setCache = false)
{
var cacheKey = CacheConventions.Cachekey<Currency>(id: 1, baseKey: "Last");
if (!CacheService.TryGet(cacheKey, out Currency cachedItem))
{
cachedItem = await TestDbContext.Currencies.OrderByDescending(x => x.CreateDate).FirstOrDefaultAsync(x => !string.IsNullOrEmpty(x.Title));
if (setCache && cachedItem != null)
CacheService.Set(cacheKey, cachedItem);
}
return cachedItem;
}
}
}
UnitOfWork
Now it's time to have UnitOfWork. Create an interface and a class for UnitOfWork
IUnitOfWork
There is a base interface called IUnitOfWork. Create an interface and inherit it from that IUnitOfWork. Then you have to add all of your repositories here inside this interface just like below:
public interface ITestUnitOfWork : IUnitOfWork
{
ICurrencyRepository Currencies { get; }
}
UnitOfWork
There is a base class called UnitOfWork. Create a class and inherit it from that UnitOfWork and ITestUnitOfWork. Then you have to decorate your class as follows and add all of your repositories here inside this class just like below:
public class TestUnitOfWork : UnitOfWork, ITestUnitOfWork
{
private TestDbContext TestDbContext => Context as TestDbContext;
public TestUnitOfWork
(
TestDbContext context,
ICacheService cacheService,
ICurrencyRepository currencyRepository
) : base(context, cacheService)
{
Currencies = currencyRepository;
}
public ICurrencyRepository Currencies { get; set; }
}
What do you have now
Almost Done. There is only a few configurations left. But before that lets desscuss what do you have now. Imagine we have a service called CurrencyService and we have these functionality including many others insise the service.
public class CurrencyService : ICurrencyService
{
private readonly ITestUnitOfWork _unitOfWork;
public CurrencyService(ITestUnitOfWork testUnitOfWork)
{
this._unitOfWork = testUnitOfWork;
}
public async ValueTask Get()
{
// Getting first row of table
var data1 = await _unitOfWork.Currencies.FirstAsync();
// Getting first row of table with specifications, and set cache as true
var data1 = await _unitOfWork.Currencies.FirstAsync(predicate: x => x.CreateDate > DateTime.Now,
orderBy: x => x.OrderByDescending(o => o.CreateDate),
setCache: true,
asNoTracking: AsNoTrackingType.AsNoTracking);
// Getting first row of table
var data2 = await _unitOfWork.Currencies.FirstOrDefaultAsync();
// Getting first row of table with specifications, and set cache as true
var data2 = await _unitOfWork.Currencies.FirstOrDefaultAsync(predicate: x => x.CreateDate > DateTime.Now,
orderBy: x => x.OrderByDescending(o => o.CreateDate),
setCache: true,
asNoTracking: AsNoTrackingType.AsNoTrackingWithIdentityResolution);
// Getting last row of table
var data3 = await _unitOfWork.Currencies.LastAsync();
// Getting last row of table with specifications, and set cache as true
var data4 = await _unitOfWork.Currencies.LastOrDefaultAsync(predicate: x => x.CreateDate > DateTime.Now,
orderBy: x => x.OrderByDescending(o => o.CreateDate),
setCache: true,
asNoTracking: AsNoTrackingType.None);
// Selecting/Searching throughout the table
var data5 = await _unitOfWork.Currencies.FindAsync(predicate: x => x.CreateDate > DateTime.Now,
orderBy: x => x.OrderByDescending(o => o.CreateDate),
setCache: true,
page: 1, pageSize: 100,
asNoTracking: AsNoTrackingType.AsNoTracking);
// Get a row with the id of 12 => Id can be any DATA TYPE
var data6 = await _unitOfWork.Currencies.GetAsync(12, setCache: true);
// Get all data of a table
var data7 = await _unitOfWork.Currencies.GetAllAsync(setCache: true, asNoTracking: AsNoTrackingType.AsNoTracking);
// Get maximum value
var data8 = await _unitOfWork.Currencies.MaxAsync(x => x.Rate, setCache: true);
// Get maximum value according to the predicate
var data8 = await _unitOfWork.Currencies.MaxAsync(predicate: x => x.CreateDate > DateTime.Now, selector: x => x.Rate, setCache: true);
// Get minimum value
var data9 = await _unitOfWork.Currencies.MinAsync(x => x.Rate, setCache: true);
// Get minimum value according to the predicate
var data9 = await _unitOfWork.Currencies.MinAsync(predicate: x => x.CreateDate > DateTime.Now, selector: x => x.Rate, setCache: true);
// Get Sum of values
var data10 = await _unitOfWork.Currencies.SumAsync(predicate: x => x.CreateDate > DateTime.Now, selector: x => x.Rate, setCache: true);
// Get Sum of values
var data11 = await _unitOfWork.Currencies.CountAsync();
// Get Sum of values according to the predicate
var data11 = await _unitOfWork.Currencies.CountAsync(predicate: x => x.CreateDate > DateTime.Now, selector: x => x.Rate, setCache: true);
// Get Average of values
var data12 = await _unitOfWork.Currencies.AverageAsync(predicate: x => x.CreateDate > DateTime.Now, selector: x => x.Rate, setCache: true);
}
public async Task GetQuery()
{
// You have access to Where clause for any other usage
await _unitOfWork.Currencies.Where(x => x.CreateDate > DateTime.Now).Include(x => x.CurrencyRules).ToListAsync();
// You can get AsQueryable() for any further implementation
await _unitOfWork.Currencies.AsQueryable().Where(x => x.CreateDate > DateTime.Now).ToListAsync();
// You can even excecute your own T-Sql query
await _unitOfWork.Currencies.FromSqlRaw("SELECT * FROM [dbo].[Currency]").ToListAsync();
}
public void Remove()
{
_unitOfWork.Currencies.Remove(currency);
_unitOfWork.Currencies.RemoveRange(currencies);
_unitOfWork.SaveChangesAsync();
}
public async Task Add()
{
_unitOfWork.Currencies.Add(currency);
_unitOfWork.Currencies.AddRange(currencies);
await _unitOfWork.Currencies.AddAsync(currency);
await _unitOfWork.Currencies.AddRangeAsync(currencies);
await _unitOfWork.SaveChangesAsync();
}
public async Task Update()
{
var currency = await _unitOfWork.Currencies.GetAsync(12);
currency.LastModifiedDate = DateTime.Now;
await _unitOfWork.SaveChangesAsync();
}
public async Task DoSometingTransactional()
{
_unitOfWork.BeginTransaction();
try
{
var currency = await _unitOfWork.Currencies.GetAsync(12);
currency.LastModifiedDate = DateTime.Now;
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitAsync();
}
catch (Exception ex)
{
await _unitOfWork.RollbackAsync();
}
}
}
Easy Peasy caching
With the help of AuxiliaryLibraries.CacheManager we have a easy access to cashing our data here. As mentioned above, we can cache data just by setting setCache as true. If we do that, it means use cache, if data has already stored in Redis just fetch and if it didn't get data from Database and then set it to redis. The intersting part here is, there is no need to set the cache key, naming convention is used according to the EntityName and the parameters you passed. There might be a big question: When the cached data will update? There is a very easy answer for that and that is when you use _unitOfWork.SaveChangesAsync() cahing data will remove. Not all of data that cached, just that part you have updated, inserted, or deleted to db. Let's dive into caching a little bit deeper. If you want to use caching out od=f those function, you can do as follows, or simply use AuxiliaryLibraries.CacheManager and follow its instructions.
public class CurrencyService : ICurrencyService
{
public async Task Caching()
{
// cache key is generating according to the passed parameters to functions. Pass them just like that into the below function
var cacheKey = CacheConventions.Cachekey<Currency>(id: 1, baseKey: "Last");
// Or
var cacheKey = CacheConventions.Cachekey<Currency>(predicate: x => x.CreateDate > DateTime.Now,
orderBy: x => x.OrderByDescending(o => o.CreateDate));
// Removing value of the cacheKey
_unitOfWork.RefreshCache(cacheKey);
// Replacing the value of the cacheKey by obj
await _unitOfWork.RefreshCache(cacheKey, obj);
// Removing any cached data related to Currency
await _unitOfWork.RefreshCache<Currency>(setCache: true);
// Removing any cached data related to Currency with the predicate
_unitOfWork.RefreshCache<Currency>(predicate: x => x.CreateDate > DateTime.Now);
// Or you can simply use
_unitOfWork.Currencies.RefreshCache(cacheKey); // Removing value of the cacheKey
await _unitOfWork.Currencies.RefreshCache(cacheKey, obj); // Replacing the value of the cacheKey by obj
_unitOfWork.Currencies.RefreshCache(); // Removing any cached data related to Currency
_unitOfWork.Currencies.RefreshCache(predicate: x => x.CreateDate > DateTime.Now); // Removing any cached data related to Currency with the predicate
// Try to get a value from cache
if (_unitOfWork.TryGetCache<Currency>(cacheKey, out var currency))
{
currency.ToString();
}
}
}
Configuration
Now we have to do the last part, Configuration. for this we must register all of our repositories and unit of worlk into IOC container.
service.AddScoped<ITestUnitOfWork, TestUnitOfWork>();
service.AddScoped<ICurrencyRepository, CurrencyRepository>();
And we have to set use cache as well, if we want to use caching. Otherwise it is not necessary.
service.UseCache(configuration);
//add this to appsettings
"CacheConfiguration": {
"AbsoluteExpirationInHours": 1,
"SlidingExpirationInMinutes": 30,
"Host": "111.111.111.111",
"Port": "80",
"Password": "redis",
"DatabaseID": 1
}
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
-
net6.0
- AuxiliaryLibraries.CacheManager (>= 1.0.2)
- Microsoft.EntityFrameworkCore.Relational (>= 7.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.