AppUser : IdentityUser 可以链接到员工实体,同时在清洁架构中保持依赖倒置的关注点分离

问题描述 投票:0回答:1

我选择在基础设施层定义这样的 ApplicationUser 类:

namespace MySolution.Infrastructure.Context
{
    // Add profile data for application users by adding properties to the ApplicationUser class
    public class ApplicationUser : IdentityUser
    {
        public EmployeeId EmployeeId { get; set; }
        public Employee Employee { get; set; }
    }

}

我还创建了一个用于将用户连接到员工的表

namespace MySolution.Infrastructure.Context
{
    public class EmployeeUserMap
    {
        public string ApplicationUserId { get; set; }
        public ApplicationUser ApplicationUser { get; set; }
        public EmployeeId EmployeeId { get; set; }
        public Employee Employee { get; set; }
    }
}

这是我的域层中的实体:


namespace MySolution.Domain.Entities
{
    public class Employee
    {
        //empty constructor
        private Employee() { } // Required by EF core
        
        //properties
        public EmployeeId Id { get; init; }
        public required VatNumber WorkplaceVAT { get; init; }
        public required string EmployeeName { get;  set; }
        public required Address Address { get;  set; }
        public required ContactInfo ContactInfo { get;  set; }
        public required UserRole Role { get; set; }
        public string? ApplicationUserId { get; set; }
        public CompanyId CompanyId { get; init; }

        //Navigational properties
        public Company Company { get; set; }

        [SetsRequiredMembers]
        public Employee(string name, ContactInfo contactInfo, Address address, VatNumber workplaceVAT, UserRole role, CompanyId companyId, string applicationUserId)
        {
            Id = EmployeeId.Create();
            EmployeeName = name ?? throw new ArgumentNullException(nameof(name));
            ContactInfo = contactInfo ?? throw new ArgumentNullException(nameof(contactInfo));
            Address = address ?? throw new ArgumentNullException(nameof(address));
            WorkplaceVAT = workplaceVAT ?? throw new ArgumentNullException(nameof(workplaceVAT));
            Role = role;
            CompanyId = companyId;
            ApplicationUserId = applicationUserId;
            Validate(this);
        }

        private static void Validate(Employee employee)
        {
            var context = new ValidationContext(employee);
            Validator.ValidateObject(employee, context, validateAllProperties : true);
        }
        public void ChangeContactDetails(ContactInfo newContactDetails)
        {
            ContactInfo = newContactDetails ?? throw new ArgumentNullException(nameof(newContactDetails));
        }
        public void ChangeAddress(Address newAddress) 
        { 
            Address = newAddress ?? throw new ArgumentNullException(nameof(newAddress)); 
        }
    }
}

我不知道如何保持域层独立,而是将 ApplicationUserId 传递给实体。我希望 Employee-ApplicationUser 之间存在一对一的关系,并且我希望能够首先创建一个 Employee 并使 applicationId 可为空,接下来我希望仅当具有相同邮件的员工存在时才能注册用户.

    public async Task RegisterUser(EditContext editContext)
    {
        var employee = await _mediator.Send(new GetEmployeeByEmailQuery(Input.Email), default);

        if (employee != null)
        {
            var user = CreateUser();

            await UserStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
            var emailStore = GetEmailStore();
            await emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);

            user.EmployeeId = employee.Id;

            var result = await UserManager.CreateAsync(user, Input.Password);

            if (!result.Succeeded)
            {
                identityErrors = result.Errors;
                return;
            }

            await UserManager.UpdateAsync(user);

            employee.ApplicationUserId = user.Id;

            await _mediator.Send(new UpdateEmployeeCommand(new VatNumber(employee.WorkplaceVat), employee.Name, AddressMapper.ToValueObject(employee.Address), ContactInfoMapper.ToValueObject(employee.ContactInfo), employee.ApplicationUserId!, employee.Role, employee.CompanyId), default);

            Logger.LogInformation("User created a new account with password.");



            var userId = await UserManager.GetUserIdAsync(user);
            var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = NavigationManager.GetUriWithQueryParameters(
                NavigationManager.ToAbsoluteUri("Account/ConfirmEmail").AbsoluteUri,
                new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code, ["returnUrl"] = ReturnUrl });

            await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

            if (UserManager.Options.SignIn.RequireConfirmedAccount)
            {
                RedirectManager.RedirectTo(
                    "Account/RegisterConfirmation",
                    new() { ["email"] = Input.Email, ["returnUrl"] = ReturnUrl });
            }

            await SignInManager.SignInAsync(user, isPersistent: false);
            RedirectManager.RedirectTo(ReturnUrl);
        }
        else
        {
            identityErrors = new List<IdentityError> { new IdentityError { Description = "Employee not found for the provided email." } };
        }
    }

.net asp.net-core asp.net-identity clean-architecture
1个回答
0
投票

要在链接 Employee 和 ApplicationUser 时保持域独立性,您可以尝试以下方法:

1.在领域层让员工远离基础设施依赖。包含一个可为空的 ApplicationUserId 并添加一个方法来链接它。

2.在基础设施层中,在 DbContext 中配置 EF Core 以实现一对一关系。

3.在Service层处理注册逻辑。首先,创建 Employee,然后注册 ApplicationUser,将 ApplicationUserId 链接到 Employee,并更新这两个实体。这确保了服务层中的域完整性和正确链接

© www.soinside.com 2019 - 2024. All rights reserved.