5

我正在构建我的第一个 SPA,并且我已经为我的每个实体构建了 DTO,但我刚刚发现轻而易举,它似乎负责将您的更改序列化为最小包以优化更新/添加/等等

我构建 DTO 的原因是为了“扁平化”我的数据并限制我将多少数据放在网络上,但我想知道如果 Breeze 处理它,我是否还需要这个开销。

4

2 回答 2

5

DTO 是有原因的。“扁平化数据”不是其中之一。“限制我在网络上传输的数据量”也不是。

Breeze 在对象图方面做得很好。想象一下为客户发送 100 个订单。您不想在每个订单 DTO 上重复客户名称。使用 Breeze,您可以查询客户订单(使用“扩展”),您会获得一份客户副本和与之配套的订单。

var 查询 = 新微风.EntityQuery.from('客户')
           .where('Id', 'eq', 42)
           .expand('订单');

另一方面,如果您只需要客户名称列表,请使用“投影”:

var query = new browse.EntityQuery.from('Customers') // 所有客户
           .select('id, companyName'); // 投影到一个匿名的 2-property 对象中

偶尔使用服务器端 DTO 来构建您无法从客户端轻松创建的东西(例如,Customer-and-total-current-year-order-dollars)。

关键是您可以混合 DTO、投影和实体查询以满足您的需求。您不必一路走下去(在我看来)。

于 2013-03-20T21:03:28.523 回答
1

我们目前正在评估从 Knockout 到 Angular 和 Breeze 的更改,以摆脱我们编写的大部分 DTO 和 DTO 映射代码(服务器和客户端代码)。我们所做的不是公开 DAO,而是为所有实体创建 DTO。最后发生的事情是,在许多情况下(不是全部)我们有看起来 90% 与数据库对象相似的类。这使我们得出这样的结论:在我们的案例中,DTO 没有意义,我们所花费的开销是浪费精力,我们需要用更好的方法来摆脱这个问题。所以必须开始一轮重构:-)

由于这里我们有两位专家(@John 和@Ward)在一个地方,我也将借此机会回答这个问题,并进一步提出一个关于实施的问题,到目前为止我还没有完全回答我自己,也许是 John Ward 可以澄清这一点,因为我认为如果仍然需要 DTO,这是问题的重要方面。

看着微风,它似乎对避免大量 DTO 和 DTO 映射代码有很大帮助,我完全同意使用 DTO 来减少与微风一起通过电线的使用是没有意义的,因为这是完美处理的事情如上所述,通过微风在客户端进行查询。这是我可以完全确认并且有道理的事情。像我们一样创建许多不同的 DTO 类也不是最好的方法。Breeze 用更少的代码做得更好。

使用 DTO 和 DTO 映射代码来分离关注点我仍然认为是一个好主意和原则,但它也带来了很多开销,在许多情况下可能不需要。因此,要利用微风,您当然可以在客户端创建 DTO 并写入/生成元数据,但这不是微风的基本理念。你可以这样使用它,但是你在 DAO 上停留的时间越长,你需要编写的代码就越少,你的项目就越快。但是,breeze 允许您这样做,因此该框架也可以与 DTO 一起使用,但这并不是编写 BREW 的基本思想。两者的混合(DAO 和 DTO 的暴露)可能是最好的方法。

但是什么时候使用 DTO 呢?

  • 安全
  • 复杂逻辑(计算)或当您因为过于复杂而无法使用简单的 CRUD 方法时,您不会或不能(安全)在客户端公开。

在安全的情况下,我实际上不是 100% 确定,这就是我在这里写信并想问两位专家的原因。我们在服务器端使用 EF,最好的主意是在服务器端使用投影以确保安全。但是怎么做呢?

我提出这个问题是因为我认为如果仍然需要 DTO,能够回答这个问题是最重要的。

我们以 EF 的以下代码结束(在我们的评估演示中):

private IQueryable<News> RestrictFields(IQueryable<News> query)
    {
        return query
            .ToList() // This seemd to be needed, otherwhise I cannot use new News()
            .Select(t => new News()
                {
                    Id = t.Id,
                    Text = t.Text,
                    Title = t.Title,
                    Date = t.Date
                })
            .AsQueryable();
    }

正如您在上面看到的,我们有一个 EF 查询。所以我们尝试的第一个方法就是使用 new News() 进行投影。这不起作用,因为 EF 不允许您在投影中使用相同的 DAO 类,只能使用 DTO 对象或匿名对象。所以我们使用了 ToList() 和 AsQueryable() 的解决方法。但这似乎不正确,而且很可能来自客户端的查询参数不会发送到数据库,并且可能因此某些参数无法正常工作,例如“扩展”。

那么出于安全原因在服务器端进行投影的最佳方法是什么,以便最终真正摆脱对 DTO 的需求?@John:我看到了你的帖子,你说你在演示项目中为你的培训课程(Angular 和 Breeze)使用了扬声器上的投影,但我找不到它在哪里实现。

在这里我真的被困住了,这对我来说是了解是否仍然需要 DTO 以及它如何与 Breeze 完美配合的缺失环节。

我希望我的回答有助于回答您的一些问题,此外,我希望它还为您 Jake 提供了一些非常重要的有关使用微风以及是否仍然需要 DTO 的链接。

亲切的问候,

克里斯

于 2014-01-30T08:16:59.757 回答