具有 NHibernate 和企业业务逻辑的 OData WCF 数据服务
首先让我为整个主题的长度表示歉意。这将相当长,但我希望确保该消息清晰无误。
在公司,我们有一个现有的 ASP.NET Web 应用程序。在 .NET Framework 3.5 SP1 上用 C# ASP.NET 编写。不久前,使用 WCF 和 SOAP 为此 Web 应用程序开发了一个初始 API,以允许外部各方在不依赖浏览器的情况下与应用程序进行通信。
这个 API 存在了一段时间,但最终要求创建一个新的 RESTfull API,并依赖于新技术。我接受了这项任务,并使用 Microsoft MVC 2 框架创建了初始 API,在我们的 ASP.NET Web 应用程序中运行。最初需要一些时间才能使其正常运行,但目前我们可以对应用程序进行 REST 调用以接收详细说明我们的资源的 XML。
我参加过 Microsoft WebCamp,我立即就被 OData 概念所吸引。这与我们正在做的非常相似,但这是一个由更多玩家支持的协议,而不是我们自己的实现。目前,我正在研究 PoC(概念验证),以重新创建我使用 OData 协议和 WCF DataService 技术开发的 API。
在互联网上搜索 NHibernate 2 与数据服务配合使用后,我成功创建了 API 的只读版本,该 API 允许我们通过将传入查询请求映射到业务层来从内部业务层读取实体。 然而,我们希望有一个功能性 API,它还允许使用 OData 协议创建实体。所以现在我有点困惑如何继续。我一直在阅读以下文章: http://weblogs.asp.net/ cibrax/default.aspx?PageIndex=3
上面的文章很好地解释了如何将自定义 DataService 映射到 NHibernate 层。我以此为基础继续,但我有一个“问题”,我不想使用 NHibernate 将我的请求直接映射到数据库,但我希望将它们映射到我们的业务层(一个单独的 DLL) )根据访问权限、特权和触发器执行大量检查、约束和更新。
所以我想问的是,例如,我创建了自己的 NhibernateContext 类,如上面的文章所示,但依赖于我们的业务层而不是 NHibernate 会话,它可以工作吗?我可能必须大量依赖反射来确定我在运行时使用的对象的类型,并调用正确的业务类来执行更新和删除。
用一张小的 ascii 图片来演示:
*-----------------*
* Database *
*-----------------*
*------------------------*
* DAL(Data Access Layer) *
*------------------------*
*------------------------*
* BUL (Bussiness Layer) *
*------------------------*
*---------------* *-------------------*
* My OData stuff* * Internal API *
*---------------* *-------------------*
*------------------*
* Web Application *
*------------------*
那么,这会起作用吗?或者性能会使其变得无用吗? 或者我只是在这里错过了球? 我的想法是,我希望重用存储在 BUL 和 BUL 中的任何逻辑。 DAL 层来自 OData WCF DataService。
我正在考虑创建从 Data.Services 命名空间中的 EntityModel 类继承的新类,并创建一个新的 DataService 对象来标记对 BUL 和 BUL 的所有调用。达尔和API 层。然而,我不确定在哪里/谁拦截创建和删除资源的请求。
我希望我想解释的内容很清楚,我希望有人能在这方面帮助我。
Let me first apologise for the length of the entire topic. It will be fairly long, but I wish to be sure that the message comes over clearly without errors.
Here at the company, we have an existing ASP.NET WebApplication. Written in C# ASP.NET on the .NET Framework 3.5 SP1. Some time ago an initial API was developed for this web application using WCF and SOAP to allow external parties to communicate with the application without relying on the browsers.
This API survived for some time, but eventually the request came to create a new API that was RESTfull and relying on new technologies. I was given this assignment, and I created the initial API using the Microsoft MVC 2 Framework, running inside our ASP.NET WebApplication. This took initially quiet some time to get it properly running, but at the moment we're able to make REST calls on the application to receive XML detailing our resources.
I've attended a Microsoft WebCamp, and I was immediatly sold by the OData concept. It was very similar then what we are doing, but this was a protocol supported by more players instead of our own implementation. Currently I'm working on a PoC (Proof of Concept) to recreate the API that I developed using the OData protocol and the WCF DataService technology.
After searching the Internet for getting NHibernate 2 to work with the Data Services, I succeeded in creating a ReadOnly version of the API that allows us to read out the entities from the internal business layer by mapping the incoming query requests to our Business layer.
However, we wish to have a functional API that also allows the creation of entities using the OData protocol. So now i'm a bit stuck on how to proceed. I've been reading the following article : http://weblogs.asp.net/cibrax/default.aspx?PageIndex=3
The above articly nicely explains on how to map a custom DataService to the NHibernate layer. I've used this as a base to continue on, but I have the "problem" that I don't want to map my requests directly to the database using NHibernate, but I wish to map them to our Business layer (a seperate DLL) that performs a large batch of checks, constraints and updates based upon accessrights, privledges and triggers.
So what I want to ask, I for example create my own NhibernateContext class as in the above articly, but instead rely on our Business Layer instead of NHibernate sessions, could it work? I'd probably have to rely on reflection alot to figure out the type of object I'm working with at runtime and call the correct business classes to perform the updates and deletes.
To demonstrate with a smal ascii picture:
*-----------------*
* Database *
*-----------------*
*------------------------*
* DAL(Data Access Layer) *
*------------------------*
*------------------------*
* BUL (Bussiness Layer) *
*------------------------*
*---------------* *-------------------*
* My OData stuff* * Internal API *
*---------------* *-------------------*
*------------------*
* Web Application *
*------------------*
So, would this work, or would the performance make it useless?
Or am I just missing the ball here?
The idea is that I wish to reuse whatever logic is stored in the BUL & DAL layer from the OData WCF DataService.
I was thinking about creating new classes that inherit from the EntityModel classes in the Data.Services namespace and create a new DataService object that marks all calls to the BUL & DAL & API layers. I'm however not sure where/who to intercept the requests for creating and deleting resources.
I hope it's a bit clear what I'm trying to explain, and I hope someone can help me on this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
细节决定成败,但听起来你提出的设计应该可行。
您可以在 DataService 类中定义适用于每个人的访问权限、配置设置和自定义操作。在这种情况下,我认为您将更多地关注数据上下文(DataService 中的“T”)。
对于上下文,确实有两个有趣的路径:读取和写入。读取通过 IQueryable 入口点进行。编写 LINQ 提供程序是一项艰巨的工作,但 NHibernate 已经支持这一点,尽管它会返回我想象中的 DAL 实体。如果您可以用数据库可以理解的术语表达这些内容,则可以在此处使用查询拦截器进行访问检查。
更新路径来自我所理解的您试图运行更多业务逻辑的地方(您提到了验证、额外更新等)。为此,您需要关注 IUpdatable 实现(如果您使用的是最新版本,则为 IDataServiceUpdateProvider)。在这里您可以使用任何您想要的对象 - 它们可以是 DAL 对象或业务对象。您可以在 DAL 中执行所有操作,然后在 SaveChanges() 上运行验证,或者在业务对象上执行所有操作(如果它们在运行时进行验证)。
您可以在两个地方从一种对象“跳”到另一种对象。一种是在 GetResource() API 中,您可以在其中获取 IQueryable,大概是 DAL 实体的形式。另一个是在 ResolveResource() 中,运行时要求一个对象进行序列化,就像从 IQueryable 中获取一样,因此它可能也是一个 DAL 实体。
希望这会有所帮助 - 对非统一 API 进行统一访问可能很困难,但通常非常值得!
The devil is in the details, but it sounds like the design you're proposing should work.
The DataService class is where you get to define the access rights applicable to everyone, configuration settings, and custom operations. In this scenario, I think you will be focusing more on the data context instead (the 'T' in DataService).
For the context, there are really two interesing paths: reads and writes. Reads happen through the IQueryable entry points. Writing a LINQ provider is a good chunk of work, but NHibernate already supports this, although it would return what I imagine we're calling DAL entities. You can use query interceptors to do access checks here if you can express those in terms that the database would understand.
The update path is from what I understand where you are trying to run more business logic (you mentioned validation, extra updates, etc). To do this, you'll want to focus on the IUpdatable implementation (IDataServiceUpdateProvider if you're using the latest version). Here you can use whichever objects you want - they could be DAL objects or business objects. You can do everything in the DAL and then run validation on SaveChanges(), or do everything on business objects if they validate as they go.
There are two places where you might 'jump' from one kind of objects to another. One is in the GetResource() API, where you get an IQueryable, presumably in term of DAL entities. The other is in ResolveResource(), where the runtime is asking for an object to serialize, just like it would get from an IQueryable, so it's presumably also a DAL entity.
Hope this helps - doing uniform access over non-uniform APIs can be hard, but often well worth it!