ProfileService 1.2.7
dotnet add package ProfileService --version 1.2.7
NuGet\Install-Package ProfileService -Version 1.2.7
<PackageReference Include="ProfileService" Version="1.2.7" />
<PackageVersion Include="ProfileService" Version="1.2.7" />
<PackageReference Include="ProfileService" />
paket add ProfileService --version 1.2.7
#r "nuget: ProfileService, 1.2.7"
#:package ProfileService@1.2.7
#addin nuget:?package=ProfileService&version=1.2.7
#tool nuget:?package=ProfileService&version=1.2.7
ProfileLib
A lightweight, extensible profile management library for .NET applications that provides a clean architecture approach to handling profile data with dynamic query building.
Features
- 🎯 Base profile entity with audit properties
- 💾 Generic repository pattern
- 🔍 Dynamic query building with type safety
- 🗃️ Multiple database provider support
- 🧱 Easy to extend and customize
Installation
dotnet add package ProfileLib
Add your preferred database provider:
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
# or
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
# or
dotnet add package Pomelo.EntityFrameworkCore.MySql
# or
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
Configuration
appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=your_server;Database=your_db;User=your_user;Password=your_password;"
},
"ProfileService": {
"DatabaseProvider": "MySQL",
"MigrationsAssembly": "YourAssemblyName",
"MaxPageSize": 100,
"CacheDuration": "00:30:00",
"MaxCacheSize": 1000
}
}
Usage
- Create your profile class:
public class StudentProfile : ProfileBase
{
public string? MatricNumber { get; private set; }
public string FirstName { get; private set; } = string.Empty;
public string LastName { get; private set; } = string.Empty;
public string? Department { get; private set; }
public string? Level { get; private set; }
public string? Session { get; private set; }
private StudentProfile() : base() { }
public static StudentProfile Create(
string email,
string firstName,
string lastName,
string? matricNumber = null,
string? department = null,
string? level = null,
string? session = null)
{
return new StudentProfile
{
Email = email.ToLower(),
FirstName = firstName,
LastName = lastName,
MatricNumber = matricNumber,
Department = department,
Level = level,
Session = session,
Name = $"{firstName} {lastName}"
};
}
}
- Create your repository interface and implementation:
public interface IStudentProfileRepository : IProfileRepositoryBase<StudentProfile>
{
Task<StudentProfile?> GetStudentProfileAsync(string matricNo);
Task<List<StudentProfile>> GetStudentProfilesByDeptAsync(string dept);
Task<List<StudentProfile>> GetStudentProfilesByDeptLevelAsync(string level, string dept);
}
public class StudentProfileRepository : BaseProfileRepository<StudentProfile>, IStudentProfileRepository
{
public StudentProfileRepository(
DbContext context,
ILogger<BaseProfileRepository<StudentProfile>> logger)
: base(context, logger)
{
}
public Task<StudentProfile?> GetStudentProfileAsync(string matricNo)
{
var predicate = new QueryBuilder<StudentProfile>()
.WhenNotNullOrEmpty(matricNo, x => x.MatricNumber!.Equals(matricNo))
.Build();
return Query().FirstOrDefaultAsync(predicate);
}
public Task<List<StudentProfile>> GetStudentProfilesByDeptAsync(string dept)
{
var predicate = new QueryBuilder<StudentProfile>()
.WhenNotNullOrEmpty(dept, x => x.Department!.Equals(dept))
.Build();
return Query().Where(predicate).ToListAsync();
}
}
- Setup your DbContext:
public class StudentProfileDbContext : DbContext
{
public StudentProfileDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<StudentProfile> StudentProfiles => Set<StudentProfile>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<StudentProfile>(entity =>
{
entity.HasKey(e => e.Id);
entity.Property(e => e.Name).HasMaxLength(100);
entity.Property(e => e.Email).HasMaxLength(100);
entity.Property(e => e.MatricNumber).HasMaxLength(20);
// ... additional configurations
});
}
}
- Configure services in Program.cs:
var connectionString = builder.Configuration["DefaultConnection"];
// Add services
builder.Services.AddProfileService<StudentProfile, StudentProfileRepository>(
builder.Configuration,
connectionString!,
DatabaseProvider.MySQL);
// Register your repository
builder.Services.AddScoped<IStudentProfileRepository, StudentProfileRepository>();
Query Building
The QueryBuilder<T> provides fluent methods for building type-safe queries:
var predicate = new QueryBuilder<StudentProfile>()
.WhenNotNullOrEmpty(dept, x => x.Department!.Equals(dept))
.WhenNotNullOrEmpty(level, x => x.Level!.Equals(level))
.WhenNotNullOrEmpty(session, x => x.Session!.Equals(session))
.Build();
var results = await Query()
.Where(predicate)
.ToListAsync();
Testing
Create test classes inheriting from ProfileBase for unit testing:
public class TestDbContext : DbContext
{
public TestDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<TestStudentProfile> StudentProfiles => Set<TestStudentProfile>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestStudentProfile>(entity =>
{
entity.HasKey(e => e.Id);
// ... configurations
});
}
}
public class TestStudentProfileRepositoryTests : IDisposable
{
private readonly TestDbContext _context;
private readonly TestStudentProfileRepository _repository;
private readonly Mock<ILogger<BaseProfileRepository<TestStudentProfile>>> _loggerMock;
public TestStudentProfileRepositoryTests()
{
var options = new DbContextOptionsBuilder<TestDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_context = new TestDbContext(options);
_loggerMock = new Mock<ILogger<BaseProfileRepository<TestStudentProfile>>>();
_repository = new TestStudentProfileRepository(_context, _loggerMock.Object);
}
[Fact]
public async Task GetStudentProfileAsync_ShouldReturnProfile_WhenMatricNumberExists()
{
// Test implementation
}
}
Base Profile Properties
public abstract class ProfileBase
{
public Guid Id { get; protected set; }
public string Name { get; protected set; }
public string Email { get; protected set; }
public DateTime CreatedAt { get; protected set; }
public DateTime? UpdatedAt { get; protected set; }
public string? CreatedBy { get; protected set; }
public string? UpdatedBy { get; protected set; }
public ProfileStatus Status { get; protected set; }
}
Available Database Providers
- SQL Server
- PostgreSQL
- MySQL
- SQLite
Each provider is configured with optimal settings including:
- Retry policies
- Connection resiliency
- Migrations support
- Performance optimizations
License
This project is licensed under the MIT License - see the LICENSE file for details.
| 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 was computed. 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. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- FluentValidation (>= 11.9.0)
- Microsoft.EntityFrameworkCore (>= 8.0.0)
- Microsoft.EntityFrameworkCore.InMemory (>= 8.0.0)
- Microsoft.EntityFrameworkCore.Relational (>= 8.0.0)
- Microsoft.EntityFrameworkCore.Sqlite (>= 8.0.0)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.0)
- Microsoft.Extensions.Caching.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Caching.Memory (>= 8.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 8.0.0)
- Pomelo.EntityFrameworkCore.MySql (>= 8.0.0-beta.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.