24

I just started learning about ASP.NET Web API and I have several things that are still unclear to me:

  • why should I use EntitySetController,which inherits from odata controller instead of ApiController
  • Why is EF frequently mentioned in the context of OData. I know it "represents" an Entity, but I don't see why the 2 are connected. The first is on Service Layer and EF is Model.
  • I have read and understood a lot of litereture written about the subject, yes I missed when its the best practice

Thanks a lot, David

4

2 回答 2

44

为什么要使用继承自 odata 控制器而不是 ApiController 的 EntitySetController

  • 我同意这令人困惑,并且似乎缺少文档(至少当我遇到与您相同的问题时)。我放松心情的方法就是阅读代码。我鼓励你也这样做,因为它真的很短(专注于 EntitySetController 类及其助手);最多不应该超过 5-10 分钟(承诺),之后你不会有任何问题。

    简短的故事是它消除了常见案例的一些样板(但如果您需要更多上下文和意见,请继续阅读)。

为什么在 OData 的上下文中经常提到 EF。我知道它“代表”一个实体,但我不明白为什么 2 是连接的。第一个是在服务层上,EF 是模型。

  • 这也让我无休止地困惑,直到我放弃并查看了 OData 的起源、WCF 数据服务(以前的 ADO.NET 数据服务)和OData 规范(提示是 OData 核心协议版本仍然用标头指定称为“数据服务版本”)。在那里您可以发现 OData 使用EDM,即实体数据模型,它与 EF 使用的模型规范相同,并以与 EF 相同的格式对其进行序列化: CSDL(概念架构定义语言)。这并非巧合,WCF 数据服务主要支持 EF,虽然它不需要它,但可以说它的设计是基于它的。

    请注意,WCF 数据服务仍然是 OData 的旗舰实现。

可能引起高度兴趣的事情(至少对我来说是这样):在将 EF 与 ASP.NET Web API 和 OData 扩展一起使用时,(据我所知)无法在两者之间共享模型。

如果您不觉得这很有趣,您可以跳到下一个要点以获得下一个答案。

例如,在 Code-First 设置中使用 EF 时,您通常会在很大程度上基于代码约定和 EF System.Data.Entity.DbModelBuilder(“流体 API”)来构建模型。然后,您将使用System.Web.Http.OData.Builder.ODataConventionModelBuilder执行几乎完全相同的操作来构建 OData 模型,并获得几乎完全相同的结果。过去,我设法从 EF 团队或 Web API 团队的随机会议中挖掘出一些随机笔记,其中简要提到了这一点,据我所知(我再也找不到这个文档了),那里没有改善这种情况的计划。因此,他们现在有两种不同且不兼容的 EDM 实现。

我承认我没有花时间仔细检查代码以正确验证这一点,但我知道 Web API + OData 扩展依赖于EdmLib(它提供最初为 WCF 数据服务开发的Microsoft.Data.Edm ),而 EF没有,而是使用它自己的System.Data.Entity.Edm实现。我也知道他们基于约定的模型构建器是不同的,如上所述。在 DB-First 设置中使用 EF 会变得很荒谬;您在EDMX 文件中获得 CSDL 格式的序列化 EDM 模型,并且 OData 扩展继续并在运行时从 CLR 代码(使用单独的代码约定)本身生成自己的序列化 CSDL 代码,该 CLR 代码由 EF 通过 T4 模板从初始 CSDL 生成。你的头转得厉害吗?


更新:这在很大程度上得到了改善不到两周前(7 月 19 日),抱歉我错过了。(感谢 RaghuRam Nadiminti。)我没有查看补丁,但从示例代码看来,它的工作方式似乎是必须使用 EF EDMX 序列化程序将模型序列化为 CSDL,然后使用 EdmLib 解析器将其反序列化为由 OData 扩展使用。它仍然感觉有点像 EF Code-First 设置中的 hack(至少 CLR 代码只分析一次,但如果两个组件一开始都使用相同的内存模型,我会更喜欢它)。但是,在使用 Model-First 或 Database-First 场景时,可以通过直接反序列化 VS 生成的 EDMX 文件来采取捷径。在最后一种情况下,它实际上感觉不像是黑客,但同样,单一模型是最好的。我不 不知道 EF 可能会切换到使用 EdmLib 或者 EdmLib 会切换到使用 EF 的 EDM 模型,这两个项目现在都非常强大,并且阻碍可能不仅仅是技术问题。不幸的是,ASP.NET 团队对此 AFAICT 无能为力。



更新:再次偶然偶然发现了那些会议记录。他们确实来自 EF 团队,并表示他们不打算在 EdmLib 上工作。


然而,我现在相信这一切都是好事。原因是,如果他们填补了所有空白,删除了所有样板文件,并使一切正常,他们最终会回到 WCF 数据服务所在的位置,这是一个完全集成的解决方案,程序员通过“在管道中注入代码”拦截器”。对我来说,去那里的唯一原因是因为开源需求,但即便如此,我认为尝试和倡导开源 WCF-DS 更合理。

现在的问题变成了:“那么 Web API + OData 扩展有什么用呢?”。好吧,当您确实需要两种不同的模型用于数据存储和 Web 服务时,它非常适合。当“拦截器”设计不够灵活,无法在两个模型之间进行转换时,这是一个很好的选择。


更新:截至 2014 年 3 月 27 日,这是官方的,他们尝试缩小这些差距,在此过程中弃用 WCF 数据服务。很早的谈话提到了一个“处理程序”来做到这一点,很可能是一个 ASP.NET HTTP 处理程序(参见公告的评论)。看起来这方面的计划很少,因为他们仍在集思广益,以使 ASP.NET Web API 填充 WCF 数据服务的用例。我在对公告的评论和这个线程(在公告前几天开始)中提到了上面的那些用例。

许多其他人表达了几乎相同的担忧(再次,请参阅相关讨论),所以很高兴看到我没有做这一切。

有些人不相信 ASP.NET Web API 可以在合理的时间内变成对数据服务用例有用的东西,因此有些人建议 MSFT 重新考虑他们的决定。是否使用 ASP.NET 来满足开源需求的问题也没有实际意义:如果一切顺利,WCF 数据服务将很快开源,尽管没有任何宣传努力。(这只是一个源转储,目前尚不清楚是否有人会维护它。)

据我所知,一切都指向预算削减,有些人说这是全公司“重新聚焦”的结果,尽管所有这一切都应该持保留态度。

撇开这些不谈,现在有可能随着时间的推移出现新的解决方案——在 OData API 方面甚至比 WCF 数据服务或 Web API 更好。尽管现在看起来有点混乱,但 MSFT OData 团队确实相对较早地收到了来自客户的相当多的反馈,所以还是有希望的(尤其是如果未来的解决方案,如果有的话,它本身是开源的)。过渡可能会很痛苦,但请务必在未来观看有关此问题的讨论。

我不确定我是否会再花时间更新这篇文章;我只是想强调一下关于 Web API 和数据服务的事情将会发生很大的变化,因为这个答案仍然不时被赞成。



更新: RESTier (公告) 似乎是结果。


最后,我的(个人)意见:OData 尽管在技术上是一个基于 RESTful HTTP 的协议,但它非常、非常、非常面向数据。这绝对没问题(我们可以用 HTTP 定义很多不同类型的接口),而且我发现所有关于 ServiceStack 与 OData 的争论都无关紧要(我相信它们在我们当前的常见架构中运行在不同的层)。我发现令人担忧的是人们试图让基于 OData 的 API 表现得像一个以行为为中心(或“面向流程”或“类似 ServiceStack”)的 API。对我来说,OData URI 约定和资源表示格式(Atom 和 JSON)一起取代了 SQL、WCF 数据服务“查询拦截器”和“更改拦截器”取代了 DBMS 触发器和OData 操作替换 DBMS 存储过程。从这个角度来看,您会立即看到,如果您需要放在 OData API 后面的领域逻辑太复杂或不是非常面向数据,您最终会得到不尊重 REST 原则的复杂“操作”,并且感觉不对的实体。如果您将 OData API 视为纯数据层,那就没问题了。您可以在其上堆叠服务,就像在 SQL 数据库上放置“服务层”一样。

因此,我不确定 Web API + OData 扩展是否那么好。如果您需要根本不同的模型,那么您的应用程序可能不太面向数据(除非您只是合并来自各种来源或其他东西的模型),因此 OData 不适合。这表明您至少应该单独考虑 Web API(下面使用 SQL 或 OData)或类似 ServiceStack 的东西。

无论好坏,Javascript 客户端都无法将 SQL 与远程服务器通信。也许在未来通过浏览器 API,或者通过WebSockets的变体,但现在,OData 是最接近远程数据层的东西,任何人都可以为具有瘦或没有服务器端逻辑的富 JS 客户端获得。OData 当然被其他类型的客户端使用,但我想说它在客户端 Web 平台上特别有用,其中 Breeze.js 或 JayData 之类的东西对于 OData 就像实体框架对于 SQL 一样。

我已经阅读并理解了很多关于该主题的文献,是的,我错过了最佳实践

  • 别担心,我环顾四周,但我认为没有人真正知道他们在做什么。当你理解这个烂摊子的时候,就假装和其他人一样。
于 2013-07-30T18:18:17.010 回答
0

如果要创建 OData 端点,请使用 EntitySetController。如果您想返回通用 JSON 或 XML 或其他格式(例如,使用自定义格式化程序),请使用 ApiController。

在 Web API 中,EF 和 OData 不一定是相连的。您可以编写不使用 EF 的 OData 端点。很多 Web API 教程都使用 EF,因为 EF 代码优先在教程中相对容易展示。:-)

于 2013-07-30T17:49:36.123 回答