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

时间:2010-08-09 07:57:22

标签: asp.net-mvc asp.net-mvc-2 domain-driven-design dto data-transfer-objects

我有以下域名实体:

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并将其传递给视图。

我的第二个问题,如果这种方法是最佳实践方法,那么又是这样吗?如果没有,为什么以及我应该采取哪些不同的做法?

2 个答案:

答案 0 :(得分:5)

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

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

祝你好运, 拉迪斯拉夫

答案 1 :(得分:3)

就个人而言,对于数据检索,我建议从存储库中返回POCO实体并将其映射到控制器中的ViewModel(Automapper)。没有必要真正拥有中介对象。

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

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

关于CartItemResult的问题。我个人会将Total逻辑放在ViewModel中,并从返回IEnumerable<CartItem>的存储库方法中填充控制器中的ViewModel。

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