
Research
/Security News
Critical Vulnerability in NestJS Devtools: Localhost RCE via Sandbox Escape
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Zonit.Extensions.Databases.SqlServer
Advanced tools
A flexible and extensible library for building repositories and managing CRUD operations using Entity Framework Core. Includes support for DTOs, dynamic queries, and external data extensions.
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.
Install-Package Zonit.Extensions.Databases.Abstractions
Install-Package Zonit.Extensions.Databases.SqlServer
Where
, Include
, Select
, paging, ordering, and more).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).
IDatabaseExtension<TModel>
using Zonit.Extensions.Databases.Examples.Entities;
namespace Zonit.Extensions.Databases.Examples.Extensions;
public class UserExtension : IDatabaseExtension<UserModel>
{
public async Task<UserModel> InitializeAsync(Guid userId, CancellationToken cancellationToken = default)
{
// Here you can call a REST API or any other data source.
var model = new UserModel {
Id = userId,
Name = "UserName",
};
return await Task.FromResult(model);
}
}
.Extension()
in your repository query chain.var user = await _userRepository.Extension(x => x.UserExtension).GetByIdAsync(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.
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;
}
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;
}
public interface IBlogRepository : IDatabaseRepository<Blog> { }
internal class BlogRepository(DatabaseContext _context)
: DatabaseRepository<Blog>(_context), IBlogRepository { }
builder.Services.AddDbSqlServer<DatabaseContext>();
builder.Services.AddTransient<IBlogRepository, BlogRepository>();
var blog = await _blogRepository.AddAsync(new Blog
{
Title = "Hello World",
Content = "Example content"
});
var blogSingle = await _blogRepository.GetByIdAsync(blogId);
var blogSingleDto = await _blogRepository.GetByIdAsync<BlogDto>(blogId);
var firstBlog = await _blogRepository.Where(x => x.Title == "Hello World").GetFirstAsync();
var firstBlogDto = await _blogRepository.Where(x => x.Title == "Hello World").GetFirstAsync<BlogDto>();
var updated = await _blogRepository.UpdateAsync(blog.Id, entity =>
{
entity.Title = "New Title";
});
or
blog.Title = "New Title";
var updated = await _blogRepository.UpdateAsync(blog);
var deleted = await _blogRepository.DeleteAsync(blog.Id);
or
var deleted = await _blogRepository.DeleteAsync(blog);
var blogs = await _blogRepository.GetListAsync();
var blogsDto = await _blogRepository.GetListAsync<BlogDto>();
Below is an overview of the main interfaces and methods.
(See XML comments in code for details.)
IDatabaseRepository<TEntity>
// Queryable & CRUD interface for TEntity
IDatabaseAsQueryable<TEntity> AsQuery();
// Query customization:
IDatabaseQueryOperations<TEntity> Extension(Expression<Func<TEntity, object?>> extensionExpression);
IDatabaseQueryOperations<TEntity> Select<TDto>(Expression<Func<TEntity, TDto>> selector);
IDatabaseQueryOperations<TEntity> Include(Expression<Func<TEntity, object?>> includeExpression);
IDatabaseQueryOperations<TEntity> Where(Expression<Func<TEntity, bool>> whereExpression);
IDatabaseMultipleQueryable<TEntity> Skip(int count);
IDatabaseMultipleQueryable<TEntity> Take(int count);
IDatabaseMultipleRepository<TEntity> OrderBy(Expression<Func<TEntity, object>> keySelector);
IDatabaseMultipleRepository<TEntity> OrderByDescending(Expression<Func<TEntity, object>> keySelector);
// Single record access:
Task<TEntity?> GetByIdAsync(int id, CancellationToken cancellationToken = default);
Task<TDto?> GetByIdAsync<TDto>(int id, CancellationToken cancellationToken = default);
Task<TEntity?> GetByIdAsync(Guid id, CancellationToken cancellationToken = default);
Task<TDto?> GetByIdAsync<TDto>(Guid id, CancellationToken cancellationToken = default);
Task<TEntity?> GetAsync(CancellationToken cancellationToken = default);
Task<TDto?> GetAsync<TDto>(CancellationToken cancellationToken = default);
// Existence check:
Task<bool> AnyAsync(CancellationToken cancellationToken = default);
// Add/Update/Delete:
Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<TDto> AddAsync<TDto>(TEntity entity, CancellationToken cancellationToken = default);
Task<bool> UpdateAsync(int id, Action<TEntity> updateAction, CancellationToken cancellationToken = default);
Task<bool> UpdateAsync(Guid id, Action<TEntity> updateAction, CancellationToken cancellationToken = default);
Task<bool> UpdateAsync(TEntity entity, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(int entity, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(Guid entity, CancellationToken cancellationToken = default);
Task<bool> DeleteAsync(TEntity entity, CancellationToken cancellationToken = default);
// Multiple records access:
Task<IReadOnlyCollection<TEntity>?> GetListAsync(CancellationToken cancellationToken = default);
Task<IReadOnlyCollection<TDto>?> GetListAsync<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);
Note:
The deprecated IDatabasesRepository<TEntity>
interface has been removed and is not supported anymore. Please migrate to IDatabaseRepository<TEntity>
and related interfaces for all new development.
See the Examples
project included in the repository.
FAQs
A flexible and extensible library for building repositories and managing CRUD operations using Entity Framework Core. Includes support for DTOs, dynamic queries, and external data extensions.
We found that zonit.extensions.databases.sqlserver demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Product
Customize license detection with Socket’s new license overlays: gain control, reduce noise, and handle edge cases with precision.
Product
Socket now supports Rust and Cargo, offering package search for all users and experimental SBOM generation for enterprise projects.