使用 apicontroller vs odata EntitySetController [关闭]
Posted
技术标签:
【中文标题】使用 apicontroller vs odata EntitySetController [关闭]【英文标题】:using apicontroller vs odata EntitySetController [closed] 【发布时间】:2013-07-30 17:28:53 【问题描述】:我刚开始学习 ASP.NET Web API,有几件事我还不清楚:
为什么要使用EntitySetController,它继承自odata控制器而不是ApiController 为什么在 OData 的上下文中经常提到 EF。我知道它“代表”一个实体,但我不明白为什么 2 是连接的。第一个是在服务层上,EF 是模型。 我已经阅读并理解了很多关于该主题的文献,是的,我错过了最佳实践非常感谢, 大卫
【问题讨论】:
这不是基于意见的。它甚至不像一个基于意见的问题。投票关闭的人可以这样做吗:关闭在不同意见在答案中变得明显之后。 这是一个很好的问题,而且一点也不基于意见。 【参考方案1】:如果要创建 OData 端点,请使用 EntitySetController。如果您想返回通用 JSON 或 XML 或其他格式(例如,使用自定义格式化程序),请使用 ApiController。
在 Web API 中,EF 和 OData 不一定是连接的。您可以编写不使用 EF 的 OData 端点。很多 Web API 教程都使用 EF,因为 EF 代码优先在教程中相对容易展示。 :-)
【讨论】:
谢谢,但我什么时候需要 OData 端点?例如,我有一个类“A”和其他 3 个从 A 继承的类:A1、A2 和 A3。我想公开 A1、A2 和 A3 的 CRUD 操作。我应该为它们中的每一个(我确实想要 3 个不同的控制器)创建 ApiController 还是 EntitySetController? 通常您希望每个“服务”有一个端点;这是一个架构决策。每个 Web API 代表一个 OData 端点(我称之为 Web API 是“您将 ODataRoute 和 EDM 模型映射到的东西)。一个模型有多个实体(您的三个类)。每个实体由单个 ODataController 控制,可能是一个 EntitySetController(它只是扩展了 ODataController 类)。 ODATA 端点可以做 API 端点可以做的所有功能,为什么你需要两者【参考方案2】:为什么要使用EntitySetController,它继承自odata控制器而不是ApiController
我同意这令人困惑并且似乎缺少文档(至少当我和你有同样的问题时)。我放松心情的方式就是阅读the code。我鼓励你也这样做,因为它真的很短(专注于 EntitySetController 类及其helpers);最多不应该超过 5-10 分钟(承诺),之后你不会有任何问题。
简短的故事是它消除了一些常见案例的样板(但如果您需要更多上下文和意见,请继续阅读)。
为什么在 OData 的上下文中经常提到 EF。我知道它“代表”一个实体,但我不明白为什么 2 是连接的。第一个是在服务层上,EF 是模型。
这个也让我困惑不已,直到我放弃并查看了 OData 的起源,WCF Data Services(以前的 ADO.NET 数据服务)和OData specifications(暗示 OData Core 协议版本仍然用名为“DataServicesVersion”的标头指定)。在那里你可以发现 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 file 中获得 CSDL 格式的序列化 EDM 模型,OData 扩展继续并在运行时从 CLR 代码(使用单独的代码约定)本身生成自己的序列化 CSDL 代码,由 EF 通过 T4 从初始 CSDL 生成模板。你头晕目眩吗?
更新:这是不到两周前(7 月 19 日)的largely improved,抱歉我错过了。 (感谢 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 无能为力。
更新:再次偶然发现those meeting notes。他们确实来自 EF 团队,并表示他们不打算在 EdmLib 上工作。
但是,我现在相信这一切都是好事。原因是,如果他们填补了所有空白,删除了所有样板文件,并使一切正常,他们基本上将最终到达 WCF 数据服务所在的位置,这是一个完全集成的解决方案,程序员通过“在管道中注入代码”拦截器”。对我来说,去那里的唯一原因是因为开源需求,但即便如此,我认为尝试和倡导开源 WCF-DS 更合理。
现在的问题变成了:“那么,Web API + OData 扩展有什么好处呢?”。好吧,当您确实需要两种不同的模型用于数据存储和 Web 服务时,它非常适合。当“拦截器”设计不够灵活,无法在两个模型之间进行转换时,它非常适合。
更新:自 2014 年 3 月 27 日起,这是官方的,他们将尝试缩小这些差距,deprecating WCF Data Services in the process。很早的谈话提到了一个“处理程序”来做到这一点,很可能是一个 ASP.NET HTTP 处理程序(参见公告中的 cmets)。看起来这方面的计划很少,因为他们仍在集思广益,以使 ASP.NET Web API 填充 WCF 数据服务的用例。我在对公告的评论和this thread(在公告前几天开始)中提到了上面的这些用例。
许多其他人表达了几乎相同的担忧(再次,请参阅相关讨论),所以很高兴看到我没有做这一切。
有些人不相信 ASP.NET Web API 可以在合理的时间内变成对数据服务用例有用的东西,所以有些人 suggested that MSFT reconsider their decision。是否使用 ASP.NET 来满足开源需求的问题也没有实际意义:如果一切顺利,WCF 数据服务将很快开源,尽管没有任何宣传努力。 (这只是一个源转储,目前尚不清楚是否有人会维护它。)
据我所知,一切都表明预算削减,有些人认为这是全公司“重新聚焦”的结果,尽管所有这一切都应该持保留态度。
撇开这些不谈,现在有可能随着时间的推移出现一种新的解决方案——在 OData API 方面甚至比 WCF 数据服务或 Web API 更好。虽然现在看起来有点混乱,但 MSFT OData 团队确实相对较早地从客户那里收到了相当多的反馈,所以还是有希望的(特别是如果未来的解决方案,如果有的话,它本身是开源的)。过渡可能会很痛苦,但请务必关注未来有关此问题的讨论。
我不确定我是否会再花时间更新这篇文章;我只是想强调一下,关于 Web API 和数据服务的事情即将发生很大变化,因为这个答案仍然会不时被投票。
更新: RESTier (announcement) 似乎是结果。
最后,我的(个人)意见:OData 尽管在技术上是一个基于 RESTful HTTP 的协议,但非常、非常、非常面向数据。这绝对没问题(我们可以用 HTTP 定义很多不同类型的接口),而且我发现所有关于 ServiceStack 与 OData 的争论都无关紧要(我相信它们在我们当前的常见架构中运行在不同的层)。我发现令人担忧的是人们试图让基于 OData 的 API 表现得像一个以行为为中心(或“面向流程”或“类似 ServiceStack”)的 API。对我来说,OData URI 约定和资源表示格式(Atom 和 JSON)一起取代了 SQL,WCF 数据服务"Query Interceptors" and "Change Interceptors" 取代了 DBMS 触发器,OData Actions 取代了 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 一样。
别担心,我环顾四周,但我认为没有人真正知道他们在做什么。当你理解这个混乱的时候,就假装和其他人一样。我已经阅读并理解了很多关于该主题的文献,是的,我错过了最佳实践
【讨论】:
很好的答案。一件小事是 Web API OData 可以支持外部生成的 IEdmModel。这个issue 现已修复。因此,如果您想按原样公开数据库,现在就可以。 更新了对你的补丁的解释(顺便说一句,干得好,我希望我做对了!)。 感谢您的出色而冗长的回答。 (以一种好的方式。=))我最喜欢你对最后一个问题的回答。哈哈哈,虽然我希望几年后还不是这样。 =) 我们回到 OData V4 的第一方,因为他们还没有实现分离接口模式。 Microsoft.Data.Edm 和 Microsoft.OData.Edm 有自己独立的 IEdmModel 定义。太棒了。以上是关于使用 apicontroller vs odata EntitySetController [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
Web API OData V3 `$inlinecount` 失败
如何使用命令(API)和查询(odata)控制器将位置标头传递给响应
使用 OData 响应 Owin Self-Host 忽略 Web Api 中的 Null 属性/值
[转]vs2012 + web api + OData + EF + MYsql 开发及部署
在 ASP.NET Web API 控制器的 nunit 测试中实例化新的 System.Web.Http.OData.Query.ODataQueryOptions