using APP.Domain;
using APP.Models;
using CORE.Models;
using CORE.Services;
using Microsoft.EntityFrameworkCore;
namespace APP.Services
{
// StatusService inherits the DbService class for Status entity type,
// therefore Status entity database operations of the DbService
// class can be used in this class.
// StatusService also implements the IService interface for
// StatusRequest and StatusResponse types, therefore IService method
// definitions can be implemented for types StatusRequest and
// StatusResponse in this class, which will be used by
// the controller actions.
public class StatusService : DbService<Status>,
IService<StatusRequest, StatusResponse>
{
// Constructor that passes the injected DbContext instance
// to the DbService base class constructor.
public StatusService(DbContext db) : base(db)
{
}
// Overrides the base virtual DbQuery method to include
// User entities data to the query to be used in the
// Query and Remove methods and orders the query by Status
// entity Title. 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 responses and returns the
// status response query.
// Example query: "select Title, UserNamesR, UserCountR from Statuses
// left outer join Users on Statuses.Id = Users.StatusId order by
// Title". where Title, UserNamesR and UserCountR are the
// StatusResponse properties.
// The returned query can be executed by invoking
// ToList, SingleOrDefault, FirstOrDefault, Any, etc. LINQ
// (Language Integrated Query) methods and then the returned result
// can be used.
// This projected query by the Select LINQ method will be used by
// the List and Single methods of the IService interface.
public IQueryable<StatusResponse> Query()
{
return DbQuery()
.Select(s => new StatusResponse
{
// Map each Status entity property to
// StatusResponse 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 UserResponse
{
// Map each User entity property to
// StatusResponse's UserResponse 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.
}
// Gets the Status entity by ID then returns a mapped
// StatusRequest instance from the found Status entity.
public StatusRequest Edit(int id)
{
var statusEntity = DbSingle(id);
// Example SQL: "select * from Statuses where Id = 5".
// statusEntity may be null since the OrDefault version
// of the Single method is used. If Single method
// was used, an exception would be thrown.
if (statusEntity is null) // if (statusEntity == null) can
// also be written.
return null;
// Map each Status entity property to StatusRequest property
// and return the StatusRequest instance.
return new StatusRequest
{
Id = statusEntity.Id,
Title = statusEntity.Title
};
}
// Checks whether the status with the same trimmed and
// case sensitive title exists in the Statuses database table
// first. If it doesn't exist, inserts the Status entity
// mapped from the StatusRequest instance to the Statuses
// database table.
public CommandResponse Add(StatusRequest request)
{
if (DbQuery()
.Any(s => s.Title == request.Title.Trim()))
return Error("Status with the same title exists!");
// s: Status entity delegate.
// Trim method removes white space characters in the
// beginning and at the end.
// Create a new Status entity instance from the
// StatusRequest instance then insert the entity in the
// Statuses database table (second save default parameter
// of the DbAdd method is true therefore changes of the
// DbSets are commited to the related database tables).
var statusEntity = new Status
{
Title = request.Title.Trim()
};
DbAdd(statusEntity);
// Entity's Id value will be updated by the database
// after the insert operation.
return Success(statusEntity.Id, "Status created successfully.");
}
// Checks whether the status with the same trimmed and
// case sensitive title other than the status request record
// exists in the Statuses database table first.
// If the entity doesn't exist, gets the Status entity by ID
// from the table, then updates the Status entity properties
// from status request properties and finally updates the
// Status entity in the Statuses database table.
public CommandResponse Update(StatusRequest request)
{
if (DbQuery()
.Any(s => s.Id != request.Id &&
s.Title == request.Title.Trim()))
return Error("Status with the same title exists!");
// Get the Status entity by ID from the Statuses database
// table and check whether it is null or not.
var statusEntity = DbSingle(request.Id);
if (statusEntity is null)
return Error("Status not found!");
// Update Status entity properties from status request properties.
// Then update the entity in the Statuses database table (second save
// default parameter of the DbUpdate method is true
// therefore changes of the DbSets are commited to the related
// database tables).
statusEntity.Title = request.Title.Trim();
DbUpdate(statusEntity);
return Success(statusEntity.Id, "Status updated successfully.");
}
// Gets the Status entity by ID from the Statuses database table.
// If the entity exists, checks if the Status entity has
// relational User entities. If not, deletes the entity from the
// Statuses database table.
public CommandResponse Remove(int id)
{
// Get the Status entity by ID from the Statuses database table
// and check whether it is null or not.
var statusEntity = DbSingle(id);
if (statusEntity is null)
return Error("Status not found!");
// Check if the Status entity has relational User entities.
if (statusEntity.Users.Any()) // if (statusEntity.Users.Count > 0)
// can also be written.
return Error("Status has relational users!");
// Delete the Status entity from the Statuses database table
// (second save default parameter of the DbRemove method is
// true therefore changes of the DbSets are commited to
// the related database tables).
DbRemove(statusEntity);
return Success(statusEntity.Id, "Status deleted successfully.");
}
}
}