In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article mainly introduces the example analysis of data transmission objects and application services in the ABP framework, which has a certain reference value, and interested friends can refer to it. I hope you will gain a lot after reading this article.
Data transfer object (DTOs)
Data transfer objects (Data Transfer Objects) are used for data transmission in the application layer and presentation layer.
The presentation layer passes in the data transfer object (DTO) to invoke an application service method, and then the application service executes some specific business logic through the domain object and returns DTO to the presentation layer. In this way, the presentation layer and the domain layer are completely separated. In applications with good layering, the presentation layer does not directly use domain objects (repositories, entities).
1. The role of data transfer objects:
Creating a DTO for each application service method seems like a tedious and time-consuming task. But if you use them correctly, this will save your project. Why is that?
(1) Abstract domain layer (Abstraction of domain layer)
In the presentation layer, the data transfer object abstracts the domain object effectively. In this way your layers will be properly isolated. Even when you want to completely replace the presentation layer, you can continue to use the existing application layer and domain layer. Instead, you can rewrite the domain layer and modify the database structure, entities, and ORM framework, but you don't need to make any changes to the presentation layer, as long as your application layer hasn't changed.
(2) data hiding (Data hiding)
Imagine that you have a User entity with attributes Id, Name, EmailAddress, and Password. If the return type of the GetAllUsers () method of UserAppService is List. This way anyone can check everyone's password, even if you don't print it on the screen. It's not just a security issue, it's also about data hiding. The application service should only return what is needed in the presentation layer, just right.
(3) serialization & lazy loading (Serialization & lazy load problems)
When you return data (objects) to the presentation layer, the data may be serialized. For example, in an Action that returns a MVC of Json, your object needs to be serialized into JSON and sent to the client. Returning the entity directly to the presentation layer may cause trouble.
In a real project, entities refer to other entities. The User entity references the Role entity. So, when you serialize User, Role will also be serialized. And Role also has a List and Permission also quotes PermissionGroup and so on. . Can you imagine that these objects will be serialized? This is likely to cause the entire database data to be serialized unexpectedly. So how to solve it? Mark attributes as non-serializable? No, because you don't know when a property should be serialized and when it shouldn't be serialized. So in this case, it is a good choice to return a data transfer object that can be securely serialized and customized.
Almost all ORM frameworks support lazy loading. It is loaded only when you need to load the entity. For example, the User type refers to the Role type. When you get User from the database, the Role property is not populated. Role is loaded from the database only when you read the Role property for the first time. Therefore, when you return such an entity to the presentation layer, it is easy to cause side effects (loading from the database). If the serialization tool reads the entity, it will read all the properties recursively so that your entire database will be read.
There are more problems with using entities in the presentation layer. The best solution is that the presentation layer should not reference any assembly that contains the domain layer.
2.DTO convention & verification
ABP provides powerful support for data transfer objects. It provides some related (Conventional) types & interfaces and provides recommendations for DTO naming and usage conventions. When you use DTO,ABP like here, it will automate some tasks and make it easier for you.
An example (Example)
Let's look at a complete example. We want to write an application service method to search people based on name and return a list of people. The Person entity code is as follows:
Public class Person: Entity {public virtual string Name {get; set;} public virtual string EmailAddress {get; set;} public virtual string Password {get; set;}}
First, we define an application service interface:
Public interface IPersonAppService: IApplicationService {SearchPeopleOutput SearchPeople (SearchPeopleInput input);}
ABP recommends that naming input/ouput objects is similar to MethodNameInput/MethodNameOutput, where Input and Output need to be defined separately for each application service method. Even if your method receives or returns only one value, it is best to create the corresponding DTO type. In this way, your code will be more extensible, and you can add more properties without changing the signature of the method, which will not destroy the existing client application.
Of course, the return value of the method may be void, and then you add a return value without destroying the existing application. If your method does not require any parameters, then you do not need to define an Input Dto. But creating an Input Dto may be a better solution, because the method may require a parameter in the future. Of course, it's up to you to create it or not. The Input and Output DTO types are defined as follows:
Public class SearchPeopleInput: IInputDto {[StringLength (40, MinimumLength = 1)] public string SearchedName {get; set;}} public class SearchPeopleOutput: IOutputDto {public List People {get; set;}} public class PersonDto: EntityDto {public string Name {get; set;} public string EmailAddress {get; set;}
Verification: as a convention, Input DTO implements the IInputDto interface and Output DTO implements the IOutputDto interface. When you declare the IInputDto parameter, ABP will automatically verify the validity of the method before it is executed. This is similar to the ASP.NET MVC authentication mechanism, but note that the application service is not a Controller. ABP intercepts it and checks the input. Check the DTO validation (DTO Validation) documentation for more information. EntityDto is a simple type that has the same Id attribute as an entity. You can use the generic version of your entity Id if it is not int. EntityDto also implements the IDto interface. You can see that PersonDto does not contain the Password attribute because the presentation layer does not need it.
Before going any further, let's implement IPersonAppService:
Public class PersonAppService: IPersonAppService {private readonly IPersonRepository _ personRepository; public PersonAppService (IPersonRepository personRepository) {_ personRepository = personRepository;} public SearchPeopleOutput SearchPeople (SearchPeopleInput input) {/ / get entity var peopleEntityList = _ personRepository.GetAllList (person = > person.Name.Contains (input.SearchedName)) / / convert to DTO var peopleDtoList = peopleEntityList .Select (person = > new PersonDto {Id = person.Id, Name = person.Name, EmailAddress = person.EmailAddress}) .ToList (); return new SearchPeopleOutput {People = peopleDtoList};}
We get the entity from the database, convert the entity to DTO, and return output. Note that we did not manually check the validity of the Input data. ABP automatically validates it. ABP even checks whether Input is null and throws an exception if it is null. This prevents us from manually checking the validity of the data in each method.
But you probably don't like to manually convert Person entities to PersonDto. This is really a boring job. This is especially true when Peson entities contain a large number of attributes.
Automatic mapping between 3.DTO and entities
Fortunately, there are some tools that can make mapping (transformation) very simple. AutoMapper is one of them. You can add it to your project through nuget. Let's use AutoMapper to override the SearchPeople method:
Public SearchPeopleOutput SearchPeople (SearchPeopleInput input) {var peopleEntityList = _ personRepository.GetAllList (person = > person.Name.Contains (input.SearchedName)); return new SearchPeopleOutput {People = Mapper.Map (peopleEntityList)};}
That's the whole code. You can add more attributes to entities and DTO, but the conversion code remains the same. Before that, there's only one thing you need to do: mapping.
Mapper.CreateMap ()
AutoMapper creates the code for the mapping. In this way, dynamic mapping does not become a performance problem. It's so fast and convenient. AutoMapper creates the PersonDto from the Person entity and assigns values to the attributes of the PersonDto according to the naming convention. Naming conventions are configurable and flexible. You can also customize the mapping and use more features, check the AutoMapper documentation for more information.
4. Use attributes and extension methods to map (Mapping using attributes and extension methods)
ABP provides several attributes and extension methods to define mappings. To use it you need to add Abp.AutoMapper to your project through nuget. There are two ways to map using the AutoMap feature (attribute), one is to use AutoMapFrom and AutoMapTo. The other is to use the MapTo extension method. Examples of defining mappings are as follows:
[AutoMap (typeof (MyClass2))] / / define mapping (so there are two ways to map) public class MyClass1 {public string TestProp {get; set;}} public class MyClass2 {public string TestProp {get; set;}}
Then you can map through the MapTo extension method:
Var obj1 = new MyClass1 {TestProp = "Test value"}; var obj2 = obj1.MapTo (); / / creates a new MyClass2 object and assigns the value of obj1.TestProp to the TestProp property of the new MyClass2 object. The above code creates a new MyClass2 object based on MyClass1. You can also map existing objects as follows: var obj1 = new MyClass1 {TestProp = "Test value"}; var obj2 = new MyClass2 (); obj1.MapTo (obj2); / / set the properties of obj2 according to obj1
5. Secondary interfaces and types
ABP also provides some auxiliary interfaces that define commonly used standardized attributes.
ILimitedResultRequest defines the MaxResultCount attribute. So you can implement this interface on your Input DTO to limit the number of result sets.
IPagedResultRequest extends ILimitedResultRequest by adding the SkipCount attribute. So we implement this interface in SearchPeopleInput for paging:
Public class SearchPeopleInput: IInputDto, IPagedResultRequest {[StringLength (40, MinimumLength = 1)] public string SearchedName {get; set;} public int MaxResultCount {get; set;} public int SkipCount {get; set;}}
For paging requests, you can use the Output DTO that implements IHasTotalCount as the return result. Standardized attributes help us create reusable code and specifications. You can view other interfaces and types under the Abp.Application.Services.Dto namespace.
Application service
Application services are used to expose domain (business) logic to the presentation layer. The presentation layer invokes the application service by passing in the DTO (data transfer object) parameters, while the application service executes the corresponding business logic through the domain object and returns the DTO to the presentation layer. Therefore, the presentation layer and the domain layer will be completely isolated. In an ideal hierarchical project, the presentation layer should never directly access domain objects.
1.IApplicationService interface
In ABP, an application service needs to implement the IApplicationService interface. The best practice is to create an interface for each application service. So, let's first define an application service interface, as follows:
Public interface IPersonAppService: IApplicationService {void CreatePerson (CreatePersonInput input);}
IPersonAppService has only one method, which will be called by the presentation layer to create a new Person. CreatePersonInput is a DTO object, as follows:
Public class CreatePersonInput: IInputDto {[Required] public string Name {get; set;} public string EmailAddress {get; set;}}
Next, we implement the IPersonAppService interface:
Public class PersonAppService: IPersonAppService {private readonly IRepository _ personRepository; public PersonAppService (IRepository personRepository) {_ personRepository = personRepository;} public void CreatePerson (CreatePersonInput input) {var person = _ personRepository.FirstOrDefault (p = > p.EmailAddress = = input.EmailAddress); if (person! = null) {throw new UserFriendlyException ("There is already a person with given email address");} person = new Person {Name = input.Name, EmailAddress = input.EmailAddress}; _ personRepository.Insert (person);}}
Here are a few important tips:
PersonAppService performs database operations through IRepository. It is generated by constructor injection patterns. We used dependency injection here.
PersonAppService implements IApplicationService (inherits IApplicationService through IPersonAppService). ABP automatically registers it with the dependency injection system and can be injected into other types for use.
The CreatePerson method requires a parameter of type CreatePersonInput. This is a DTO as input, which will be automatically verified by ABP to validate its data. You can check the DTO and data validation (Validation) documents for details.
two。 Application service type
Application Services (Application Services) need to implement the IApplicationService interface. Of course, you can choose to inherit your application service (Application Services) from the ApplicationService base class, so your application service will naturally implement the IApplicationService interface. The ApplicationService base class provides convenient logging and localization capabilities. It is recommended that you create an application service base class for your application that inherits from the ApplicationService type. In this way, you can add some common functions to provide to all your application services. An example of an application service is as follows:
Public class TaskAppService: ApplicationService, ITaskAppService {public TaskAppService () {LocalizationSourceName = "SimpleTaskSystem";} public void CreateTask (CreateTaskInput input) {/ / log, Logger is defined in ApplicationService Logger.Info ("Creating a new task with description:" + input.Description); / / get localized text (L is LocalizationHelper.GetString (...) Var text = L ("SampleLocalizableTextKey"); / / TODO: Add new task to database... }}
In this case, we define LocalizationSourceName in the constructor, but you can define it in the base class so that you don't need to define it in each specific application service. Check out the logging (logging) and localization (localization) documents for more information.
Thank you for reading this article carefully. I hope the article "sample Analysis of data transfer objects and Application Services in ABP Framework" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.