Sisusa.Data.EFCore 3.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package Sisusa.Data.EFCore --version 3.0.0
                    
NuGet\Install-Package Sisusa.Data.EFCore -Version 3.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Sisusa.Data.EFCore" Version="3.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Sisusa.Data.EFCore" Version="3.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Sisusa.Data.EFCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Sisusa.Data.EFCore --version 3.0.0
                    
#r "nuget: Sisusa.Data.EFCore, 3.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#addin nuget:?package=Sisusa.Data.EFCore&version=3.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Sisusa.Data.EFCore&version=3.0.0
                    
Install as a Cake Tool

User Documentation for Repository Pattern Implementation in Sisusa.Data.EFCore

This document provides a comprehensive guide for using the SimpleRepository, BaseRepository, and new query-related classes from the Sisusa.Data.EFCore namespace. These classes implement the repository pattern for managing data access in applications using Entity Framework Core.


Overview

Purpose

The repository pattern abstracts data access logic, providing a consistent and reusable interface for performing CRUD operations on database entities. This implementation supports generic data access for entities identified by a primary key (TId).

Key Components

  1. SimpleRepository

    • Provides basic CRUD and query operations.
    • Abstraction over DbSet.
  2. BaseRepository

    • Extends SimpleRepository with additional functionality like managing proxy entities.
    • Supports creation of proxy objects using a Func<TId, TEntity> delegate to simplify some operations Delete, Update.
  3. DataSourceContext

    • Extends DbContext to manage entity sets (EntitySet<T>).
    • Supports transaction management ; bypasses the Database call, so that instead of
        var transaction = await context.Database.BeginTransactionAsync();
    

    we can simply do:

      var transaction = await context.BeginTransactionAsync();
    

    Remember, the goal is to have a shared interface that can work for any data source (SQL, NoSQL, File, etc.) some of which may not have the concept of a Database.

  4. Query<TEntity>

    • Provides a fluent interface for building queries with filtering, ordering, and projections.
    • This is SQL/EF specific and is simply a wrapper around functionality that EF already provides:
        //EF native
        var membersOver20 = await context.Set<ClubMembers>()
            .Where(p => (TimeService.CurrentYear - p.DateOfBirth.Year) > 20)
            .OrderBy(p => p.Id)
            .ThenBy(p => p.Name)
            .Include(p => p.PaymentInfo).ToList();
         //using the Query class  becomes
         var membersOver20 = await Query<ClubMembers>.UsingContext(context).
             .Where(p => (TimeService.CurrentYear - p.DateOfBirth.Year) > 20)
             .OrderBy(p => p.Id)
             .ThenBy(p => p.Name)
             .Include(p => p.PaymentInfo).ToListAsync();
         //aim is to have more verbose and readable code
    
    
  5. EntitySet<T>

    • An implementation of IEntityCollection<T> for use with an EF context, enabling advanced querying and entity management.
        var members = context.Entities<ClubMembers>();>
        //same as 
        var members = context.Set<ClubMembers>();
    

Prerequisites

Installation

Ensure you have the following packages installed:

  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer (or other database provider)

Setup

Configure the DataSourceContext in your Startup.cs or Program.cs file:

services.AddDbContext<DataSourceContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

services.AddScoped(typeof(IRepository<,>), typeof(SimpleRepository<,>));
services.AddScoped(typeof(BaseRepository<,>));

Class Descriptions

SimpleRepository

The SimpleRepository class provides generic CRUD operations for entities.

Key Methods
  • AddNewAsync

    public virtual Task AddNewAsync(TEntity entity)
    

    Adds a new entity to the database.

  • FindAllAsync

    public virtual Task<List<TEntity>> FindAllAsync()
    

    Retrieves all entities from the database.

  • FindByIdAsync

    public virtual Task<TEntity?> FindByIdAsync(TId id)
    

    Retrieves an entity by its primary key.

  • UpdateAsync

    public virtual Task UpdateAsync(TEntity entity)
    

    Updates an existing entity in the database.

  • DeleteByIdAsync

    public virtual Task DeleteByIdAsync(TId id)
    

    Deletes an entity by its primary key.

BaseRepository

The BaseRepository class extends SimpleRepository to include proxy creation and additional entity management capabilities.

Key Methods
  • AddNewAsync Behaves the same as in SimpleRepository but supports additional logic for proxies.

  • UpdateByIdAsync

    public virtual Task UpdateByIdAsync(TId id, TEntity updatedEntity)
    

    Updates an entity identified by its primary key.

  • HasByIdAsync

    public virtual Task<bool> HasByIdAsync(TId id)
    

    Checks if an entity exists by its primary key.

Query<TEntity>

The Query<TEntity> class provides a fluent API for building queries with filtering, ordering, and projections.

Key Methods
  • Where

    public Query<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
    

    Adds a filtering condition to the query.

  • OrderBy

    public Query<TEntity> OrderBy(Expression<Func<TEntity, object>> keySelector, OrderMode mode = OrderMode.Ascending)
    

    Adds an ordering to the query.

  • ThenBy

    public Query<TEntity> ThenBy(Expression<Func<TEntity, object>> keySelector, OrderMode mode = OrderMode.Ascending)
    

    Adds a secondary ordering to the query.

  • Include

    public Query<TEntity> Include(Expression<Func<TEntity, object>> navigationPropertyPath)
    

    Includes a navigation property in the query.

  • ProjectTo

    public IQueryable<TNew> ProjectTo<TNew>(Expression<Func<TEntity, TNew>> selector) where TNew : class
    

    Projects the query results to a new type.

EntitySet<T>

The EntitySet<T> class provides advanced querying and entity management capabilities.

Key Methods
  • AddAsync

    public async Task AddAsync(T entity, CancellationToken cancellationToken = default)
    

    Adds a new entity to the set.

  • RemoveAsync

    public async Task RemoveAsync(T entity, CancellationToken cancellationToken = default)
    

    Removes an entity from the set.

  • CountAsync

    public async Task<int> CountAsync()
    

    Returns the count of entities in the set.


Usage Examples

1. SimpleRepository: Basic CRUD Operations

Scenario

Suppose we have an Employee entity with a primary key of type int. We need to manage employees using the repository.

Setup
public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Department { get; set; }
}

var repository = new SimpleRepository<Employee, int>(context);
Examples
  • Add a New Employee

    var newEmployee = new Employee { Name = "John Doe", Department = "HR" };
    await repository.AddNewAsync(newEmployee);
    
  • Retrieve All Employees

    var employees = await repository.FindAllAsync();
    
  • Retrieve an Employee by ID

    var employee = await repository.FindByIdAsync(1);
    
  • Update an Employee

    var employee = await repository.FindByIdAsync(1);
    if (employee != null)
    {
        employee.Department = "Finance";
        await repository.UpdateAsync(employee);
    }
    
  • Delete an Employee

    await repository.DeleteByIdAsync(1);
    

2. BaseRepository: Advanced Operations with Proxy Creation

Scenario

Suppose we have a Product entity. The BaseRepository allows efficient handling of proxy objects for managing data.

Setup
public class Product
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

var repository = new BaseRepository<Product, Guid>(context, id => new Product { Id = id });
Examples
  • Add a New Product

    var product = new Product { Id = Guid.NewGuid(), Name = "Laptop", Price = 1200.00m };
    await repository.AddNewAsync(product);
    
  • Update a Product by ID

    var productId = Guid.NewGuid();
    var updatedProduct = new Product { Name = "Gaming Laptop", Price = 1500.00m };
    await repository.UpdateByIdAsync(productId, updatedProduct);
    
  • Delete a Product by ID

    var productId = Guid.NewGuid();
    await repository.DeleteByIdAsync(productId);
    
  • Check if a Product Exists

    var exists = await repository.HasByIdAsync(productId);
    

3. Query<TEntity>: Building Queries

Scenario

Using the Query<TEntity> class to filter and order results.

Setup
var query = Query<Product>.FromContext(context)
    .Where(p => p.Price > 1000)
    .OrderBy(p => p.Name);
Example
  • Get Products
    var products = await query.GetCompiled().ToListAsync();
    

4. Transaction Management with DataSourceContext

Scenario

You want to ensure atomicity when performing multiple operations.

Example
using var transaction = await context.BeginTransactionAsync();
try
{
    await repository.AddNewAsync(new Employee { Name = "Alice", Department = "IT" });
    await repository.AddNewAsync(new Employee { Name = "Bob", Department = "Finance" });

    await context.SaveChangesAsync();
    transaction.Commit();
}
catch
{
    transaction.Rollback();
    throw;
}

Best Practices

  1. Validation

    • Ensure inputs (e.g., id and entity) are not null.
  2. Error Handling

    • Handle EntityNotFoundException gracefully when performing updates or deletions.
  3. Transaction Usage

    • Wrap multiple related operations in a transaction to maintain consistency.
  4. Entity Set Configuration

    • Customize EntitySet logic to suit specific data access requirements.

Conclusion

The SimpleRepository, BaseRepository, Query<TEntity>, and EntitySet<T> classes provide powerful abstractions for managing database operations. Their extensible design supports a variety of use cases, making data access straightforward and maintainable. Use these classes to simplify your data layer and focus on core business logic.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
4.1.2 138 5/5/2025
4.1.1 141 5/4/2025
4.1.0 140 5/4/2025
4.0.0 64 5/3/2025
3.0.1 83 5/2/2025
3.0.0 118 5/2/2025
2.0.1 112 1/5/2025
2.0.0 108 1/5/2025
1.2.3 106 12/23/2024
1.2.2 107 12/23/2024 1.2.2 is deprecated because it has critical bugs.
1.2.1 101 12/19/2024
1.0.1 115 12/16/2024
1.0.0 100 12/14/2024

Breaking updates - reduced the layers over EF and used raw EF where possible. e.g, methods  expecting EntitySet<T> now work with DbSet<T>. Added dependency to EFCore.BulkExtensions - haven't got around to making that work yet. Streamlined the BatchInsertManager(and renamed)