Dto 和域实体。我是否正确创建了 dto?

发布于 2024-09-13 14:57:06 字数 1690 浏览 7 评论 0原文

我有以下域实体:

public class CartItem
{
    public virtual Guid Id { get; set; }
    public virtual Guid SessionId  { get; set; }
    public virtual int Quantity  { get; set; }
    public virtual Product Product  { get; set; }
}

我有以下 DTO:

public class CartItemDTO
{
    public CartItemDTO(CartItem cartItem)
    {
        Id = cartItem.Id;
        Quantity = cartItem.Quantity;
        Name = cartItem.Product.Name;
        Price = cartItem.Product.Price;
    }

    public Guid Id { get; private set; }
    public int Quantity { get; private set; }
    public string Name { get; private set; }
    public decimal Price { get; private set; }
}

当前的工作流程非常简单:我的存储库返回 CartItem 类型的 IEnumerable。我的服务将其转换为 dto (CartItemDTO)。然后我的控制器将其传递给视图。到目前为止,一切都很好。

现在我想为每个行项目实现总计。我将以下属性添加到 CartItemDTO。

public decimal Total { get; private set; }

然后,我将以下代码添加到 CartItemDTO 构造函数中。

Total = cartItem.Quantity * cartItem.Product.Price;

我的第一个问题是这是否是最佳实践方法?如果没有,为什么?我应该在其他地方添加 Total 属性吗?如果是这样,为什么?

我还想实现整个购物车的总计,因此我创建了一个新类(如下)并修改了我的服务以返回它。

public class CartItemResult
{
    public CartItemResult(IEnumerable<CartItemDTO> result)
    {
        CartItems = new List<CartItemDTO>(result);
        Total = result.Sum(total => total.Total);
    }

    public IList<CartItemDTO> CartItems { get; private set; }
    public decimal Total { get; private set; }
}

现在,我可以将新类传递给视图,也可以创建一个单独的 ViewModel,将新类的内容传递给 ViewModel,然后将其传递给视图。

我的第二个问题是,这种方法是否是最佳实践方法?如果不是,为什么以及我应该采取什么不同的做法?

I have the following domain entity:

public class CartItem
{
    public virtual Guid Id { get; set; }
    public virtual Guid SessionId  { get; set; }
    public virtual int Quantity  { get; set; }
    public virtual Product Product  { get; set; }
}

I have the following DTO:

public class CartItemDTO
{
    public CartItemDTO(CartItem cartItem)
    {
        Id = cartItem.Id;
        Quantity = cartItem.Quantity;
        Name = cartItem.Product.Name;
        Price = cartItem.Product.Price;
    }

    public Guid Id { get; private set; }
    public int Quantity { get; private set; }
    public string Name { get; private set; }
    public decimal Price { get; private set; }
}

The current work flow is pretty simple: my repository returns a IEnumerable of type CartItem. My service transforms it to dto's (CartItemDTO). My controller then passes it to the view. So far so good.

Now I want to implement a total for each of the line items. I added the following property to CartItemDTO.

public decimal Total { get; private set; }

I then added the following code to the CartItemDTO constructor.

Total = cartItem.Quantity * cartItem.Product.Price;

My first question is if this is a best practices approach? If not, why? Should I have added the Total property somewhere else? If so, why?

I also wanted to implement a total for the entire cart so I create a new class (below) and modified my service to return it.

public class CartItemResult
{
    public CartItemResult(IEnumerable<CartItemDTO> result)
    {
        CartItems = new List<CartItemDTO>(result);
        Total = result.Sum(total => total.Total);
    }

    public IList<CartItemDTO> CartItems { get; private set; }
    public decimal Total { get; private set; }
}

I could now either pass the new class to the view or create a separate ViewModel and pass the content of the new class to the ViewModel and pass that to the view.

My second question is, again if this approach is a best practices approach? If not, why and what should I have done differently?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紫瑟鸿黎 2024-09-20 14:57:06

DTO 是用于传输数据的纯类。它不应该包含任何逻辑。您已添加域驱动设计标签,因此我认为您想要使用域对象和域服务。您的域对象 (CartItem) 负责计算商品的总计。领域对象是数据+业务逻辑和使用该数据的规则。计算总计是业务逻辑。另外,对于第二部分(CartItemResult),这通常由称为域服务的东西处理。领域服务提供的业务逻辑与单个领域对象无关,而是与多个领域对象一起工作。

但您还应该考虑项目的复杂性。你真的需要这个吗?不要仅仅因为模式存在就使用它们,总要找到使用它们的理由。 David Neale 提到的方法对于某些应用程序也是正确的。

此致,
拉迪斯拉夫

DTO is pure class for transfering data. It should not contain any logic. You have added domain driven design tag so I think you want to use domain objects and domain services. It is responsibility of your domain object (CartItem) to compute total for item. Domain object is data + business logic and rules working with that data. Computing total is business logic. Also for your second part (CartItemResult) this is usually handled by something called domain service. Domain service provides business logic which is not related to single domain object but instead works with many domain objects.

But you should also think about complexity of your project. Do you really need this? Don't use patterns just because they exists, always find reason to use them. Approach mentioned by David Neale is also correct for some applications.

Best regards,
Ladislav

迟到的我 2024-09-20 14:57:06

就我个人而言,对于数据检索,我建议从存储库返回 POCO 实体并将其映射到控制器中的 ViewModel (Automapper )。实际上不需要有中间对象。

应在何处实现 Total 属性取决于您的设计。该属性是否在域中用于任何业务逻辑?可能是吗?如果没有,那么您可能会认为它只是一个表示问题并且适合 ViewModel。

对于数据更新 - 在 UI 中返回类似于 CartItemUpdateViewModel 的内容,该实体映射到控制器中 CartItemUpdateDetails 的域实体,然后将其传递给存储库方法。

至于您关于 CartItemResult 的问题。我个人会将 Total 逻辑放入 ViewModel 中,并通过返回 IEnumerable 的存储库方法在控制器中填充该 ViewModel。

查看 WhoCanHelpMe 项目,了解展示 DDD 的优秀企业应用程序。

Personally, for data retrieval, I would suggest returning the POCO entity from the repository and mapping it to the ViewModel in the controller (Automapper). There's no need to have an intermediary object really.

It is up to your design where the Total property should be implemented. Is that property used in the domain for any business logic? Could it be? If not then you might consider it merely a presentation concern and suitable for the ViewModel.

For data update - return something like a CartItemUpdateViewModel in your UI which maps to a domain entity of CartItemUpdateDetails in the controller which is then passed to the repository method.

As far as your question regarding the CartItemResult goes. I would personally be putting the Total logic in a ViewModel and populate that ViewModel in the contrller from a repository method returning IEnumerable<CartItem>.

Take a look at the WhoCanHelpMe project for a good enterprise application showcasing DDD.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文