DataExplorer.EfCore 3.0.5

dotnet add package DataExplorer.EfCore --version 3.0.5
NuGet\Install-Package DataExplorer.EfCore -Version 3.0.5
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="DataExplorer.EfCore" Version="3.0.5" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DataExplorer.EfCore --version 3.0.5
#r "nuget: DataExplorer.EfCore, 3.0.5"
#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.
// Install DataExplorer.EfCore as a Cake Addin
#addin nuget:?package=DataExplorer.EfCore&version=3.0.5

// Install DataExplorer.EfCore as a Cake Tool
#tool nuget:?package=DataExplorer.EfCore&version=3.0.5

DataExplorer.EfCore

Build Status

Library featuring a combination of Unit of Work, Repository, Specification and Data Service patterns.

Installation

Base DataExplorer package is required.

To register the library services with the DI container use the DataExplorerConfiguration extension method provided by the library:

builder.AddDataExplorer(options => 
{
    options.AddEfCore(assembliesToScan);
});

Description

Library provides definition of a base entity (with generic Id and with long Id) which should be inherited by any entity defined within application's domain.

public class CustomEntity : Entity<long>
{
    public bool CustomField { get; set; }
}

You can also implement IUpdatedAt and/or ICreatedAt interfaces to let the library handle the metadata properties automatically.

Library supports soft deletion via a IsDisabled property on entities, you can mark an entity as a soft deleted entity using IDisableableEntity interface. Snowflake IDs are supported using an IdGenerator, to mark an entity to use snowflake IDs inherit from SnowflakeEntity or implement ISnowflakeEntity interface and override the Id property. Ids can be generated by a provided IdGenerator which you can add as a singleton service via AddIdGen()

To avoid LINQ boilerplate a specification pattern is used to encapsulate query logic and should be used like so:

public CustomSpecification : Specification<CustomEntity>
{
    public CustomSpecification(bool customField)
    {
        Where(x => x.CustomField == customField);
    }
}

EF 7 ExecuteDeleteAsync and ExecuteUpdateAsync methods are now supported. In order to use the update method you must create a Specification that inherits from UpdateSpecification<TEntitiy>:

public CustomUpdateSpecification : UpdateSpecification<CustomEntity>
{
    public CustomUpdateSpecification(bool customField)
    {
        Where(x => x.CustomField == customField);
        Modify(x => x.SetProperty(p => p.CustomField, !customField));
    }
}

Please use IntelliSense to check for available methods but pretty much everything should be supported by now.

Every data service automatically grabs it's corresponding entity repository from the Unit of Work and exposes it via properties, you can however do anything and everything through exposed DbContext, UnitOfWork, Mapper and other properties.

Getting a repository is done through methods on IUnitOfWork:

unitOfWork.GetRepository<IRepository<CustomEntity>>();

Please use IntelliSense to find other helpful get repo methods. You can't (without reflection magic) create custom repository implementations, their constructor is internal, you can only get generic repos with the methods exposed via IUnitOfWork, any custom, additional logic, should be performed in the service layer.:

Given below context definitions (always abstract your own context) - either manually register your context interface as a service or use AddDbContext methods on DataExplorerEfCoreConfiguration.

public interface ICustomDbContext : IEfDbContext
{
}

public class CustomDbContext : EfDbContext, ICustomDbContext
{
}

You can define a crud data service like so to add some custom logic:

public interface ICustomDataService : ICrudDataService<CustomEntity, ICustomDbContext>
{
    Task<Result> GetFirstEntityWithCustomFieldTrueAndPerformLogicAsync();
}

public class CustomDataService : CrudDataService<CustomEntity, ICustomDbContext>, ICustomDataService
{
    public async Task<Result> GetFirstEntityWithCustomFieldTrueAndPerformLogicAsync()
    {
        var entityRes = await GetSingleBySpecAsync(new CustomSpecification(true));

        if (!entityRes.IsDefined(out var entity))
            return entityRes;

        /// perform custom logic on entity or whatnot

        return Result.FromSuccess();
    }
}

You can also simply inject a generic data service to perform simple operations like so:


public class CustomController : ControllerBase
{
    private readonly IReadOnlyDataService<CustomEntity,ICustomDbContext> _dataService;

    public CustomController(IReadOnlyDataService<CustomEntity,ICustomDbContext> dataService)
        => _dataService = dataService;

    [HttpGet]
    public async Task<IActionResult> GetAllByCustomFieldAsync(bool customField)
    {
        var subRes = await _dataService.GetBySpecAsync(new CustomSpecification(customField)); // or GetBySpecAsync<SomeDto> to automatically map the entity using AutoMapper
        if (!subRes.IsDefined(out var result))
            return BadRequest();

        return Ok(result);
    }
}

All service methods should return a Result struct which determines whether the operation succeeded or not and returns additional objects if necessary and shouldn't throw exceptions unless absolutely necessary.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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. 
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
3.0.5 101 2/16/2024
3.0.4 98 1/25/2024
3.0.3 146 1/4/2024
3.0.2 183 11/22/2023
3.0.1 109 11/21/2023
3.0.0 107 11/20/2023
2.3.12 133 9/12/2023
2.3.11 138 9/1/2023
2.3.10 143 8/31/2023
2.3.9 116 8/31/2023
2.3.8 145 8/31/2023
2.3.7 152 8/30/2023
2.3.6 138 8/30/2023
2.3.5 155 8/30/2023
2.3.3 178 8/18/2023
2.3.2 183 8/8/2023
2.3.1 173 7/13/2023
2.3.0 171 7/11/2023
2.2.9 156 7/10/2023
2.2.8 192 6/25/2023
2.2.7 137 5/31/2023
2.2.6 168 5/17/2023
2.2.5 191 5/10/2023
2.2.4 219 4/14/2023
2.2.3 210 4/14/2023
2.2.2 203 4/14/2023
2.2.1 223 4/7/2023
2.2.0 247 3/14/2023
2.1.10 278 2/26/2023
2.1.9 264 2/26/2023
2.1.8 267 2/23/2023
2.1.7 253 2/23/2023
2.1.6 252 2/21/2023
2.1.5 257 2/21/2023
2.1.4 268 2/15/2023
2.1.3 277 2/3/2023
2.1.2 317 1/28/2023
2.1.1 328 1/22/2023
2.1.0 316 1/22/2023
2.0.8 329 1/11/2023
2.0.7 318 1/11/2023
2.0.6 324 1/9/2023
2.0.5 321 1/9/2023
2.0.4 389 11/21/2022
2.0.3 365 11/21/2022
2.0.2 362 11/19/2022
2.0.1 364 11/19/2022
2.0.0 347 11/19/2022
1.1.10 356 11/18/2022
1.1.9 406 9/27/2022
1.1.8 430 9/26/2022
1.1.7 462 9/24/2022
1.1.6 417 9/21/2022
1.1.5 403 9/19/2022
1.1.4 423 9/19/2022
1.1.3 418 9/19/2022
1.1.2 439 9/19/2022
1.1.0 449 9/17/2022
1.0.16 423 9/8/2022
1.0.15 445 8/29/2022
1.0.14 408 8/29/2022
1.0.13 431 8/29/2022
1.0.12 418 8/29/2022
1.0.11 424 8/29/2022
1.0.10 434 8/25/2022
1.0.8 418 8/25/2022
1.0.7 418 8/25/2022
1.0.6 419 8/25/2022
1.0.5 421 8/24/2022
1.0.4 418 8/23/2022
1.0.3 440 8/23/2022
1.0.2 428 8/23/2022
1.0.1 426 8/22/2022