Skip to content

Latest commit

 

History

History

My.Hr

My.Hr

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 both direct ADO.NET (with stored procedures) and Entity Framework (EF) where applicable.

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 composition

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.

Scope

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.

Employee

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).

Performance Review

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).

Solution skeleton

This solution should be created using the solution template capability, following the getting started guide.

The following four commands should be invoked to create the solution structure. Start in a folder where the solution should reside. To simplify the ongoing copy and paste activities within this sample it is highly recommended that the My.Hr naming convention below is used.

dotnet new install beef.template.solution --nuget-source https://api.nuget.org/v3/index.json
mkdir My.Hr
cd My.Hr
dotnet new beef --company My --appname Hr --datasource SqlServer

The following solution structure will have been generated. Open My.Hr.sln in Visual Studio.

└── My.Hr               # Solution that references all underlying projects
  └── Testing
    └── My.Hr.Test      # Unit and intra-integration tests
  └── Tools
    └── My.Hr.CodeGen   # Entity and Reference Data code generation console
    └── My.Hr.Database  # Database code generation console
  └── My.Hr.Api         # API end-point and operations
  └── My.Hr.Business    # Core business logic components
  └── My.Hr.Common      # Common / shared components

Note: Code generation should not be performed before updating the corresponding YAML files as described in the next sections. Otherwise, extraneous files will be generated that will then need to be manually removed.

Also, any files that start with Person (being the demonstration entity) should be removed (deleted) from their respective projects as they are encountered. This then represents the baseline to build up the solution from.


Railway-oriented programming

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.


Implementation steps

As described earlier, this sample will walk through the implementation in a number of logical steps:

  1. Employee DB - creates the Employee database table and related stored procedures.
  2. Employee API - creates the Employee entities, API and related data access logic.
  3. Employee Test - creates the Employee end-to-end integration tests to validate the API and database functionality.
  4. Employee Search - adds the Employee search capability and tests.
  5. Employee Terminate - adds the Employee termination capability and tests.
  6. Employee Performance Review - adds the employee PerformanceReview capability end-to-end, from the the database, through the APIs and corresponding testing.

Conclusion

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 :-)