GaEpd.AppLibrary
5.3.1
Prefix Reserved
dotnet add package GaEpd.AppLibrary --version 5.3.1
NuGet\Install-Package GaEpd.AppLibrary -Version 5.3.1
<PackageReference Include="GaEpd.AppLibrary" Version="5.3.1" />
paket add GaEpd.AppLibrary --version 5.3.1
#r "nuget: GaEpd.AppLibrary, 5.3.1"
// Install GaEpd.AppLibrary as a Cake Addin #addin nuget:?package=GaEpd.AppLibrary&version=5.3.1 // Install GaEpd.AppLibrary as a Cake Tool #tool nuget:?package=GaEpd.AppLibrary&version=5.3.1
Georgia EPD-IT App Library
This repo contains a library created by Georgia EPD-IT to provide common classes and tools for our web applications.
(Much of this work was inspired by the ABP Framework.)
How to install
To install , search for "GaEpd.AppLibrary" in the NuGet package manager or run the following command:
dotnet add package GaEpd.AppLibrary
What's included
Domain entities
The following interfaces and abstract implementations of domain entities are provided for domain driven design:
- The basic
IEntity<TKey>
interface defines an entity with a primary key of the given type. - The special case
IEntity
interface defines an entity with aGUID
primary key. IAuditableEntity<TUserKey>
adds created/updated properties and methods for basic data auditing.ISoftDelete
andISoftDelete<TUserKey>
add properties for "soft deleting" an entity rather than actually- deleting it.
INamedEntity
adds a "Name" string property.IActiveEntity
adds an "Active" boolean property.
There are also abstract classes based on the above interfaces from which you should derive your domain
entities: Entity<TKey>
, AuditableEntity<TKey, TUserKey>
, SoftDeleteEntity<TKey, TUserKey>
,
AuditableSoftDeleteEntity<TKey, TUserKey>
, and StandardNamedEntity
.
The StandardNamedEntity
class derives from AuditableEntity<Guid>
, INamedEntity
, and IActiveEntity
, and includes
methods for enforcing the length of the Name
. Maximum and minimum name length can be set in the constructor.
Example usage:
public class DerivedNamedEntity : StandardNamedEntity
{
public override int MinNameLength => 2;
public override int MaxNameLength => 50;
public DerivedNamedEntity() { }
public DerivedNamedEntity(Guid id, string name) : base(id, name) { }
}
ValueObject
An abstract ValueObject record can help add value objects to your domain entities.
A value object is a compound of properties, such as an address or
date range, that are comparable based solely on their values rather than their references. The properties of a value
object are typically stored with its parent class, not as a separate record with its own ID. Value objects should be
treated as immutable. When deriving from ValueObject
, you must provide a GetEqualityComponents()
method to define
which properties to use to determine equality.
Example usage:
[Owned]
public record Address : ValueObject
{
public string Street { get; init; } = string.Empty;
public string? Street2 { get; init; }
public string City { get; init; } = string.Empty;
public string State { get; init; } = string.Empty;
[DataType(DataType.PostalCode)]
public string PostalCode { get; init; } = string.Empty;
protected override IEnumerable<object> GetEqualityComponents()
{
yield return Street;
yield return Street2 ?? string.Empty;
yield return City;
yield return State;
yield return PostalCode;
}
}
Note: The [Owned]
attribute is an Entity Framework attribute defining this as a value object owned by the parent
class. See Owned Entity Types for more info on how
this is implemented in EF Core.
Data Repositories
Common data repository interfaces define basic entity CRUD operations. The IReadRepository
interface defines get and
search operations (including paginated search). The IWriteRepository
interface defines insert, update, and delete
operations. IRepository
combines the read and write interfaces. Finally, the INamedEntityRepository
adds a
find-by-name method.
(Note that these interfaces work directly with domain entities. Your application should define application/domain services that define how the application interacts with the entities & repositories through data transfer objects (DTOs).)
There are two abstract BaseRepository
classes that each implement the IRepository
interface, one using in-memory
data and the other requiring an Entity Framework database context.
There are similarly two abstract NamedEntityRepository
classes that each implement the INamedEntityRepository
interface.
Example usage:
public interface IDerivedRepository : INamedEntityRepository<DerivedNamedEntity> { }
public sealed class DerivedRepository : NamedEntityRepository<DerivedNamedEntity, AppDbContext>, IDerivedRepository
{
public DerivedRepository(AppDbContext context) : base(context) { }
}
Predicate builder
Code from C# in a Nutshell is included to enable creating
filter expressions that can be combined. The library comes with the commonly used filters WithId(id)
for all entities
and ExcludedDeleted()
for "soft delete" entities.
Example usage:
public static Expression<Func<MyEntity, bool>> IsActive(this Expression<Func<MyEntity, bool>> predicate) =>
predicate.And(e => e.IsActive);
public static Expression<Func<MyEntity, bool>> ActiveAndNotDeletedPredicate() =>
PredicateBuilder.True<MyEntity>().IsActive().ExcludeDeleted();
Pagination classes
IPaginatedRequest
and IPaginatedResult<T>
define how to request and receive paginated (and sorted) search results.
The System.Linq.Dynamic.Core package is included.
List Item record
A ListItem<TKey>
record type defines a key-value pair with fields for ID of type TKey
and string
Name.
The ToSelectList()
extension method takes a ListItem
enumerable and returns an MVC SelectList
which can be used to
create an HTML <select>
element.
Enum extensions
GetDisplayName()
and GetDescription()
return the DisplayAttribute.Name
and DescriptionAttribute
values of an
enum, respectively.
Guard clauses
The GuardClauses package is included by reference.
What's not included
The File Service and GuardClauses packages have been moved to separate repositories.
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. |
-
net8.0
- GaEpd.GuardClauses (>= 2.0.0)
- Microsoft.EntityFrameworkCore (>= 8.0.0)
- System.Linq.Dynamic.Core (>= 1.3.7)
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 |
---|---|---|
5.3.1 | 451 | 9/11/2024 |
5.3.0 | 607 | 9/10/2024 |
5.2.1 | 1,142 | 4/30/2024 |
5.2.0 | 127 | 4/29/2024 |
5.1.0 | 1,032 | 1/3/2024 |
5.0.1 | 123 | 1/2/2024 |
5.0.0 | 137 | 1/2/2024 |
4.1.0 | 586 | 11/9/2023 |
4.0.0 | 213 | 10/25/2023 |
3.5.1 | 358 | 9/20/2023 |
3.5.0 | 166 | 9/19/2023 |
3.4.0 | 135 | 9/18/2023 |
3.3.0 | 345 | 8/11/2023 |
3.2.0 | 605 | 5/22/2023 |
3.1.0 | 420 | 4/25/2023 |
3.0.0 | 733 | 3/27/2023 |
2.0.0 | 295 | 3/7/2023 |
1.1.0 | 676 | 12/22/2022 |
1.0.1 | 432 | 10/14/2022 |
1.0.0 | 860 | 10/6/2022 |
0.4.0-beta | 222 | 9/29/2022 |
0.3.0-beta | 205 | 9/23/2022 |
# Changelog
## [5.3.1] - 2024-09-11
- Fixed the Entity Framework repository's `GetAsync` method to enable change tracking for the returned entity.
## [5.3.0] - 2024-09-10
- Added `GetAsync` and `FindAsync` overloads that allow you to specify what navigation properties to include (when using the Entity Framework repository).
## [5.2.1] - 2024-04-30
- Added a `GetOrderedListAsync` overload method with predicate matching.
## [5.2.0] - 2024-04-30
- Added a string `Truncate` function.
- Added a `GetOrderedListAsync` method to the Named Entity Repository.
## [5.1.0] - 2024-01-03
- Updated the included GuardClauses library to v2.0.0.
## [5.0.1] - 2024-01-02
- Updated changelog for v5.0.0 release.
## [5.0.0] - 2024-01-02
- Upgraded to .NET 8.0.
### Added
- Added entity and repository interfaces that default to using a GUID primary key and updated the abstract classes to use these new interfaces.
### Changed
- **Breaking changes:**
- Uses of `EntityNotFoundException` will need to be updated to provide the class type. For example, `EntityNotFoundException(typeof(MyEntity), id)` should be replaced with `EntityNotFoundException<MyEntity>(id)`.
- References to `IEntity<Guid>` may need to be replaced with `IEntity`.
## [4.1.0] - 2023-11-09
- Implement IAsyncDisposable in repositories.
## [4.0.0] - 2023-10-25
- Move GuardClauses to a separate NuGet package.
## [3.5.1] - 2023-09-20
- Derived EF repositories can now specify the DbContext type.
## [3.5.0] - 2023-09-19
- Added an abstract StandardNameEntity along with INamedEntity and IActiveEntity interfaces.
- Added INamedEntityRepository and INamedEntityManager interfaces and implementations.
## [3.4.0] - 2023-09-18
- Included abstract implementations of BaseRepository.
## [3.3.0] - 2023-08-11
- Added a "ConcatWithSeparator" string extension.
- Added "PreviousPageNumber" and "NextPageNumber" properties to the IPaginatedResult interface.
- Made some possible performance improvements to the Enum extensions.
Breaking change: The Enum extensions no longer work with nullable Enum values.
## [3.2.0] - 2023-05-22
- Added a "SetNotDeleted" (undelete) method to the ISoftDelete interface.
## [3.1.0] - 2023-04-25
- Added a "SaveChanges" method to the write repository.
## [3.0.0] - 2023-04-25
- Upgraded the library to .NET 7.
## [2.0.0] - 2023-03-07
- Moved the write repository operations to a separate interface.
- Added "Exists" methods to the read repository interface.
- Renamed the user ID properties on auditable entities.
## [1.1.0] - 2023-03-07
- Added predicate builder and common entity filters.
- Added enum extensions.
- Added the System.Linq.Dynamic.Core package.
## [1.0.1] - 2022-10-14
- Added a Readme file to the package.
## [1.0.0] - 2022-10-06
_Initial release._
[5.3.0]: https://github.com/gaepdit/app-library/releases/tag/v5.3.0
[5.2.1]: https://github.com/gaepdit/app-library/releases/tag/v5.2.1
[5.2.0]: https://github.com/gaepdit/app-library/releases/tag/v5.2.0
[5.1.0]: https://github.com/gaepdit/app-library/releases/tag/l%2Fv5.1.0
[5.0.1]: https://github.com/gaepdit/app-library/releases/tag/al%2Fv5.0.1
[5.0.0]: https://github.com/gaepdit/app-library/releases/tag/al%2Fv5.0.0
[4.1.0]: https://github.com/gaepdit/app-library/releases/tag/al%2Fv4.1.0
[4.0.0]: https://github.com/gaepdit/app-library/releases/tag/al%2Fv4.0.0
[3.5.1]: https://github.com/gaepdit/app-library/releases/tag/v3.5.1
[3.5.0]: https://github.com/gaepdit/app-library/releases/tag/v3.5.0
[3.4.0]: https://github.com/gaepdit/app-library/releases/tag/v3.4.0
[3.3.0]: https://github.com/gaepdit/app-library/releases/tag/v3.3.0
[3.2.0]: https://github.com/gaepdit/app-library/releases/tag/v3.2.0
[3.1.0]: https://github.com/gaepdit/app-library/releases/tag/v3.1.0
[3.0.0]: https://github.com/gaepdit/app-library/releases/tag/v3.0.0
[2.0.0]: https://github.com/gaepdit/app-library/releases/tag/v2.0.0
[1.1.0]: https://github.com/gaepdit/app-library/releases/tag/v1.1.0
[1.0.1]: https://github.com/gaepdit/app-library/releases/tag/v1.0.1
[1.0.0]: https://github.com/gaepdit/app-library/releases/tag/v1.0.0