从业务对象中抽象数据访问层
将数据访问代码与业务对象分离并不是什么新鲜事,但我总是在寻找实现某些目标的“最佳方法”。
我有以下课程:
橙色 - 这是我的业务对象。
OrangeList - 这是一个橙子列表。
用户可以通过调用 OrangeList.Fetch(someCriteria) 从数据存储中获取 Orange 对象。 因此 OrangeList 必须具有对数据访问层的引用 - 因此它具有属性:IDataProvider MyDataProvider。
这对我有用,但问题是我们无法单独获取单个 Orange - 我们总是必须通过 OrangeList。
Orange 和 OrangeList 中的一个或两者都必须源自某个保存 DataProvider 的公共对象。
这是一个问题,还是我的方法一开始就偏离了目标?
任何提示/指示表示赞赏,谢谢。
编辑:根据下面的讨论,我检查了存储库模式。
但是对于我的项目,我认为将存储库与存储库进一步分离是个好主意达尔。
所以......存储库是我获取橙子和保存橙子的方式,但仍然不知道如何。 我将其委托给 IDataProvider,它可以是图中列出的一些。
澄清一下 - Orange 不知道如何获取/更新自身,对吗? 这是一个纯粹的业务对象——这就是重点吗?
替代文本 http://img22.imageshack.us/img22/2460/repositorya.jpg< /a>
如果您想知道,我的“LegacyDataProvider”是支持旧系统,该系统访问基于文件的数据库(FoxPro,eek) - 但这让我可以将其包装起来并与我保持一定距离新代码。
在 .NET 程序集构造方面,为了防止循环引用,我将拥有一个 Repository.DLL [OrangeRepo]、一个 DataProviderInterface.DLL [IDataProvider] 和一个 BusinessObjects.dll [Orange]。 都好?
那我有关于存储库的想法了吗?
It's nothing new to de-couple the data access code from your business objects, but I'm always on the look-out for the "best way" to achieve something.
I have the following classes:
Orange - this is my Business Object.
OrangeList - this is a List of Oranges.
The user would fetch Orange objects from the data store by calling OrangeList.Fetch(someCriteria). Therefore OrangeList has to have a reference to the Data Access Layer - so it has the property: IDataProvider MyDataProvider.
This will work for me, but the problem is that we cannot fetch a single Orange by itself - we always have to go via OrangeList.
Either that or both Orange and OrangeList would have to descend from some common object that would hold the DataProvider.
Is this a problem, or is my approach WAY off the mark in the first place?
Any hints/pointers are appreciated, thanks.
EDIT: In light of the discussion below, I checked out the Repository pattern.
However for my project, I think it is a good idea to separate still further the Repository from the DAL.
SO.... The Repository is how I GET Oranges, and SAVE Oranges, but still doesn't know HOW. I delegate that to the IDataProvider, which could be a number of those listed in the diagram.
To clarify - Orange does NOT know how to fetch/update itself, right? It's a PURE business object - and is that the point?
alt text http://img22.imageshack.us/img22/2460/repositorya.jpg
In case you're wondering, my "LegacyDataProvider" is to support an OLD system, which accesses a file-based Database (FoxPro, eek) - but this lets me wrap this up and keep it at arms-length from my new code.
In terms of .NET assembly construction, to prevent circular references it looks like I'm gonna have a Repository.DLL [OrangeRepo], a DataProviderInterface.DLL [IDataProvider], and a BusinessObjects.dll [Orange]. All good?
Have I got the idea of the repository then?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我建议 存储库模式
I suggest the Repository Pattern
我会(并且确实)从一个主 API 对象(OrangeCart?)中组合所有这些东西,该对象还为数据访问层组合了一个接口对象。 您的 Orange 和 OrangeList 知道它们属于 OrangeCart 并与其对话以进行 DAL 操作。
I would (and do) compose all these things off of a master API object (OrangeCart?) that also composes an interface object for the data access layer. Your Oranges and OrangeLists know that they belong to the OrangeCart and to talk to it for DAL operations.
我没有 OrangeList(someCriteria),而是 Oranges.Criteria1List、Oranges.Criteria2List。 对于单身人士,我有 Oranges.GetItem(orangeId)。
按照您的方式进行操作,BusinessObject 最终需要使用逻辑数据设计术语而不是概念术语进行思考。
(存储库实现给我带来了同样的不适 - 通常它们的用途就是在表上放置一个薄抽象厚代码层。我不喜欢 BL 被要求了解数据库实现细节,例如数据类型和大小。解耦这些类型的依赖关系常常很有用。)
Rather than OrangeList(someCriteria), I'd have Oranges.Criteria1List, Oranges.Criteria2List. For a singleton, I'd have Oranges.GetItem(orangeId).
Doing it your way, the BusinessObject ends up needing to think in logical data design terms rather than conceptual terms.
(Repository implementations cause me the same discomfort - too often all they are used for is to put a thin-abstraction thick-code layer over the tables. I don't like the BL to ever be required to know about database implementation details like data types and sizes. Too often it's useful to decouple these kinds of dependencies.)