0

我已经编写了一个网关来从我的数据库中获取结果集。我如何将每一行存储在一个单独的 dao 中,以便我可以进一步操作每条记录?或者我可以直接访问结果集来获取记录吗?

这是我的网关(顺便说一句,我是否应该将 cfquery 中的条件逻辑写入扩展此网关的单独 cfc?)

<cfcomponent name="MaterialDao" hint="data access object" output="false">
 <cffunction name="init" hint="constructor" access="public" output="false" returntype="MaterialDao">
  <cfargument name="dsn" type="String" required="true" hint="datasource" />
  <cfset variables.instance.dsn = arguments.dsn />
  <cfreturn this />
 </cffunction>

 <cffunction name="readMaterial" hint="read" access="public" output="false" returntype="Query">
  <cfargument name="district" type="String" />
  <cfset var qReadMaterial = "" />
  <cfquery name="qReadMaterial" datasource="#variables.instance.dsn#">
   <cfif StructKeyExists(arguments,"district")>
   SELECT A.NR, A.BEZ, D.BES, D.STA
   <cfelse>
   SELECT A.NR, A.BEZ
   </cfif>
   FROM  DEK AS D INNER JOIN ART AS A
   ON D.NR = A.NR
   WHERE 0=0
   <cfif StructKeyExists(arguments,"district")>
    AND D.BEZ = #arguments.district#
   </cfif>
   ORDER BY A.BEZ
 </cfquery>
 <cfreturn qReadMaterial />
 </cffunction>
</cfcomponent>

我已经阅读了很多文章,似乎对这个问题有不同的看法(DAO vs. Gateway,DAO & Gateway 等)。什么是最佳实践,专业人士会做什么?

4

3 回答 3

3

专业人士只对数据库访问层使用一种模式。DAO 和网关的使用是一个误称,我不确定它从哪里开始,但似乎只存在于 ColdFusion 人群中。DAO 和网关模式几乎可以提供相同的功能,但我认为 DAO 更适合谈论数据库交互时。

DAO 应该包括 CRUD 方法的功能以及返回记录集。由于 CRUD 和基本记录集是高度重复的,因此我使用代码生成器来创建此交互的代码,然后自定义我需要的内容。这是选择所需记录的条件逻辑的好地方。

正如 Aaron 所提到的,由于创建对象的性能开销,在 ColdFusion 中为数据库中的一组记录返回对象数组是不可行的。在我的视图中,我通常只使用从 DAO 返回的基本查询。但是,如果我正在建模的事物需要视图中的某些行为,那么我将使用类似于 Peter Bell 所做的事情将查询放入对象中。

于 2009-06-22T12:38:15.277 回答
2

几个月前,Peter Bell 做了一个关于迭代业务对象 CFC 的精彩演示,它允许您使用这个简单的框架获取多条记录并一次迭代一条记录:http: //ibo.riaforge.org/。在 CF 生成对象的速度稍微快一点之前,回收对象的单个实例并重新填充属性可能是您最好的选择。也许这可以帮助您一次将一条记录加载到您的 DAO 中。

条件逻辑可以进入网关或管理器 CFC。通常,我会在 CFC 中包含简单的逻辑,就像您在帖子中概述的逻辑一样。

一点建议,您可能希望不再需要 arguments.distinct 并使用 if (structKeyExists(arguments, "distinct") ) { do something } 进行简单检查。

问候,

——亚伦·格林利

于 2009-06-22T11:39:17.237 回答
1

在我们公司,我们对这些东西思考了几个月,通过 RDS 和其他一些旧的(有人记得 CFPowerTools 吗?)尝试使用 Adob​​e CF DAO 创建器。

我们最终决定编写自己的 DAO 代码生成器,我想我会在这里分享我们的想法。我们决定的原因是因为我们需要在 SQL 中添加锁定提示,我们想让它更高效、更安全和更干净。

我们决定的设置是创建一个预定义的基本 DAO 对象(称为DAO.cfc),所有生成的“表”DAO 都扩展了该对象。它只有一些实用方法,但关键是我们可以在其中添加任何其他我们需要所有生成的 DAO 都可以访问的函数。

所以我们通过从数据库中选择一个表(使用 CF 管理 API)自动生成代码,并[TableName].cfc使用通常的 init、setter 和 getter 创建 DAO,所以基本的 CRUD 东西。

除此之外,我们还生成 a[TableName]GatewayBase.cfc和 a [TableName]Gateway.cfc[TableName]Gateway.cfc延伸[TableName]GatewayBase.cfc

因此,对于在名为“客户”的表上运行的示例 DAO,创建的文件是:

Customers.cfc /* extends DAO.cfc [not created, already exists] */
CustomersGateway.cfc 
CustomersGatewayBase.cfc /* extends CustomersGateway */

所以,这个想法是网关提供了一种处理许多“客户”记录的方法——在处理一个且只有一个时使用 DAO。网关中的所有方法一般都会返回一个 CF 查询对象。CF 效率太低,无法创建大量 DAO 对象数组,而且在我们看来,CF 中的查询对象非常灵活,因此我们很乐意使用它。

编码时,子类CustomerGateway.cfc是唯一实例化和使用的。但是,它扩展的基类有一些非常有用的泛型函数是免费提供的,比如getFieldListByProperty()基于传递的参数会通过某个属性(即列值)返回某些字段(即表列),例如:

myGateway.getFieldListByProperty(property="status", value="1", fieldList="customerName,customerID", orderBy="createdOn") />

That call will return the 'customerName' and 'customerID' values for all customers with a status of 1, ordered by the date they were created on. The code is also hardened against SQL injection and validated so sensible exceptions are thrown.

This function will provide 99% (we hope!) of the multi-record querying you do on a table. If you need a more sophisiticated query then the CustomerGateway.cfc is there for you to add functions to.

Finally, we allow you add functions to CustomerGateway CFC only because if you change the customers table (say add a column), you will need to recreate the table, and tha will overwrite the Customers.cfc and the CustomersGatewayBase.cfc. However, your custom code (if any) is safe in the sub-class.

Anyway, this might be slightly off topic, but sure I thought someone might find our experience useful.

于 2009-06-22T19:18:42.920 回答