【问题标题】:Relational databases and object oriented environment关系数据库和面向对象的环境
【发布时间】:2013-08-27 17:57:07
【问题描述】:

众所周知,面向对象的语言提供可重用性功能。

我有一个简单的三层应用程序:

  1. 表示层
  2. 业务层旨在获得可重用性的好处
  3. datalayer 是一个愚蠢的 ado.net 库(愚蠢的意思是它没有业务逻辑。)

我一直在努力在这个数据层中强制执行代码可重用性。我在数据层中的一个方法中粘贴了一个伪模式。

create connection object
open connection to database
create a transaction object
begin transaction
create command object
execute it
.
.
.
.
create nth command object
execute it
commit transaction
close connection

实际上,这段代码会膨胀到大约 300 到 400 行代码,因此无法阅读这段代码。

在这一系列命令执行中,我们在不同的表上选择/插入/更新查询。如果它不在事务中,我会将这段代码分离到它们各自的类中。

又是一个我最近遇到的意大利面图案:

business layer method1 calls datalayer method to update column1 
business layer method2 calls datalayer method to update column2
businees layer method3 calls datalayer method to save the entire result in table by updating it.

当我试图获得可重用性的好处时,这种模式出现了,这些方法是从不同的位置调用的,因此它们被重用了。但是,如果要编写简单的 sql 查询而不考虑可重用性,则将只调用一次数据库。

那么,有没有什么模式或技术可以在数据层实现可重用性?

注意:

  1. 我不想使用任何存储过程,尽管它们 提供预编译的好处等,因为它们往往会打成平手 更具体到特定数据库的数据层。
  2. 我目前也只在这里不考虑任何 ORM 解决方案 普通的 ADO.net。


借口不考虑任何 ORM。
  1. 学习曲线
  2. 避免与我认为可以的特定 ORM 的紧密耦合 通过限制数据层本身的 ORM 代码来移除。
  3. 6 个月前我上网查了一下,只有 当时有两种流行或广泛使用的 ORM 解决方案。实体 框架和 NHibernate。我选择实体框架(出于某些原因 稍后我会链接 link1, link2 除了我感觉使用 EF 会很容易,因为它是由 Microsoft 提供的)开始学习。
  4. 我在本书中使用了这个Microsoft recommended book 据我所知,有三种技术 TPT, TPHTPC; TPC 我从未尝试过。
  5. 当我检查从实体框架生成的 SQL 时,它是 非常丑陋并且正在创建一些额外的列:IDs,一些丑陋的案例 声明等,似乎对于一个高度事务性的系统 不能应用 ORM 解决方案。通过高度事务性系统,我的意思是每分钟发生 1000 次插入。数据库的大小继续膨胀,在遥远的将来会达到接近 500 到 600 GB。

【问题讨论】:

  • 动态 SQL 是唯一想到的东西,但这同样混乱(如果不是更混乱的话)。您不使用 ORM 的原因是什么?
  • “我希望有人提出解决方案,但请不要提出每个人都会推荐的解决方案。我想要一个不同的解决方案。”
  • 为什么不考虑 ORM 解决方案?不要重新发明轮子。不仅像 EF 和 NHibernate 这样的 ORM 框架已经解决了您遇到的问题,而且它们有很好的文档记录,并且很久以前就通过自己尝试解决了您将遇到的许多错误
  • 如果您出于某种原因真的坚持自己做,请阅读泛型和工作单元模式
  • @RyanHenderson 我同意你的观点,动态 SQL 是我想到的最丑陋的东西。即使这是这个宇宙中唯一的选择,我也永远不会使用它:)

标签: c# design-patterns architecture language-agnostic ado.net


【解决方案1】:

我同意 cmets 对您的问题的看法;如果可能的话,你真的应该避免在这里重新发明轮子并使用 ORM。根据经验,您最终将编写代码并解决早已解决的问题,从长远来看,这可能会花费您更多的时间。但是,我知道有时存在不允许使用 ORM 的限制。

以下是一些我认为有帮助的文章:

第一篇文章是一篇旧文章,但它解释了数据访问设计模式的不同选项。它有几种不同的模式,只有你才能真正决定哪一种最适合你,但听起来你可能想看看 Repository Pattern:

http://msdn.microsoft.com/en-us/magazine/dd569757.aspx

下一篇文章是讨论如何使用数据映射器实现存储库模式的系列文章中的第一篇,根据您上面的示例,这可能有助于减少一些冗余代码。

http://blogsprajeesh.blogspot.com/2010/02/data-access-layer-in-c-using-repository.html

最后,根据您实现数据访问模式的方式,您可能会发现模板模式和泛型很有帮助。以下文章对此进行了一些讨论,您可以从中收集一些有用的信息:

http://www.c-sharpcorner.com/UploadFile/rmcochran/elegant_dal05212006130957PM/elegant_dal.aspx

如果不了解您的项目的更多信息,很难准确地说出哪种模式最适合您的需求。但是,将工作单元模式与存储库和数据映射器结合使用可能会帮助您重用一些代码并管理您的数据访问。

【讨论】:

    【解决方案2】:

    我没有看到的是你的模型层。

    您有一个业务层和一个 DAO 层,但没有模型。

    business layer method1 calls datalayer method to update column1 
    business layer method2 calls datalayer method to update column2
    businees layer method3 calls datalayer method to save the entire result in table by updating it.
    

    为什么不是这样:

    business layer updates model/domain object A
    business layer updates model/domain object A in a different way
    business layer persists model/domain to database through data layer.
    

    这样您可以重复使用,并避免重复循环到数据库。

    最终听起来您的业务层对数据库数据模型了解太多了。您需要业务对象,而不仅仅是业务方法。

    【讨论】:

    • 我认为您的意思是DTOs:它们是在跨层对话中充当载体的对象,在这种情况下,业务层与数据层对话。是的,有一个包含所有此类 DTO 的单独项目;为了简单起见,我没有在这里展示
    • 这里还有一个有趣的地方需要注意的是,在一些来自业务层的数据库调用中,我不需要任何 DTO,我只是传递一些原始数据类型,例如 int、string 等。跨度>
    • 你能举个例子吗?这样的电话会是什么样子?是不是类似于:setCustomerToInactive(int custId)?
    • 是的,看起来就是这样
    • 我会改变它,使它不是 DAO 方法。我会让你的 DAO 坚持不活跃的客户。如果持久化不活跃的客户有什么特别之处,那么您最终可能不得不添加额外的逻辑......但老实说,如果您使您的 DAO 方法更粗糙,它将大大简化您的代码并提高您的可重用性。这与其他人推荐使用 JPA 解决方案的原因相同。 DAO 应该知道持久化整个实体,而不是单个列。否则,您将(稍微)打破对数据存储的抽象。
    猜你喜欢
    • 2010-10-19
    • 1970-01-01
    • 2011-03-23
    • 2014-08-05
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多