8

有没有人有关于在 ASP.Net MVC 应用程序中使用 Web 服务作为模型的建议或技巧?我还没有看到有人写过这样做。我想构建一个 MVC 应用程序,但不将其绑定到使用特定数据库,也不将数据库限制为单个 MVC 应用程序。我觉得 Web 服务(RESTful,很可能是 ADO.Net 数据服务)是要走的路。

4

4 回答 4

28

您的 MVC 应用程序与数据库分离的可能性或有用性有多大?在您的应用程序生命周期中,您多久看到一次从 SQL Server 到 Oracle 的更改?在过去 10 年我交付的项目中,它从未发生过。

架构就像洋葱,它们在它们所依赖的事物之上具有抽象层。如果您要使用 RDBMS 进行存储,那是您架构的核心。将自己从数据库中抽象出来以便可以交换它是非常错误的。

现在您可以将您的数据库访问与您的域分离,存储库模式是实现此目的的方法之一。如今,大多数成熟的解决方案都使用 ORM,因此如果您想要一种成熟的技术,您可能想看看 NHibernate,或者 ActiveRecord / linq2sql 在您的数据之上获得更简单的活动记录模式。

既然您已经制定了数据策略,那么您就拥有了某种领域。当您向客户端公开数据时,您可以选择通过 MVC 模式执行此操作,您通常会发送从您的域生成的 DTO 进行渲染,或者您可以决定利用像 REST 这样的架构风格来提供更松散耦合的系统,通过提供链接和自定义表示。

当您走向解决方案的外部层时,您会从紧耦合变为松耦合。

但是,如果您的问题是在 REST 架构或 Web 服务之上构建一个 MVC 应用程序,并将其用作模型……何必呢?如果您要拥有一个域模型,为什么不在您的系统服务中重用它呢?

从 MVC 应用程序生成 UI 和生成 RESTful 架构所需的文档是两个完全不同的上下文,基于彼此之上的上下文只会导致比需要更多的痛苦。而且您正在牺牲性能。

取决于您的确切场景,但是基于远程 XML 的服务作为 MVC 中的模型,从经验来看,这不是一个好主意,它可能是过度设计并且忽略了对域开始的需求。

于 2009-06-03T02:03:49.087 回答
3

编辑 2010-11-27;澄清了我的想法,这是非常需要的。

Web 服务在不同类型的应用程序中公开功能,而不是在单个应用程序中进行抽象,最常见的是。您可能正在考虑更多封装命令的方式,并以不干扰控制器/视图编程的方式读取。

如果您在解耦之后使用服务总线中的服务并在异步页面中执行异步模式。您可以看到 Rhino.ServiceBus、nServiceBus 和 MassTransit 用于 .Net 本机实现,RabbitMQ用于不同的http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/

编辑:我有一些时间尝试将消息推送到我的服务,从而将更新推送到簿记应用程序。RabbitMQ 是一个消息代理,又名 MOM(面向消息的中间件),您可以使用它向您的应用程序服务器发送消息。

您也可以简单地提供服务接口。阅读 Eric Evan 的领域驱动设计以获得更详细的描述。

REST-ful 服务接口处理大量数据,更具体地说,处理可寻址资源。它可以极大地简化您的编程模型,并允许通过 HTTP 协议对输出进行很好的控制。WCF 即将推出的编程模型使用原始论文中定义的真正休息,其中每个文档都应在一定程度上提供用于继续导航的 URI。看看这个。(在我这篇文章的第一个版本中,我感叹 REST 的“慢”,不管这意味着什么)基于 REST 的 API 也几乎是CouchDBRiak使用的。

ADO.Net 相当垃圾(!)[由于代码到实现、数据访问泄漏而导致延迟收集的 N+1 个问题 - 您总是需要查询代码所在的数据库上下文等] 与例如 LightSpeed (商业)或NHibernate。Spring.Net 还允许您使用 Web 服务外观将服务接口包装在它们的包含中,但是(暂时没有浏览它)我认为它的配置有点过于 xmly。

编辑 1:在这里使用 ADO.Net,我的意思是默认的“最佳实践”,包括 DataSet、DataAdapter 和从 DataReader 迭代大量行;它产生了相当丑陋且难以调试的代码。N+1 的东西,是的,就是关于实体框架的。

(编辑 2:EntityFramework 也没有给我留下深刻印象!)

编辑 1:在单独的程序集中创建域层 [aka. Core] 并在那里提供所有域和应用程序服务,然后从您的特定 MVC 应用程序中导入此程序集。通过核心程序集中的接口将数据访问包装在某些 DAO/存储库中,然后数据程序集会引用和实现该接口。用 IoC 连接接口和实现。您甚至可以使用上述服务总线对动态服务发现进行编程,以解决接口问题。WCF 使用这样的接口,上面的大多数服务总线也是如此;您可以在 IoC 容器中提供一个子组件解析器来自动执行此操作。

编辑 2:上述的一个很好的组合是 CQRS+EventSourcing+ReactiveExtensions。您的写入模型将接受命令,您的域模型将决定是否接受它们,它将事件推送到反应式扩展管道,也可能通过您的读取模型将使用的 RabbitMQ。

更新 2010-01-02(编辑 1)

我的想法的笑话已经被称为 MindTouch Dream 的东西编纂了。他们制作了一个截屏视频,其中他们将 Web 应用程序的几乎所有部分都视为(Web)服务,该服务也通过 REST 公开。

他们创建了一个高度并行的框架,使用协程来处理这个问题,包括他们自己的弹性线程池。

对于这个问题的所有反对者,当面说:p!收听这个截屏视频,尤其是在 12 分钟时。

实际的框架在这​​里。

如果您喜欢这种编程,请查看monad 的工作原理及其在 C# 中的实现。您还可以阅读CoRoutines

新年快乐!

2010-11-27 更新(编辑 2)

事实证明,CoRoutines 是使用 Microsoft 的任务并行库产品化的。您的任务现在实现了与实现 IAsyncResult 相同的功能。Caliburn 是一个使用它们的酷框架。

Reactive Extensions 将 monad 理解提升到了异步的下一个级别。

ALT.Net 世界似乎正朝着我第一次写这个答案时所说的方向发展,尽管我对新类型的架构知之甚少。

于 2009-06-01T20:34:09.763 回答
3

您应该以与数据访问无关的方式定义模型,例如使用存储库模式。然后,您可以创建由特定数据访问技术(Web 服务、SQL 等)支持的具体实现。

于 2009-06-01T20:46:00.770 回答
0

这真的取决于这个 mvc 项目的大小。如果网站将被少数用户(< 5000)使用,我会说将 UI 和域保持在相同的运行环境中。

另一方面,如果您正在计划一个将被数百万人访问的网站,您必须考虑分布式,这意味着您需要以一种可以扩展/扩展的方式构建您的网站。这意味着您可能需要使用额外的服务器(Web、应用程序和数据库)。

为了使其正常工作,您需要将您的 mvc UI 站点与应用程序分离。应用程序层通常包含您的域模型,并且可能通过 WCF 或服务总线公开。我更喜欢服务总线,因为它更可靠并且可能使用像 msmq 这样的持久队列。

我希望这有帮助

于 2011-11-30T09:18:13.280 回答