使用apicontroller vs odata EntitySetController

时间:2013-07-30 14:02:42

标签: asp.net-web-api odata

我刚刚开始学习ASP.NET Web API,我还有几件事情尚不清楚:

  • 我为什么要使用EntitySetController,它继承自odata控制器而不是ApiController
  • 为什么在OData的上下文中经常提到EF。我知道它“代表”一个实体,但我不明白为什么这两个是连接的。第一个是服务层,EF是模型。
  • 我已经阅读并理解了很多关于这个主题的文字,是的,我错过了最佳实践

非常感谢, 大卫

2 个答案:

答案 0 :(得分:41)

  

为什么我应该使用EntitySetController,它继承自odata控制器而不是ApiController

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

    简短的故事是它为常见案例消除了一些样板(但如果你想要更多的背景和意见,请继续阅读)。

  

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

  • 这个人也无休止地困惑我,直到我放弃并查看OData的起源,WCF Data Services(以前的ADO.NET数据服务)和OData specifications(提示是OData核心协议版本仍然使用名为" 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(最初提供Microsoft.Data.Edm为WCF数据服务开发),而EF则没有,而是使用自己的System.Data.Entity.Edm实现。我也知道他们基于会议的模型构建器是不同的,如上所述。在DB-First设置中使用EF时会变得荒谬可笑;您在EDMX file中获得了CSDL格式的序列化EDM模型,并且OData扩展在运行时继续从CLR代码(使用单独的代码约定)生成它们自己的序列化CSDL代码本身由EF从初始CSDL生成通过T4模板。你的头旋得多吗?


更新:两周前(7月19日)有点largely improved,对不起我错过了。 (感谢RaghuRam Nadiminti。)我没有查看补丁,但是从示例代码看,它的工作方式似乎是必须使用EF EDMX序列化器将模型序列化为CSDL,然后使用EdmLib解析器对其进行反序列化由OData扩展使用。它仍然感觉有点像EF Code-First设置中的黑客攻击(至少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处理程序(请参阅公告的评论)。看起来很少有计划进入这个,因为他们仍然集思广益,以使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和数据服务的事情将会发生很大的变化,因为这个答案仍在不时被推翻。



更新: RESTierannouncement)似乎就是结果。


最后,我的(个人)观点:OData尽管在技术上是基于REST的HTTP协议,但它非常非常非常以数据为导向。这绝对没问题(我们可以使用HTTP定义很多不同类型的接口),而且,我发现所有的ServiceStack与OData辩论无关(我相信它们在我们当前的常见架构中的不同层运行)。令我担心的是,人们试图使基于OData的API像行为中心(或者过程导向的"或者#34; 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的影响。

  

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

  • 别担心,我环顾四周,但我认为没有人真正知道他们在做什么。当你弄清楚这个混乱时,就像假装其他人一样假装。

答案 1 :(得分:0)

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

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