Zonit.Extensions.Databases.SqlServer
0.1.8
See the version list below for details.
dotnet add package Zonit.Extensions.Databases.SqlServer --version 0.1.8
NuGet\Install-Package Zonit.Extensions.Databases.SqlServer -Version 0.1.8
<PackageReference Include="Zonit.Extensions.Databases.SqlServer" Version="0.1.8" />
<PackageVersion Include="Zonit.Extensions.Databases.SqlServer" Version="0.1.8" />
<PackageReference Include="Zonit.Extensions.Databases.SqlServer" />
paket add Zonit.Extensions.Databases.SqlServer --version 0.1.8
#r "nuget: Zonit.Extensions.Databases.SqlServer, 0.1.8"
#addin nuget:?package=Zonit.Extensions.Databases.SqlServer&version=0.1.8
#tool nuget:?package=Zonit.Extensions.Databases.SqlServer&version=0.1.8
Zonit.Extensions.Databases
Zonit.Extensions.Databases is a flexible library for building repositories and handling CRUD operations on databases.
It provides abstractions and interfaces, making it easy to manage database access and to extend your repositories with custom logic, REST API data, or other external sources.
You can use your own repositories and expand them anytime with additional functions, while still keeping your codebase clean and modular.
📦 NuGet Packages
Abstraction
Install-Package Zonit.Extensions.Databases.Abstractions
SQL Server Implementation
Install-Package Zonit.Extensions.Databases.SqlServer
🚀 Features
- Speed up repository work � focus on your logic, not on database �plumbing�.
- Simple abstractions for common CRUD operations.
- Full support for DTO models.
- Built-in support for query building (
Where
,Include
,Select
, paging, ordering and more). - Plug-and-play: Easily extend repositories with custom methods or external data without touching the extension itself.
💡 New! Extension Methods for External Data
Now you can easily include properties and data from outside your database, for example, by pulling from an external API or service.
This is useful when your model should have extra fields, computed properties, or needs to include data fetched live (not loaded from your DB).
How it works:
- Create an Extension Class implementing
IDatabaseExtension<TModel>
- In this class, implement business logic for fetching or computing the desired data.
using Zonit.Extensions.Databases.Examples.Entities;
namespace Zonit.Extensions.Databases.Examples.Extensions;
public class UserExtension : IDatabaseExtension<UserModel>
{
public async Task<UserModel> InicjalizeAsync(Guid userId, CancellationToken cancellationToken = default)
{
// EXAMPLE: Here we would call a REST API or any other source.
var model = new UserModel {
Id = userId,
Name = "UserName",
};
return await Task.FromResult(model);
}
}
- Reference the extension using
.Extension()
in your repository query chain.
var user = await _userRepository.Extension(x => x.UserExtension).GetAsync(userId);
The .Extension(x => x.UserExtension)
call tells the repository to supply or load the UserExtension
property for your entity.
This can be virtual
, NotMapped
, or simply a property populated on demand.
Use Case:
Suppose your Blog
Entity has a UserModel? User
property, but you want to always fetch the latest user data from an API instead of the DB.
Simply create an extension and reference it. The fetching, mapping, and attach process is handled by the extension system for you.
📖 Example Usage
Entity Model
public class Blog
{
public Guid Id { get; set; }
[NotMapped]
public UserModel? User { get; set; }
public Guid? UserId { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public DateTime Created { get; private set; } = DateTime.UtcNow;
}
DTO Example
internal class BlogDto(Blog x)
{
public string Id { get; set; } = $"Id: {x.Id}";
public string Title { get; set; } = $"Title: {x.Title}";
public string Content { get; set; } = $"Content: {x.Content}";
public string Created { get; set; } = $"Created: {x.Created:G}";
}
public class UserModel
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
}
Repository Implementation
public interface IBlogRepository : IDatabaseRepository<Blog, Guid> { }
internal class BlogRepository(DatabaseContext _context)
: DatabaseRepository<Blog, Guid>(_context), IBlogRepository { }
public interface IBlogsRepository : IDatabasesRepository<Blog> { }
internal class BlogsRepository(IDbContextFactory<DatabaseContext> _context)
: DatabasesRepository<Blog, DatabaseContext>(_context), IBlogsRepository { }
Service Registration / Dependency Injection
builder.Services.AddDbSqlServer<DatabaseContext>();
builder.Services.AddTransient<IBlogRepository, BlogRepository>();
builder.Services.AddTransient<IBlogsRepository, BlogsRepository>();
⚙️ CRUD Operations
Create
var blog = await _blogRepository.AddAsync(new Blog
{
Title = "Hello World",
Content = "Example content"
});
Read (Single or DTO)
var blogSingle = await _blogRepository.GetAsync(x => x.Title == "Hello World");
var blogSingleDto = await _blogRepository.GetAsync<BlogDto>(x => x.Title == "Hello World");
Read First
var blogFirst = await _blogRepository.GetFirstAsync(x => x.Title == "Hello World");
var blogFirstDto = await _blogRepository.GetFirstAsync<BlogDto>(x => x.Title == "Hello World");
Or:
var repository = _blogsRepository;
var blogs = await repository.OrderBy(x => x.Created).GetFirstAsync();
var blogsDto = await repository.OrderBy(x => x.Created).GetFirstAsync<BlogDto>();
Update
var blog = await _blogRepository.GetFirstAsync(x => x.Title == "Hello World");
blog.Title = "New Title";
var update = await _blogRepository.UpdateAsync(blog);
Delete
var delete = await _blogRepository.DeleteAsync(blog.Id);
Or
var blog = await _blogRepository.GetFirstAsync(x => x.Title == "Hello World");
var delete = await _blogRepository.DeleteAsync(blog);
Read All
var repository = _blogsRepository;
var blogs = await repository.GetAsync();
var blogsDto = await repository.GetAsync<BlogDto>();
📃 Repository APIs
IDatabaseRepository<TEntity, TType>
Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<TDto> AddAsync<TDto>(TEntity entity, CancellationToken cancellationToken = default);
Task<TEntity?> GetAsync(TType id, CancellationToken cancellationToken = default);
Task<TDto?> GetAsync<TDto>(TType id, CancellationToken cancellationToken = default);
Task<TEntity?> GetAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
Task<TDto?> GetAsync<TDto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
Task<TEntity?> GetFirstAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
Task<TDto?> GetFirstAsync<TDto>(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
Task<bool> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(TType entity, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);
IDatabaseReadRepository<TEntity> Extension(Expression<Func<TEntity, object?>> extension);
IDatabasesRepository<TEntity>
IDatabasesRepository<TEntity> Query();
IDatabasesRepository<TEntity> Extension(Expression<Func<TEntity, object?>> extension);
IDatabasesRepository<TEntity> Skip(int skip);
IDatabasesRepository<TEntity> Take(int take);
IDatabasesRepository<TEntity> Include(Expression<Func<TEntity, object>> includeExpression);
IDatabasesRepository<TEntity> Where(Expression<Func<TEntity, bool>> predicate);
IDatabasesRepository<TEntity> OrderBy(Expression<Func<TEntity, object>> keySelector);
IDatabasesRepository<TEntity> OrderByDescending(Expression<Func<TEntity, object>> keySelector);
IDatabasesRepository<TEntity> Select(Expression<Func<TEntity, TEntity>> selector);
Task<IReadOnlyCollection<TEntity>?> GetAsync(CancellationToken cancellationToken = default);
Task<IReadOnlyCollection<TDto>?> GetAsync<TDto>(CancellationToken cancellationToken = default);
Task<TEntity?> GetFirstAsync(CancellationToken cancellationToken = default);
Task<TDto?> GetFirstAsync<TDto>(CancellationToken cancellationToken = default);
Task<int?> UpdateRangeAsync(Action<TEntity> updateAction, CancellationToken cancellationToken = default);
Task<int> GetCountAsync(CancellationToken cancellationToken = default);
🌟 Why use this extension?
- Build repository pattern code faster and cleaner.
- Decouple your database logic from your app logic.
- At any time, extend your repositories with custom business logic or fetch data from external APIs with zero changes to the extension library.
- Full control: you can always create custom methods in your repository when needed.
ℹ️ For more examples
See the Examples
project included in the repository.
Product | Versions 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. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net8.0
- Microsoft.EntityFrameworkCore (>= 8.0.12)
- Microsoft.EntityFrameworkCore.Abstractions (>= 8.0.12)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.12)
- Microsoft.Extensions.Hosting (>= 8.0.1)
- Zonit.Extensions.Databases.Abstractions (>= 0.1.8)
-
net9.0
- Microsoft.EntityFrameworkCore (>= 9.0.1)
- Microsoft.EntityFrameworkCore.Abstractions (>= 9.0.1)
- Microsoft.EntityFrameworkCore.SqlServer (>= 9.0.1)
- Microsoft.Extensions.Hosting (>= 9.0.1)
- Zonit.Extensions.Databases.Abstractions (>= 0.1.8)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.0.3 | 50 | 4/25/2025 |
1.0.2 | 112 | 4/23/2025 |
1.0.1 | 109 | 4/22/2025 |
1.0.0 | 67 | 4/19/2025 |
0.1.14 | 70 | 4/19/2025 |
0.1.13 | 75 | 4/19/2025 |
0.1.12 | 184 | 4/18/2025 |
0.1.11 | 170 | 4/17/2025 |
0.1.10 | 177 | 4/17/2025 |
0.1.9 | 176 | 4/17/2025 |
0.1.8 | 168 | 4/17/2025 |
0.1.7 | 167 | 4/17/2025 |
0.1.6 | 185 | 4/16/2025 |
0.1.5 | 93 | 1/29/2025 |
0.1.4 | 128 | 6/13/2024 |
0.1.3 | 110 | 6/5/2024 |
0.1.2 | 110 | 6/4/2024 |
0.1.1 | 106 | 6/4/2024 |
0.1.0 | 114 | 6/3/2024 |
0.0.13 | 105 | 5/1/2024 |
0.0.12 | 111 | 4/28/2024 |
0.0.11 | 130 | 4/24/2024 |
0.0.10 | 117 | 4/22/2024 |
0.0.9 | 114 | 4/21/2024 |
0.0.8 | 133 | 4/21/2024 |
0.0.7 | 122 | 4/18/2024 |
0.0.6 | 116 | 4/18/2024 |