using CORE.Domain;
using CORE.Services;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Users.APP.Domain;
using Users.APP.Features.Users;
namespace Users.APP.Features.Statuses
{
// Request properties are created according to the data that
// will be retrieved from APIs.
public class StatusQueryRequest : Record,
IRequest<IQueryable<StatusQueryResponse>>
{
}
// Response properties are created according to the data to be
// presented in API responses.
public class StatusQueryResponse : Record
{
// Copy all the non navigation properties from Status entity.
public string Title { get; set; }
// Add the new properties ending with R declaring Response
// for custom properties or formatted string value properties.
// Way 1: Map primitive type properties for basic information.
public string UserNamesR { get; set; }
// Property value for the count of the users of the status.
public int UserCountR { get; set; }
// Way 2: Map complex type object for more information.
// Either Way 1, Way 2 or both can be used.
public List<UserQueryResponse> UsersR { get; set; }
}
// StatusQueryHandler inherits the DbService class for Status entity type,
// therefore Status entity database operations of the DbService
// class can be used in this class.
// StatusQueryHandler also implements the Mediator IRequestHandler
// interface for StatusQueryRequest and IQueryable of StatusQueryResponse
// types, therefore IRequestHandler interface's Handle method
// definition can be implemented for types StatusQueryRequest and
// IQueryable of StatusQueryResponse in this class, which will be used by
// the related controller's action.
public class StatusQueryHandler : DbService<Status>,
IRequestHandler<StatusQueryRequest, IQueryable<StatusQueryResponse>>
{
// Constructor that passes the injected DbContext instance
// to the DbService base class constructor.
public StatusQueryHandler(DbContext db) : base(db)
{
}
// Overrides the base virtual DbQuery method to include
// User entities data to the query to be used in the Handle
// method and orders the query by Status entity Title
// property ascending.
// The overridden DbQuery method can be used in any method
// below by invoking the DbQuery method.
protected override IQueryable<Status> DbQuery()
{
return base.DbQuery() // "select * from Statuses"
// entity query.
.Include(s => s.Users) // Includes the relational
// User entities data to the query
// by using left outer join.
.OrderBy(s => s.Title); // Orders the query by Title
// property of the Status entity
// in ascending order.
// OrderByDescending can be used
// for descending order.
// s: Status entity delegate.
}
// Gets the updated query from the DbQuery method then projects
// the Status entities to status query responses and returns the
// StatusQueryResponse query.
// The returned query can be executed by invoking ToListAsync,
// SingleOrDefaultAsync, FirstOrDefaultAsync, AnyAsync, etc.
// LINQ (Language Integrated Query) methods and then the
// returned result can be used.
public Task<IQueryable<StatusQueryResponse>> Handle(
StatusQueryRequest request, CancellationToken cancellationToken)
{
var query = DbQuery().Select(s => new StatusQueryResponse
{
// Map each Status entity property to
// StatusQueryResponse property.
Id = s.Id,
Title = s.Title,
// Way 1: Map primitive type data for basic information.
UserNamesR = string.Join(", ", s.Users.Select(u => u.UserName)),
// string type's Join method gets a seperator as the first
// parameter and gets a collection of strings as the second
// parameter then concatenates each string item in collection
// with the seperator and returns a string.
UserCountR = s.Users.Count,
// Count property of the List type returns the item count
// of the collection.
// Way 2: Map complex type object for more information.
// Either Way 1, Way 2 or both can be used.
UsersR = s.Users.Select(u => new UserQueryResponse
{
// Map each User entity property to
// StatusQueryResponse’s UserQueryResponse property.
Id = u.Id,
UserName = u.UserName,
PasswordR = new string('*', u.Password.Length),
// Let's hide the password with *.
FirstName = u.FirstName,
LastName = u.LastName,
FullNameR = u.FirstName + " " + u.LastName,
// Concatenate the first name and last name
// with a white space for the full name.
RegistrationDate = u.RegistrationDate,
BirthDate = u.BirthDate,
Gender = u.Gender,
IsOnline = u.IsOnline,
Score = u.Score,
StatusId = u.StatusId
}).ToList()
});
// s: Status entity delegate, u: User entity delegate.
return Task.FromResult(query);
}
}
}