EfCore.GenericServices
2.0.0-preview001
See the version list below for details.
dotnet add package EfCore.GenericServices --version 2.0.0-preview001
NuGet\Install-Package EfCore.GenericServices -Version 2.0.0-preview001
<PackageReference Include="EfCore.GenericServices" Version="2.0.0-preview001" />
paket add EfCore.GenericServices --version 2.0.0-preview001
#r "nuget: EfCore.GenericServices, 2.0.0-preview001"
// Install EfCore.GenericServices as a Cake Addin #addin nuget:?package=EfCore.GenericServices&version=2.0.0-preview001&prerelease // Install EfCore.GenericServices as a Cake Tool #tool nuget:?package=EfCore.GenericServices&version=2.0.0-preview001&prerelease
Now supports JSON Patch updates.
EfCore.GenericServices (NuGet link)
This library helps you quickly code Create, Read, Update and Delete (CRUD) accesses for a web/mobile/desktop application. It acts as a adapter between a database accessed by Entity Framework Core (EF Core) and the needs of the front-end system. Typical web applications have hundreds of CRUD pages - display this, edit that, delete the other. And each CRUD access has to adapt the data in the database to show the user, and then apply the changes to the database. This library extracts the pattern into a library, making the writing of the CRUD front-end code both quicker and simpler to write. The code for each of the four access type (Create, Read, Update and Delete) are identical, apart from the ViewModel/DTO specific to the actual feature. So, you create one set of update code for your specific applictation and then cut/paste + change one line for all the other versions. Here is the code from the example Razor Page application contained in this repo for adding a review to a Book (the example site is a tiny Amazon-like site).
public class AddReviewModel : PageModel
{
private readonly ICrudServices _service;
public AddReviewModel(ICrudServices service)
{
_service = service;
}
[BindProperty]
public AddReviewDto Data { get; set; }
public void OnGet(int id)
{
Data = _service.ReadSingle<AddReviewDto>(id);
if (!_service.IsValid)
{
_service.CopyErrorsToModelState(ModelState, Data, nameof(Data));
}
}
public IActionResult OnPost()
{
if (!ModelState.IsValid)
{
return Page();
}
_service.UpdateAndSave(Data);
if (_service.IsValid)
return RedirectToPage("BookUpdated", new { message = _service.Message});
//Error state
_service.CopyErrorsToModelState(ModelState, Data, nameof(Data));
return Page();
}
}
If you compare that with the
AddPromotion or
ChangePubDate
update you will see they are identical apart from the type of the Data
property.
And the ViewModel/DTO isn't anything special (see the
AddReviewDto).
They just need to be marked with an empty
ILinkToEntity<TEntity>
interface, which tells GenericServices which EF Core entity
class to map to. For more security you can also mark any read-only properties with the
[ReadOnly(true)]
attribute - GenericServices will never try to update the
database with any read-only marked property.
Technical features
The EfCore.GenericServices (NuGet, EfCore.GenericServices), is an open-source (MIT licence) netcoreapp2.0 library that assumes you use EF Core for your database accesses. It has good documentation in the repo's Wiki.
It is designed to work with both standard-styled entity classes (e.g. public setters on the properties and a public, paremeterless constructor), or with a Domain-Driven Design (DDD) styled entity classes (e.g. where all updates are done through named methods in the the entity class) - see this article for more on the difference between standard-styled entity classes and DDD styled entity classes.
It also works well with with dependancy injection (DI), such as ASP.NET Core's DI service. But does also contain a simplified, non-DI based configuration system suitable for unit testing and/or serverless applications.
NOTE: I created a similar library for EF6.x back in 2014, which has saved my many months of (boring) coding - on one project alone I think it saved 2 months out of 12. This new version contains the learning from that library, and the new DDD-enabling feature of EF Core to reimagine that library, but in a very different (hopefully simpler) way.
Library performance
I have compared the performance of the GenericService library using the excellent BenchmarkDotNet library, as part of the GitHub repo. The performance loss was an extra 25 us. - worst case, 5% of total time, and that is for the simplest update on the fastest in-memory database. See the Performance figures wiki page for full details.
Documentation and examples
- The GenericServices Wiki has lots of documentation.
- The public methods in the library are all commented for intellisense feedback.
- This repo contains a runnable example Razor Page application, with the database in the DataLayer.
- This intoductory article provides a longer introduction to EfCore.GenericServices.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. 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 was computed. 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 was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- AutoMapper (>= 7.0.1)
- Microsoft.AspNetCore.JsonPatch (>= 2.1.1)
- Microsoft.EntityFrameworkCore (>= 2.1.1)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on EfCore.GenericServices:
Package | Downloads |
---|---|
EfCore.GenericServices.AspNetCore
A support library to the EfCore.GenericServices and EfCore.GenericBizRunner libraries. It converts IStatusGeneric into ASP.NET Core's ModelState or Web API response |
|
EntityServices
Package Description |
|
UZB.ELYORBEK.EF
CRUD operations works. |
GitHub repositories (2)
Showing the top 2 popular GitHub repositories that depend on EfCore.GenericServices:
Repository | Stars |
---|---|
JonPSmith/AuthPermissions.AspNetCore
This library provides extra authorization and multi-tenant features to an ASP.NET Core application.
|
|
JonPSmith/PermissionAccessControl2
Version 2 of example application to go with articles on feature and data authorization
|
Version | Downloads | Last updated |
---|---|---|
9.0.0 | 291 | 11/21/2024 |
8.1.0 | 6,470 | 5/4/2024 |
8.0.0 | 500 | 4/10/2024 |
6.0.0 | 6,869 | 11/22/2023 |
5.2.1 | 21,317 | 1/3/2023 |
5.2.0 | 3,809 | 11/15/2022 |
5.2.0-preview001 | 686 | 12/8/2022 |
5.1.1 | 18,033 | 2/2/2022 |
5.1.0 | 26,169 | 11/10/2021 |
5.1.0-preview001 | 170 | 11/4/2021 |
5.0.1 | 17,407 | 7/8/2021 |
5.0.0 | 19,434 | 1/6/2021 |
3.3.0 | 1,388 | 6/21/2021 |
3.2.2 | 18,053 | 5/22/2020 |
3.2.1 | 3,526 | 4/11/2020 |
3.2.0 | 1,190 | 4/10/2020 |
3.1.0 | 46,412 | 1/27/2020 |
3.0.0 | 5,195 | 10/12/2019 |
2.1.0-preview001 | 1,074 | 10/4/2019 |
2.0.3 | 3,686 | 7/29/2019 |
2.0.2 | 11,248 | 4/4/2019 |
2.0.1 | 5,029 | 3/10/2019 |
2.0.0 | 7,491 | 1/2/2019 |
2.0.0-preview001 | 2,761 | 12/24/2018 |
1.3.3 | 5,721 | 10/27/2018 |
1.3.2 | 1,915 | 10/22/2018 |
1.3.1 | 2,036 | 9/26/2018 |
1.3.0 | 1,983 | 9/18/2018 |
1.2.6 | 10,498 | 8/18/2018 |
1.2.4 | 3,002 | 7/29/2018 |
1.2.3 | 2,202 | 7/24/2018 |
1.2.2 | 1,463 | 7/16/2018 |
1.2.1 | 1,496 | 7/14/2018 |
1.1.0 | 2,162 | 6/7/2018 |
1.0.0 | 2,363 | 4/12/2018 |
- New feature: Now handles EF Core's DbQuery type (DbQuery type is only used for reads) - fixes Issue #16.
- New Feature: Added `ProjectFromEntityToDto{TEntity,TDto}` to the services. This allows you to read data with a query prior to the projection to a DTO. Fixes issue #10 and #15
- New Feature: Added `IGenericStatus BeforeSaveChanges(DbContext)` to configuration.
This allows you to inject code that is called just before SaveChanges/SaveChangesAsync is run. This allows you
to add some validation, logging etc. - see issue #14.
- Improvement: Previously the Sql error handler was only used if validation was turned on.
Now, if the SaveChangesExceptionHandler property is not null, then taht method is called,
i.e. it is not longer dependant on the state of the ...ValidateOnSave flag in the config.
- Breaking change (Minor): In version 1.3.1 both `DeleteAndSave` and `DeleteWithActionAndSave` used `IgnoreQueryFilters` to get all entities.
This was done so that soft deleted items would be found, but its dangerous in multi-tenant systems.
In 2.0.0 only `DeleteWithActionAndSave` will use `IgnoreQueryFilters` to get all entities. That is safer, as you can provide extra checks in the method you provide.
- Performance bug fix: There was a performance issue when using the setup methods use in unit testing and non-DI situations