Add project files.
This commit is contained in:
65
Core.Blueprint.SQLServer/Adapters/BaseSQLAdapter.cs
Normal file
65
Core.Blueprint.SQLServer/Adapters/BaseSQLAdapter.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Core.Blueprint.SQLServer.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the base class for SQL Server entities, providing common properties for auditing and state management.
|
||||
/// </summary>
|
||||
public abstract class BaseSQLAdapter : IBaseSQLAdapter
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier for the entity.
|
||||
/// </summary>
|
||||
[Key]
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the unique identifier for the entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("guid")]
|
||||
public string Guid { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp when the entity was created.
|
||||
/// Default value is the current UTC time at the moment of instantiation.
|
||||
/// </summary>
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTime? CreatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the user or system that created the entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("createdBy")]
|
||||
public string? CreatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp when the entity was last updated.
|
||||
/// Null if the entity has not been updated.
|
||||
/// </summary>
|
||||
[JsonPropertyName("updatedAt")]
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the user or system that last updated the entity.
|
||||
/// Null if the entity has not been updated.
|
||||
/// </summary>
|
||||
[JsonPropertyName("updatedBy")]
|
||||
public string? UpdatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status of the entity, indicating whether it is active, inactive, or in another state.
|
||||
/// Default value is <see cref="StatusEnum.Active"/>.
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public StatusEnum Status { get; set; }
|
||||
|
||||
protected BaseSQLAdapter()
|
||||
{
|
||||
Guid = System.Guid.NewGuid().ToString();
|
||||
CreatedAt = DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Core.Blueprint.SQLServer/Adapters/StatusEnum.cs
Normal file
29
Core.Blueprint.SQLServer/Adapters/StatusEnum.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Core.Blueprint.SQLServer.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the possible statuses for entities in the system.
|
||||
/// Used to track the state of an entity, such as whether it is active, inactive, or deleted.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum StatusEnum
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that the entity is currently active and operational.
|
||||
/// </summary>
|
||||
Active = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the entity is currently inactive but still exists in the system.
|
||||
/// Typically used for temporary deactivation or soft-offline states.
|
||||
/// </summary>
|
||||
Inactive = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the entity has been deleted and is no longer accessible.
|
||||
/// Often used in soft-delete scenarios where the entity is retained for archival or audit purposes.
|
||||
/// </summary>
|
||||
Deleted = 2
|
||||
}
|
||||
}
|
||||
33
Core.Blueprint.SQLServer/Configuration/RegisterBlueprint.cs
Normal file
33
Core.Blueprint.SQLServer/Configuration/RegisterBlueprint.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Azure.Identity;
|
||||
using Core.Blueprint.DAL.SQLServer;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Core.Blueprint.SQLServer.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides extension methods for configuring SQL Server.
|
||||
/// </summary>
|
||||
public static class RegisterBlueprint
|
||||
{
|
||||
/// <summary>
|
||||
/// Configures SQL Server services, including the database context and generic repository, for dependency injection.
|
||||
/// </summary>
|
||||
/// <param name="services">The service collection to which the SQL Server services will be added.</param>
|
||||
/// <param name="configuration">The application configuration object for accessing settings such as connection strings.</param>
|
||||
/// <returns>An updated <see cref="IServiceCollection"/> with SQL Server services registered.</returns>
|
||||
public static IServiceCollection AddSQLServer(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var chainedCredentials = new ChainedTokenCredential(
|
||||
new ManagedIdentityCredential(),
|
||||
new SharedTokenCacheCredential(),
|
||||
new VisualStudioCredential(),
|
||||
new VisualStudioCodeCredential()
|
||||
);
|
||||
|
||||
services.AddScoped(typeof(IEntityRepository<,>), typeof(EntityRepository<,>));
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Core.Blueprint.SQLServer/Contracts/IBaseSQLAdapter.cs
Normal file
57
Core.Blueprint.SQLServer/Contracts/IBaseSQLAdapter.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using Core.Blueprint.SQLServer.Entities;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Core.Blueprint.SQLServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the interface for SQL Server entities, providing common properties for auditing and state management.
|
||||
/// </summary>
|
||||
public interface IBaseSQLAdapter
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier for the entity.
|
||||
/// </summary>
|
||||
[Key]
|
||||
[JsonPropertyName("id")]
|
||||
int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the GUID for the entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("guid")]
|
||||
string Guid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp when the entity was created.
|
||||
/// </summary>
|
||||
[JsonPropertyName("createdAt")]
|
||||
DateTime? CreatedAt { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the user or system that created the entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("createdBy")]
|
||||
string? CreatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp when the entity was last updated.
|
||||
/// </summary>
|
||||
[JsonPropertyName("updatedAt")]
|
||||
DateTime? UpdatedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the identifier of the user or system that last updated the entity.
|
||||
/// </summary>
|
||||
[JsonPropertyName("updatedBy")]
|
||||
string? UpdatedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status of the entity, indicating whether it is active, inactive, or in another state.
|
||||
/// </summary>
|
||||
[JsonPropertyName("status")]
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
StatusEnum Status { get; set; }
|
||||
}
|
||||
}
|
||||
108
Core.Blueprint.SQLServer/Contracts/IEntityRepository.cs
Normal file
108
Core.Blueprint.SQLServer/Contracts/IEntityRepository.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Core.Blueprint.DAL.SQLServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the contract for a generic repository to manage entities in a SQL Server database.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entity managed by the repository. Must be a class.</typeparam>
|
||||
/// <typeparam name="TContext">The type of the database context used by the repository. Must inherit from <see cref="DbContext"/>.</typeparam>
|
||||
public interface IEntityRepository<TEntity, TContext>
|
||||
where TEntity : class
|
||||
where TContext : DbContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves all entities of type <typeparamref name="T"/> from the database.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation, with a collection of entities as the result.</returns>
|
||||
Task<IEnumerable<TEntity>> GetAllAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all entities of type <typeparamref name="T"/> from the database that match a specified condition.
|
||||
/// </summary>
|
||||
/// <param name="predicate">An expression to filter the entities.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with a collection of matching entities as the result.</returns>
|
||||
Task<IEnumerable<TEntity>> GetByConditionAsync(Expression<Func<TEntity, bool>> predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a single entity of type <typeparamref name="T"/> by its identifier.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier of the entity to retrieve.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with the entity as the result, or null if not found.</returns>
|
||||
Task<TEntity?> GetByIdAsync(int id);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the first entity of type <typeparamref name="T"/> that matches a specified condition, or null if no match is found.
|
||||
/// </summary>
|
||||
/// <param name="predicate">An expression to filter the entities.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with the matching entity as the result, or null if none match.</returns>
|
||||
Task<TEntity?> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new entity of type <typeparamref name="T"/> to the database.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to add.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task AddAsync(TEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple entities of type <typeparamref name="T"/> to the database.
|
||||
/// </summary>
|
||||
/// <param name="entities">The collection of entities to add.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task AddRangeAsync(IEnumerable<TEntity> entities);
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing entity of type <typeparamref name="T"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to update.</param>
|
||||
/// <returns>The updated entity.</returns>
|
||||
TEntity Update(TEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Updates multiple entities of type <typeparamref name="T"/> in the database.
|
||||
/// </summary>
|
||||
/// <param name="entities">The collection of entities to update.</param>
|
||||
void UpdateRange(IEnumerable<TEntity> entities);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an entity of type <typeparamref name="T"/> from the database.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to delete.</param>
|
||||
void Delete(TEntity entity);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes multiple entities of type <typeparamref name="T"/> from the database.
|
||||
/// </summary>
|
||||
/// <param name="entities">The collection of entities to delete.</param>
|
||||
void DeleteRange(IEnumerable<TEntity> entities);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether any entities of type <typeparamref name="T"/> exist in the database that match a specified condition.
|
||||
/// </summary>
|
||||
/// <param name="predicate">An expression to filter the entities.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with a boolean result indicating whether any match exists.</returns>
|
||||
Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate);
|
||||
|
||||
/// <summary>
|
||||
/// Executes a raw SQL query and maps the result to entities of type <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <param name="sql">The raw SQL query to execute.</param>
|
||||
/// <param name="parameters">Optional parameters for the SQL query.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with a collection of entities as the result.</returns>
|
||||
Task<IEnumerable<TEntity>> ExecuteRawSqlAsync(string sql, params object[] parameters);
|
||||
|
||||
/// <summary>
|
||||
/// Counts the total number of entities of type <typeparamref name="T"/> in the database.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation, with the count as the result.</returns>
|
||||
Task<int> CountAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Saves all pending changes to the database.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
Task SaveAsync();
|
||||
}
|
||||
}
|
||||
16
Core.Blueprint.SQLServer/Core.Blueprint.SQLServer.csproj
Normal file
16
Core.Blueprint.SQLServer/Core.Blueprint.SQLServer.csproj
Normal file
@@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Azure.Identity" Version="1.13.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
182
Core.Blueprint.SQLServer/Repositories/EntityRepository.cs
Normal file
182
Core.Blueprint.SQLServer/Repositories/EntityRepository.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace Core.Blueprint.DAL.SQLServer
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="EntityRepository{TEntity, TContext}"/> class provides a comprehensive generic repository
|
||||
/// for managing entities using Entity Framework Core with SQL Server as the underlying database.
|
||||
/// Designed as a package for consumption by external applications.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The entity type managed by the repository. Must be a class.</typeparam>
|
||||
/// <typeparam name="TContext">The database context type. Must inherit from <see cref="DbContext"/>.</typeparam>
|
||||
public class EntityRepository<TEntity, TContext> : IEntityRepository<TEntity, TContext>
|
||||
where TEntity : class
|
||||
where TContext : DbContext
|
||||
{
|
||||
private readonly TContext _context;
|
||||
private readonly DbSet<TEntity> _dbSet;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EntityRepository{TEntity, TContext}"/> class with a specified database context.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="TContext"/> for database operations.</param>
|
||||
public EntityRepository(TContext context)
|
||||
{
|
||||
_context = context;
|
||||
_dbSet = _context.Set<TEntity>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all entities of type <typeparamref name="TEntity"/> from the database.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation, with a list of entities as the result.</returns>
|
||||
public async Task<IEnumerable<TEntity>> GetAllAsync()
|
||||
{
|
||||
return await _dbSet.ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all entities of type <typeparamref name="TEntity"/> from the database that match a specified filter.
|
||||
/// </summary>
|
||||
/// <param name="predicate">An expression to filter entities.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with a list of filtered entities as the result.</returns>
|
||||
public async Task<IEnumerable<TEntity>> GetByConditionAsync(Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
return await _dbSet.Where(predicate).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a single entity of type <typeparamref name="TEntity"/> by its identifier.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier of the entity.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with the entity as the result, or null if not found.</returns>
|
||||
public async Task<TEntity?> GetByIdAsync(int id)
|
||||
{
|
||||
var existingEntity = await _dbSet.FindAsync(id);
|
||||
|
||||
if (existingEntity != null)
|
||||
{
|
||||
_context.Entry(existingEntity).State = EntityState.Detached;
|
||||
}
|
||||
|
||||
return existingEntity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new entity to the database.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to add.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task AddAsync(TEntity entity)
|
||||
{
|
||||
await _dbSet.AddAsync(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds multiple entities to the database.
|
||||
/// </summary>
|
||||
/// <param name="entities">The collection of entities to add.</param>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task AddRangeAsync(IEnumerable<TEntity> entities)
|
||||
{
|
||||
await _dbSet.AddRangeAsync(entities);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing entity in the database.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to update.</param>
|
||||
/// <returns>The updated entity.</returns>
|
||||
public TEntity Update(TEntity entity)
|
||||
{
|
||||
_dbSet.Attach(entity);
|
||||
_context.Entry(entity).State = EntityState.Modified;
|
||||
return entity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates multiple entities in the database.
|
||||
/// </summary>
|
||||
/// <param name="entities">The collection of entities to update.</param>
|
||||
public void UpdateRange(IEnumerable<TEntity> entities)
|
||||
{
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
_dbSet.Attach(entity);
|
||||
_context.Entry(entity).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an entity from the database.
|
||||
/// </summary>
|
||||
/// <param name="entity">The entity to delete.</param>
|
||||
public void Delete(TEntity entity)
|
||||
{
|
||||
if (_context.Entry(entity).State == EntityState.Detached)
|
||||
{
|
||||
_dbSet.Attach(entity);
|
||||
}
|
||||
_dbSet.Remove(entity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes multiple entities from the database.
|
||||
/// </summary>
|
||||
/// <param name="entities">The collection of entities to delete.</param>
|
||||
public void DeleteRange(IEnumerable<TEntity> entities)
|
||||
{
|
||||
_dbSet.RemoveRange(entities);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the first entity matching the specified condition or null if no match is found.
|
||||
/// </summary>
|
||||
/// <param name="predicate">An expression to filter entities.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with the matched entity as the result.</returns>
|
||||
public async Task<TEntity?> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
return await _dbSet.FirstOrDefaultAsync(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if any entities exist that match the specified condition.
|
||||
/// </summary>
|
||||
/// <param name="predicate">An expression to filter entities.</param>
|
||||
/// <returns>A task representing the asynchronous operation, with a boolean result indicating existence.</returns>
|
||||
public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> predicate)
|
||||
{
|
||||
return await _dbSet.AnyAsync(predicate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Saves all pending changes to the database.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes a raw SQL query and maps the result to the specified entity type.
|
||||
/// </summary>
|
||||
/// <param name="sql">The raw SQL query.</param>
|
||||
/// <param name="parameters">Optional parameters for the query.</param>
|
||||
/// <returns>An <see cref="IEnumerable{TEntity}"/> representing the result set.</returns>
|
||||
public async Task<IEnumerable<TEntity>> ExecuteRawSqlAsync(string sql, params object[] parameters)
|
||||
{
|
||||
return await _dbSet.FromSqlRaw(sql, parameters).ToListAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Counts the total number of entities in the database.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation, with the count as the result.</returns>
|
||||
public async Task<int> CountAsync()
|
||||
{
|
||||
return await _dbSet.CountAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user