当 CFC 中的 SESSION 变量用于数据源和数据库模式时,如何避免使用这些变量?
我正在尝试重构所有 CFC 以避免使用 SESSION 和 APPLICATION 变量(这不是一件容易的任务)。
但是,在此应用程序中,SESSION 变量在每个数据库调用中使用,因为不同的登录用户可能正在访问不同的数据库和模式:
<cfquery name="qEmployees" datasource="#SESSION.DataSourceName#">
SELECT *
FROM #SESSION.DatabaseSchema#.Employees
</cfquery>
我不想经历将这两个 SESSION 变量传递给访问的每个方法调用的麻烦数据库。尤其是这种情况,因为我不想在远程 AJAX 调用中传递 DSN 和架构名称。
对于所有不应该在 CFC 中使用的范围,执行此操作的最佳实践是什么?
I'm trying to refactor all of my CFCs to avoid using SESSION and APPLICATION variables (not an easy task).
However, in this application, SESSION variables are used in every database call, since different logged in users may be accessing different databases and schemas:
<cfquery name="qEmployees" datasource="#SESSION.DataSourceName#">
SELECT *
FROM #SESSION.DatabaseSchema#.Employees
</cfquery>
I don't want to go through the trouble of passing these two SESSION variables to every method call that accesses the database. This is especially the case since I don't want to pass DSNs and Schema Names in remote AJAX calls.
What is best practice for doing this - for all Scopes that shouldn't be used in CFCs?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我认为,由于数据源确实是变量,我会将其作为可选参数传递到每个函数中,并将默认值设置为变量范围的 dsn 属性。我在 CFC 的构造函数中设置了 DSN 范围内的变量。这样您只需传入 AJAX 调用的 DSN。
我将使用应用程序的会话范围来存储用户 dsn 名称并使用该 var 传递给 AJAX 调用。
I think that since the datasource truly is variable I'd pass it into every function as an optional parameter and set the default value to a variables scoped dsn attribute. I'd set the variables scoped DSN in the CFC's constructor. That way you only have to pass in the DSN for the AJAX calls.
I'd use the session scope of your app to store the users dsn name and use that var to pass to the AJAX call.
您应该创建一个“init”方法作为 CFC 的构造函数。然后,您可以实例化 CFC 并将它们存储在共享范围(很可能是应用程序范围)中。从这里开始,为了通过 AJAX 使用此 CFC,我通常会创建一个远程外观。基本上,这是另一个将直接访问应用程序范围内的 CFC 实例的 CFC。它将实现您需要通过 Ajax 访问的方法,并使用
access="remote"
公开它们,使您的应用程序能够访问实际 CFC 中的access="public"
方法。在这种情况下,人们普遍认为远程外观可以直接访问应用程序范围作为设计模式的一部分。一个简单的例子:
example.cfc:
在您的 Application.cfc onApplicationStart() 方法中:
remote.cfc:
You should create an "init" method that will serve as a constructor for your CFC. You can then instantiate the CFCs and store them in a shared scope, most likely the application scope. From here, to use this CFC via AJAX, I typically will create a remote facade. Basically this is another CFC that will directly access the CFC instance in the application scope. It will implement the methods you need to access via Ajax, expose them using
access="remote"
giving your application access to theaccess="public"
methods from the actual CFC. In this case it is generally accepted that the remote facade can access the application scope directly as part of the design pattern.A simple example:
example.cfc:
In your Application.cfc onApplicationStart() method:
remote.cfc:
onRequest 或 onRequestStart 函数中设置数据源变量吗?
您可以在 Application.cfc等的
不确定这是否有效[未经测试 - 实际上感觉有点草率]
-肖恩
Can you set your datasource variables in the onRequest or onRequestStart functions in your Application.cfc
etc.
not sure if that will work [not tested - actually feels a bit sloppy]
-sean
您选择的范围(对于此问题的任何变体,而不仅仅是 DSN)应基于值的生命周期是否与范围的生命周期相同。
在我们的应用程序中,DSN 在应用程序的生命周期中仅设置一次,因此我们有一个在 onApplicationStart 中创建(从文件中解析)的 application.config 结构,其中包含 application.config.dsn
如果您的值确实如此确实会在会话之间发生变化,但不会在会话的生命周期内发生变化,请继续使用会话范围。
如果您的值可能针对任何给定请求而更改,但不会在请求中间发生更改,请将其放入请求范围中。
也就是说,仍然听取 ryan 的建议并添加仅默认为该值的可选参数:灵活总是最好的。
The scope you choose (for any variation of this question, not just for DSNs) should be based on whether the lifetime of the value is the same as the lifetime of the scope.
In our application, the DSN is just set once in the lifetime of the application, so we have an application.config struct that gets created (parsed from a file) in onApplicationStart, and within it is application.config.dsn
If your value really does change between sessions, but not over the life of a session, go ahead and use the session scope.
If your value could change for any given request, but not in the middle of a request, put it in the request scope.
That said, still heed ryan's advice and add optional arguments that only default to this value: being flexible is always the best.
我对此的建议是创建一个基类,然后让需要数据库访问的组件扩展该组件。它不必位于直接父层次结构中,而是位于下线的某个位置。
他们的目标是做两件事,使 cfc 从主程序中抽象出来并使其易于配置。这样就达到了两者的目的。
因此,查询数据库的 CFC 将如下所示:
上面的关键是
extends="DataAccessBase"
部分。这增加了抽象层,您可以在一个可配置点控制数据访问,但它不依赖于应用程序本身,从而使组件从其实现位置抽象出来。您的
DataAccessBase.cfc
可能如下所示:当然,您可以对如何配置和存储设置等变得更加复杂,但这超出了我认为问题的范围。 :)
我认为没有任何理由在每次方法调用时传递 DSN。是的,它有效,但没有必要。这些组件是根据数据结构的内置假设开发的,因此您知道它不会从 addItem() 调用更改为 updateItem() 调用,因此其重复工作意味着额外的故障点。 :P
有道理吗?
My suggestion for this is to create a base class and then have your components that need database access extend that component. It doesn't have to be in the immediate parent hierarchy but somewhere down the line.
They goal is to do two things, keep the cfc abstracted from the main program and keep it easily configurable. This accomplishes both.
So your CFC that queries the database would look something like this :
The key above is the
extends="DataAccessBase"
portion. This adds the layer of abstraction where you can control the data access at one configurable point, but it's not tied to the application itself, leaving the component abstracted from where it's implemented.Your
DataAccessBase.cfc
could look something like this:You can of course get more intricate with how you configure and store the settings etc, but that's out of scope of the question I think. :)
I don't see any reason to pass the DSN with every method call. Yes, it works, but it's not necessary. The components are developed with a built-in assumption of the datastructure so you know that it is not going to change from a addItem() call to a updateItem() call, thus its duplication of work which means additional points of failure. :P
Make sense?