The purpose of this sample is to demonstrate the usage of Beef (and CoreEx runtime) within the context of a fictitious Human Resources solution. The main intent is to show how Beef can be used against a relational database (SQL Server) leveraging only Entity Framework (EF).
Also, it will demonstrate how the data can be shaped differently between the database and the entity to leverage both relational and object-oriented constructs to provide a natural consuming experience from the API that accounts for the object-relational impedence mismatch.
This sample will walkthrough an approach of adding the capabilities in a series of logical steps, versus big-bang (all at once), as this is more typical of how a developer may implement.
Beef is ostensibly the code-generation engine that ultimately takes dependencies on the following capabilities to enable the end-to-functionality and testing thereof:
- CoreEx - provides the core runtime capabilties (extends .NET core);
- UnitTestEx - provides extended unit and intra-domain integration testing;
- DbEx - provides extended database management capabilties;
- OnRamp - provides the underlying code-generation engine functionality.
Within the sample there will two primary entities exposed:
- Employee - being an employee that either is, or was, employed by the ficticous organization.
- Performance Review - being a recording of a number of performance reviews for an employee over time.
This will represent an employee within the organization, and house key data such as their name, address, phone number, gender, date of birth, start and termination dates, and a list of up to five emergency contacts.
From an endpoint perspective it will support the following.
Endpoint | Description |
---|---|
GET /employees/id |
Get employee by primary identifier. |
POST /employees |
Create a new employee. |
PUT /employees/id |
Update (replace) the existing employee (only where not terminated). |
PATCH /employees/id |
Patch the existing employee (only where not terminated). |
DELETE /employees/id |
Delete an existing employee (only where not started). |
GET /employees |
Gets employee(s) that match the selection criteria (a subset of the fields to be returned, plus support for paging). |
POST /employees/id/terminate |
Updates the employee as terminated (other endpoints do not allow termination). |
This will respresent a performance review (multiple over time), and house key data such as date, outcome, notes and reviewer.
From an endpoint perspective it will support the following.
Endpoint | Description |
---|---|
GET /reviews/id |
Get review by primary identifier. |
POST /employees/id/reviews |
Create a review for a specified employee. |
PUT /reviews/id |
Update (replace) the review. |
PATCH /reviews/id |
Patch the existing review. |
DELETE /reviews/id |
Delete an existing review. |
GET /employee/id/reviews |
Gets all review(s) for the employee (with paging support). |
CoreEx version 3.0.0
introduced monadic error-handling, often referred to as Railway-oriented programming. This is enabled via the key types of Result
and Result<T>
; please review the corresponding documentation for more detail on purpose and usage.
The Result
and Result<T>
have been integrated into the code-generated output and is leveraged within the underlying validation. This is intended to simplify success and failure tracking, avoiding the need, and performance cost, in throwing resulting exceptions.
As described earlier, this sample will walk through the implementation in a number of logical steps:
- Solution Skeleton - start by creating a VS solution from Beef template
- Employee DB - creates the
Employee
database table and related entity framework capabilities. - Employee API - creates the
Employee
entities, API and related data access logic. - Employee Test - creates the
Employee
end-to-end integration tests to validate the API and database functionality. - Employee Search - adds the
Employee
search capability and tests. - Employee Terminate - adds the
Employee
termination capability and tests. - Employee Performance Review - adds the employee
PerformanceReview
capability end-to-end, from the the database, through the APIs and corresponding testing.
The implementation so far has created the API capabilities to perform operations on the data as originally defined in the scope. This section can be skipped where the related Event-driven architecture capabilities are not required.
However, to further support the goals of an Event-driven architecture (EDA) both the publishing and subscribing of events is required, and will be largely enabled leveraging the CoreEx.Events capabilities.
The Conceptual Architecture for the solution including eventing/messaging is as follows:
The Architecture is composed of the following components:
- API - represents the HR domain API-endpoint;
- SQL - represents the HR domain data and outbox repository;
- Relay - represents the HR domain Azure Service Bus publishing relay;
- Subscriber - represents the Security domain Azure Service Bus subscriber;
- OKTA - represents the external OKTA Identity Management API-endpoints (for Employee User Accounts).
- Event-stream - represents the Azure Service Bus capabilities.
The data-flow represented is related to an Employee Termination; in that an Employee's User Account will be automatically deactivated within OKTA as a result of their termination.
The HR and Security domains are completely decoupled from each other; in that there is no run-time dependency between them - they only communicate via messages in near-realtime as enabled by the event-stream.
This EDA sample will walk through the implementation in a number of logical steps (these describe the integration of the CoreEx capabilities to enable) to achieve the end-to-end Employee's User Account deactivation:
- Transactional Outbox - enqueue events into the database.
- Service Bus Publish - dequeue events (relay) from database publishing to Azure Service Bus.
- Service Bus Subscribe - simulate an additional domain subscribing to an event (from Azure Service Bus).
The basis of the functional capabilities have been created for our fictitious solution. In the end, the developer should have a reasonable understanding of how to build a relatively complicated back-end (API and database) solution leveraging Beef as the code-generator, and CoreEx as the extended runtime.
The developer should have witnessed that reasonably complicated logic can be built using this config to code-gen to custom approach. Where the custom effort is for the most part focused on the key business value delivery; not the related boilerplate. Plus, with the UnitTestEx testing framework, how complex end-to-end intra-domain integration tests can be created to appropriately validate the underlying logic - which can easily be integrated into the developer build-test-release lifecycle.
It is acknowledged that there is a learning curve required for using Beef et al; and in time greater acceleration will be achieved as experience is gained. Please review the extended documentation and provide feedback, questions, defects, etc. via an issue to any of the repos.
Thanks and enjoy :-)