为啥要在移动设备中使用实体框架?
Posted
技术标签:
【中文标题】为啥要在移动设备中使用实体框架?【英文标题】:Why would I use Entity Framework in a mobile situtation?为什么要在移动设备中使用实体框架? 【发布时间】:2015-04-28 07:44:51 【问题描述】:我想通过 Web API 保存来自 WPF 移动应用程序的编辑值,因为用户从每个字段中跳出选项卡。所以关于 LostFocus 事件。
使用 EF 时,每次更新字段时,整个实体图都会发布(放置)到 Web API。即使我只是为表单上的基本字段创建一个 DTO,我仍然会每次都发布不必要的数据。
我正在考虑忘记 Web API 中的 EF,而只是发布实体 ID、字段名称和新值。然后在控制器中,创建我自己的 SQL 更新语句并使用旧的 ADO.Net 来更新数据库。
这听起来像是回到了 20 世纪甚至 90 年代,但我有什么理由不这样做吗?
我已阅读 this post,这让我倾向于我提出的解决方案。
感谢任何 cmets 或建议
【问题讨论】:
仅仅因为您的实体包含很多属性,并不意味着您的 DTO 也必须如此。您可以拥有具有有限属性的特定 DTO。例如。对于Student
实体,您可以拥有一个仅包含FirstName
和LastName
属性的StudentListItem
DTO,前提是它们是显示学生列表时使用的唯一属性。
使用 EF 时,每次更新字段时,整个实体图都会发布(放置)到 Web API 你是什么意思?仅发送更新的字段。
@Loetn:如果客户端使用与 WebAPI 相同的实体,并且我编辑具有课程集合的学生,则具有课程集合的整个学生实体将被传递回 API 控制器.
@Flater:当然,但我的编辑表单可能有 20 个字段,所以如果我更新所有字段,仍然有 19 个不必要的字段返回服务器 20 次。
@Graeme:作为第一个想法,您可以只发送 changed 字段,并将其余字段保留为 null
。您最关心的是上述数据的安全性、使用的带宽、高效的编码原则……吗?
【参考方案1】:
听起来您正试图从 RESTful Web API 转向更多 RPC-ish。没关系,只要您对在节省带宽方面付出的额外麻烦是值得的感到高兴。
就技术水平而言,您所做的事情并没有退步;我每天都使用 EF,但我仍然经常需要不时使用普通的旧 ADO.NET
,这是有原因的,它仍然在 CLR 中得到很好的支持。所以没有理由不这样做,只要你对编写 SQL 等感到自在。
但是,出于几个原因,我建议您不要使用您当前的提议
带宽并不一定那么宝贵
即使对于移动设备,一次发送 20 或 30 个字段也可能不是很多数据。当然,如果这太多了,只有您可以知道您的具体情况,但考虑到 3 和 4G 网络的广泛可用性,除非这些字段包含大量数据,否则我不会认为这是一个问题 - 当然,它是你的用例,所以你最了解:)
并发
除非表单实际上是可以独立更新的多个离散对象的表示,否则每次更新字段时发送回单独的更改,您就有可能导致设备上的状态无效。
例如,假设User A
和User B
都在他们的设备上查看同一个对象。这个对象有 3 个字段 A, B, C
因此:
A-"FOO"
B-"42"
C-"12345"
现在假设用户 A 将字段“A”更改为“BAR”并在字段外使用标签,然后用户 B 将字段“C”更改为“67890”和标签。
您的后端现在具有对象的以下状态:
A - "BAR"
B - "42"
C - "67890"
但是,User A
和 User B
现在都具有不正确的对象状态!
如果您还可以从任一客户端重新发送整个对象,情况会变得更糟,因为如果
User A
重新发送整个表单(无论出于何种原因)User B
的更改将在没有任何警告的情况下丢失!
通常这就是为什么 RESTful 交换完整状态的机制如此有效的原因;您将 整个 对象发送回服务器,并根据该完整状态来决定它是否应该覆盖最新版本,或者返回错误,或者返回一些提示用户手动操作的状态合并更改等。
换句话说,它允许您有意义地处理冲突。例如,Entity Framework 只需包含一个特殊类型的列即可免费为您提供并发检查;您可以处理 Concurreny 异常来决定要做什么。
现在,如果表单由几个不同的实体组成, 可以独立更新,您将拥有更多基于任务的场景,因此您可以相应地为您的解决方案建模 - 所有人意味着向客户端发送一个模型,代表表单上所有单个实体的所有属性,但有单独的 POST 返回模型,以及每个模型的处理程序。
例如,如果表单显示客户主数据及其对应的地址记录,您可以向客户端发送单个模型来填充表单,但仅在客户主字段更改时发送客户主模型,并且仅发送地址当地址字段更改等时建模。这样你就可以吃蛋糕了,因为你有一个更小的 POST 有效负载并且你可以管理并发。
【讨论】:
是的,我需要阅读 EF 和并发。如果我按照 Flater 建议的那样使用 DTO,我是否认为我仍然需要将其转换回实体模型,仅将所需字段设置为修改,然后保存并处理任何并发问题 EF 通知? @Grame,是的,这是正确的,通常我会使用的过程是 1. 接收 DTO 2. 基于例如 DTO 上的 ID 属性从 EF 数据上下文中获取实体。 3. 将 DTO 中的属性设置为实体 4. 将 EF 数据上下文询问到SaveChanges()
并捕获任何抛出的 OptimisticConcurrencyException
,然后决定如何继续。有一篇很好的文章here 比我解释得更好:)
我对此有一个后续问题:在第 2 步中,我不想读取整个实体及其导航属性和数据库中的所有字段,因为我的 DTO 只有其中的一个子集。但是我不知道如何让 2 个不相关的实体指向同一张表。我见过“表拆分”的示例,其中两个实体具有不同的属性但来自同一个表。在我的情况下,一个实体将具有与另一个实体相同的一些属性,只是更少。这里有什么提示吗?
@Graeme,您可以查看Automapper,特别是允许在数据库级别进行投影的“投影”功能(即仅选择您包含在Select()
投影目标中的那些字段)。我认为这可以帮助你 - 除非我误解了......也许这需要它自己的问题?以上是关于为啥要在移动设备中使用实体框架?的主要内容,如果未能解决你的问题,请参考以下文章