在大型项目中,将整个项目拆分成多个较小的模块或域是常见的做法。这样做虽然有助于提高项目的可维护性和可扩展性,但同时也带来了一个新的问题:这些模块或域之间如何进行通信?因为某些业务流程可能需要跨越多个模块。本文将探讨如何解决这一问题。
在本系列文章中,模块和域可以互换使用,但需要注意的是,一个模块可以包含多个域,并且作为一个单体应用运行。因此,可以以类似的方式应用模块和域的规则。
根据新的需求,需要让员工能够登录系统,这意味着系统应该在“创建新员工”的过程中创建一个新的登录账户。这个登录功能将来也可以被其他模块重用,比如客户模块等。
让在“添加新员工”的界面中添加两个新字段:电子邮件和密码。
接下来,需要更新StaffHandler类,修改CreateStaffRequest如下:
public class CreateStaffRequest : IBaseCommand
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public CreateStaffRequest(string firstName, string lastName, string email, string password)
{
this.FirstName = firstName;
this.LastName = lastName;
this.Email = email;
this.Password = password;
}
}
然后,需要更新StaffCommandHandler类中的Handle方法:
public CreateStaffResponse Handle(CreateStaffRequest command)
{
this.Validate(command);
IAccountFacade accountFacade = IoC.Container.Resolve();
using (IUnitOfWork uow = this.CreateUnitOfWork<TinyERP.HRM.Aggregate.Staff>())
{
CreateAccountRequest createAccountRequest = new CreateAccountRequest(command.FirstName, command.LastName, command.Email, command.Password, command.Password);
createAccountRequest.Roles.Add(new Role(SecurityRoleType.Administrator, SecurityRoleType.Administrator, SecurityRoleType.Administrator, Modules.All, TinyERP.Common.ItemStatus.Active));
CreateAccountResponse createAccountResponse = accountFacade.CreateAccount(createAccountRequest);
TinyERP.HRM.Aggregate.Staff staff = new Aggregate.Staff();
staff.UpdateBasicInfo(command);
staff.UpdateAccount(createAccountResponse.AccountId);
IStaffRepository repository = IoC.Container.Resolve<IStaffRepository>(uow);
repository.Add(staff);
uow.Commit();
staff.PublishEvents();
return ObjectHelper.Cast<CreateStaffResponse>(staff);
}
}
在代码的第4、6、7、8行,调用了安全模块来创建一个新的登录账户,并使用“CreateStaffRequest”中提供的信息。然后,这个账户的引用将作为员工聚合的部分信息进行更新。
对于TinyERP.Security包,请从NuGet包管理器中安装。有关更多信息,请访问。
需要为TinyERP.Security提供连接字符串。由于它使用了CQRS模式,因此需要配置读写数据库(MSSQL和MongoDB)。将以下配置添加到“configuration.debug.config\aggregates”部分:
<add name="TinyERP.Security.Share.Context.ISecurityQueryDbContext" repoType="MongoDb" connectionStringName="DefaultMongoDb">
</add>
<add name="TinyERP.Security.Share.Context.ISecurityDbContext" repoType="MSSQL" connectionStringName="DefaultMSSQL">
</add>
配置文件的结果类似于:
<aggregates>
<add name="TinyERP.HRM.Context.IHRMQueryContext" repoType="MongoDb" connectionStringName="DefaultMongoDb">
</add>
<add name="TinyERP.HRM.Context.IHRMContext" repoType="MSSQL" connectionStringName="DefaultMSSQL">
</add>
<add name="TinyERP.Security.Share.Context.ISecurityQueryDbContext" repoType="MongoDb" connectionStringName="DefaultMongoDb">
</add>
<add name="TinyERP.Security.Share.Context.ISecurityDbContext" repoType="MSSQL" connectionStringName="DefaultMSSQL">
</add>
</aggregates>
请确保输入正确的repoType值,目前可以是“MSSQL”或“MongoDb”中的一个。将来可以支持更多的存储库,如RavenDb、ElasticSearch、Json文件、Azure Blob等。
编译并再次运行应用程序。UI界面看起来如下:
不用担心缺少“确认密码”字段,目前这不是很重要的。点击保存并返回到“员工”页面:
这与之前的部分相同。让检查MSSQL数据库,有两张新表名为App_Security_User_Roles和App_Security_Users。这些是由TinyERP.Security自动生成的,打开这些表,有:
有两个用户:
contact@tranthanhtu.vn:由系统创建,附加了很多角色。查看所有带有userId为"ECB06DF4-CC65-4134-9E44-EC1AFC9EF3EF"的角色。
tu.tran@email.com:这是刚刚创建的新登录账户。
在mongodb中,打开AccountSummary,有:
可以看到,在mongodb(读取站点)中有一个AccountSummary记录包含了与账户相关的所有必要信息。因此在未来,不需要在表之间进行连接来获取这些信息,这也提高了系统的性能。
应用程序应该被划分为更小的模块/域。
每个模块/域应该有一个单一的目的。
每个模块/域将管理其行为/数据,并应该与其他模块/域隔离。
每个模块/域应该通过单一的公共接口访问其他模块/域中的数据。