简体   繁体   English

应该在DTO模型还是在目标实体模型中执行计算?

[英]Should one perform a calculation in a DTO model or in the destination entity model?

I'm currently creating various entities in ASP.NET Core 2.2 with accompanying DTOs for a Web API. 我目前正在ASP.NET Core 2.2中创建各种实体,并附带用于Web API的DTO。 The client application would submit a DTO object to the relevant controller action. 客户端应用程序将向相关的控制器操作提交DTO对象。 There using the AutoMapper, this would be mapped from the DTO object to an entity object. 在那里使用AutoMapper,它将从DTO对象映射到实体对象。 The resulting entity object would be saved to an entity framework repository which at this moment would be a Microsoft SQL database. 生成的实体对象将保存到一个实体框架存储库,该存储库此时将是Microsoft SQL数据库。 For brevity let's assume that the time zones would be irrelevant in this case. 为简便起见,我们假设在这种情况下时区是不相关的。

I was just wondering which approach would be more appropriate or to even have not have the calculation in either the DTO or Entity but perhaps within the Controller action. 我只是想知道哪种方法更合适,或者甚至不在DTO或Entity中但可能在Controller动作中都没有计算。

Note: The actual code is more complicated and involves various calculations for various properties, I have simply chosen a simple case to illustrate my question. 注意:实际代码更复杂,并且涉及各种属性的各种计算,我仅选择一个简单的案例来说明我的问题。

Approach #1 方法1

// Entity
public class EventTimes
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public decimal TotalHours => (decimal)(End - Start).TotalHours;
}

// DTO
public class EventTimesDto
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}

Approach #2 方法#2

// Entity
public class EventTimes
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public decimal TotalHours { get; set; }
}

// DTO
public class EventTimesDto
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public decimal TotalHours => (decimal)(End - Start).TotalHours;
}

It depends on the actual context. 这取决于实际情况。 Is the EventTimes an entity or is it rather part of your domain model? EventTimes是实体还是它是域模型的一部分?

Either way I would not put it in the dto as this is really just for transferring data, so it should not contain any logic (besides maybe validation). 无论哪种方式,我都不会将其放在dto中,因为这实际上只是用于传输数据,因此它不应包含任何逻辑(可能还包括验证)。

Since the responsibility for this calculation is neither part of the dto, nor the entity model's, you could put the heavy calculation in an EventTimesCalculator something like this: 由于此计算的职责既不是dto的一部分,也不是实体模型的职责,因此您可以将繁重的计算放入EventTimesCalculator ,如下所示:

public class EventTimesCalculator
{
    public decimal CalculateTotalHours(EventTimes eventTimes)
    {
        return (decimal)(eventTimes.End - eventTimes.Start).TotalHours;
    }
}

If the EventTimes is part of your business layer / domain model, a more appropriate way would be to have a GetTotalHours() method inside of the model, instead of a property. 如果EventTimes是您的业务层/域模型的一部分,则更合适的方法是在模型内部使用GetTotalHours()方法而不是属性。 Of course you would need to map it to the persistence model, if you want to save that information. 当然,如果要保存该信息,则需要将其映射到持久性模型。 Then again, since this information can be calculated, you don't need to persist it at all, mainly because the logic might change (example: exclude breaks, interruptions or such). 再说一次,由于可以计算出此信息,因此根本不需要保留它,主要是因为逻辑可能会更改(例如:排除中断,中断等)。

My advice is to stop thinking in terms of database entities (which I assume you meant above). 我的建议是停止对数据库实体的思考(我假设您在上文中已经说过)。

At the end, it's rather a detail where you put the calculation logic, more importantly is to have a straight forward design. 最后,它是放置计算逻辑的一个细节,更重要的是要有一个简单的设计。 Is the application monolithic put that logic in your layer that contains the business logic. 是应用程序整体式地将逻辑放在包含业务逻辑的层中。 Is it a distributed architecture, handle the calculation for the model in the service responsible for Eventing. 它是一个分布式体系结构,在负责Eventing的服务中处理模型的计算。 Is it just a small API, keep it simple, put it where you or your team would expect it the most. 它只是一个小的API,请保持简单,将其放在您或您的团队最期望的位置。

Iam using second approach because entity can contain raw which can be modified by application flow. 我使用第二种方法,因为实体可以包含可以由应用程序流程修改的原始数据。

Common pattern Data transfer object (DTO) is exactly what you want for transport data between application layers which can transform data into desired output. 通用模式数据传输对象(DTO)正是您想要在应用程序层之间传输数据的对象 ,可以将数据转换为所需的输出。 Dto can't contain business logic but also can "prepare", "reduce" data which destination need. Dto不能包含业务逻辑,但也可以“准备”,“减少”目的地需要的数据。

For example: 例如:
If presentation layer need totalHours Iam doing this in model instead of entity. 如果表示层需要totalHours Iam,则在模型中而不是实体中执行此操作。 Doing this in entity it would lead for endless modifications. 整体执行此操作将导致无休止的修改。

Another example can be user's full name Firstname , Lastname , AcademicDegree . 另一个示例可以是用户的全名FirstnameLastnameAcademicDegree

Entity can hold all of them but 实体可以容纳所有人,但

  • one presentation need [academic degree] [firstname] [lastname] and 一个演示文稿需要[学历] [名字] [姓氏]和
  • second need data in different format such as [lastname] [firstname] [academic degree]. 第二需求数据采用不同格式,例如[姓氏] [名字] [学历]。


It is good keep property that make desired format in specific DTO instead of entity IMHO. 好的保持属性可以在特定的DTO中代替实体恕我直言,从而形成所需的格式。

I in ASP.NET Core do this in onion architecture and view models and from my experience is easy to manage, change, prepare data for front-end or layers instead of change something in core. 我使用ASP.NET Core在洋葱体系结构和视图模型中进行此操作,根据我的经验,它易于管理,更改,为前端或层准备数据,而不是更改核心内容。

If someone disagrees with me please let comment I like learn something new. 如果有人不同意我的意见,请发表评论,我喜欢学习新知识。

Hope it helps 希望能帮助到你

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM