1

I am looking to migrate from a custom framework to Coldbox.

The application has 3 datasources

  1. Core
  2. Common
  3. Site

The Core datasource stores information about the sites, the common datasource stores shared information, like the states table, and the Site datasource stores the data relevant to the website.

The Site datasource is changed per request based on the URL of the request, allowing each site to be sandboxed into its own database.

From my testing it seems that the DatasourceBeans generated by Coldbox and used in it's autowiring are stored/cached in the application scope. This is what I'm thinking to do, but the change to the datasource is persisted across requests.

In Coldbox.cfc

datasources = {
    Core   = {name="DSNCore", dbType="mssql", username="", password=""},
    Common   = {name="DSNCommon", dbType="mssql", username="", password=""},
    Site = {name="", dbType="mssql", username="", password=""}
};

and

interceptors = [{
    class="interceptors.Website",
    properties={}
}];

Interceptor named Website.cfc

<cfcomponent name="Website" output="false" autowire="true">

    <cfproperty name="dsncore" inject="coldbox:datasource:Core">
    <cfproperty name="dsn" inject="coldbox:datasource:Site">

    <cffunction name="Configure" access="public" returntype="void" output="false" >
    </cffunction>

    <cffunction name="preProcess" access="public" returntype="void" output="false" >
        <cfargument name="event" required="true" type="coldbox.system.web.context.RequestContext">
        <cfargument name="interceptData" required="true" type="struct">
        <cfset var q="" />

        <cfdump var="#dsn.getMemento()#" label="DSN before change" />
        <cfquery name="q" datasource="#dsncore.getName()#">
            SELECT
                Datasource
            FROM
                Websites
            WHERE
                Domain = <cfqueryparam cfsqltype="cf_sql_idstamp" value="#cgi.http_host#" />
        </cfquery>
        <cfscript>
        dsn.setName(q.Datasource);
        </cfscript>
        <cfdump var="#dsn.getMemento()#" label="DSN after change" />
        <cfdump var="#q#" label="Results of query" /><cfabort />

    </cffunction>
</cfcomponent>

Is there any way to do this in a way that I can use the Coldbox autowire datasource beans?

Honestly, this is just the way I thought I would do it, if anyone has any other ideas on how to get my model to use NON-hardcoded different datasource per request, I would love to understand the framework better.

This question also extends to ORMs. Is there a way for, say, Transfer to use a different datasource per request? What if the databases can have potentially different schemas? Lets say that one database has been updated to a newer version, but another still uses an older version and I essentially have some if statements in the code to provide enhanced functionality to the updated database.

You may be reading these questions and thinking to yourself "You shouldn't do that." Well i am, so please no answers saying not to do it. If you have ideas on better ways to have single codebase attached to different databases then I'm all ears though.

Tyler Clendenin
  • 1,459
  • 1
  • 12
  • 25

1 Answers1

1

Another way you could do it is by using the requestStartHandler in Coldbox.cfc

<!---config/Coldbox.cfc--->
requestStartHandler = "Main.onRequestStart"

<!---handlers/Main.cfc--->
<cffunction name="onRequestStart" returntype="void" output="false">
    <cfargument name="event" required="true">
    <cfquery name="q" datasource="#dsncore.getName()#">
        SELECT
            Datasource
        FROM
            Websites
        WHERE
            Domain = <cfqueryparam cfsqltype="cf_sql_idstamp" value="#cgi.http_host#" />
    </cfquery>

    <cfset rc.dataSource = q.Datasource />
</cffunction>

Then you just have your dataSource stored in the Request Collection becuase onRequestStart will fire on every Request.

jcreamer898
  • 8,109
  • 5
  • 41
  • 56
  • That would probably work, but it doesn't seem very coldboxy. Of course it does do one thing, it makes it so that I don't have to worry about doing the DSL in every model cfc. Though does that also means that it breaks encapsulation, or is using the DSL already doing that? – Tyler Clendenin Dec 21 '11 at 17:26
  • Does that mean that every function will need me to do rc=event.getCollection()? – Tyler Clendenin Dec 21 '11 at 18:52
  • I would say that in this case I might as well use a convention based approach and store the datasource info in a request variable. – Tyler Clendenin Dec 21 '11 at 22:36