using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; using Timeline.Models; namespace Timeline.Services { public interface IUserDetailService { /// /// Get the nickname of user. /// /// The username to get nickname of. /// The user's nickname. Null if not set. /// Thrown if is null or empty. /// Thrown if user doesn't exist. Task GetUserNickname(string username); /// /// Get the detail of user. /// /// The username to get user detail of. /// The user detail. /// Thrown if is null or empty. /// Thrown if user doesn't exist. Task GetUserDetail(string username); /// /// Update the detail of user. This function does not do data check. /// /// The username to get user detail of. /// The detail to update. Can't be null. Any null member means not set. /// Thrown if is null or empty or is null. /// Thrown if user doesn't exist. Task UpdateUserDetail(string username, UserDetail detail); } public class UserDetailService : IUserDetailService { private readonly ILogger _logger; private readonly DatabaseContext _databaseContext; public UserDetailService(ILogger logger, DatabaseContext databaseContext) { _logger = logger; _databaseContext = databaseContext; } private async Task CreateEntity(long userId) { var entity = new UserDetailEntity() { UserId = userId }; _databaseContext.UserDetails.Add(entity); await _databaseContext.SaveChangesAsync(); _logger.LogInformation("An entity is created in user_details."); return entity; } // Check the existence of user detail entry private async Task CheckAndInit(long userId) { var detail = await _databaseContext.UserDetails.Where(e => e.UserId == userId).SingleOrDefaultAsync(); if (detail == null) { detail = await CreateEntity(userId); } return detail; } public async Task GetUserNickname(string username) { var userId = await DatabaseExtensions.CheckAndGetUser(_databaseContext.Users, username); var detail = await _databaseContext.UserDetails.Where(e => e.UserId == userId).Select(e => new { e.Nickname }).SingleOrDefaultAsync(); if (detail == null) { var entity = await CreateEntity(userId); return null; } else { var nickname = detail.Nickname; return string.IsNullOrEmpty(nickname) ? null : nickname; } } public async Task GetUserDetail(string username) { var userId = await DatabaseExtensions.CheckAndGetUser(_databaseContext.Users, username); var detailEntity = await CheckAndInit(userId); return UserDetail.From(detailEntity); } public async Task UpdateUserDetail(string username, UserDetail detail) { if (detail == null) throw new ArgumentNullException(nameof(detail)); var userId = await DatabaseExtensions.CheckAndGetUser(_databaseContext.Users, username); var detailEntity = await CheckAndInit(userId); if (detail.Nickname != null) detailEntity.Nickname = detail.Nickname; if (detail.QQ != null) detailEntity.QQ = detail.QQ; if (detail.Email != null) detailEntity.Email = detail.Email; if (detail.PhoneNumber != null) detailEntity.PhoneNumber = detail.PhoneNumber; if (detail.Description != null) detailEntity.Description = detail.Description; await _databaseContext.SaveChangesAsync(); _logger.LogInformation("An entity is updated in user_details."); } } public static class UserDetailServiceCollectionExtensions { public static void AddUserDetailService(this IServiceCollection services) { services.AddScoped(); } } }