|
Example of inserting a Struct() into a database using keys |
A while ago a colleague and I were working on a timesheet application in Flex. The idea was that you could commit a custom timebar object, generated in flex, and it would update the dataset in the back end using the ColdFusion flex gateway.
I came across the code recently, and decided to tidy it up a bit, and make the query dynamic, based on the Struct contents. The obvious limitation to this is that your Struct and your database schema have to match exactly.
I won't go into the Flex application here, but I've emulated its input arguments here with a pre-populated structure.
2 timesheetTask = StructNew();
3 StructInsert(timesheetTask, "employeeid", '36');
4 StructInsert(timesheetTask, "timesheetDT", '0');
5 StructInsert(timesheetTask, "projectid", '6');
6 StructInsert(timesheetTask, "weekid", '25');
7 StructInsert(timesheetTask, "taskid", '39');
8 StructInsert(timesheetTask, "hours", '8');
9 StructInsert(timesheetTask, "comment", 'Comments for this task live here');
10 StructInsert(timesheetTask, "szStatus", '1');
11 StructInsert(timesheetTask, "iFirstLineApproval", '23');
12 StructInsert(timesheetTask, "iSecondLineApproval", '34');
13 StructInsert(timesheetTask, "iCurrentApprover", '');
14 StructInsert(timesheetTask, "szRejectReason", '');
15 StructInsert(timesheetTask, "szDescription", '');
16
17 updateTimesheet = createObject("component", "timesheet");
18 updateTimesheet.updateTask(timesheetTask);
19</cfscript>
Notice that this code also calls the CFC object at the end. The data itself isn't massively important, it's a time object for recording tasks.
Next we have the function, which accepts a Struct() argument called 'taskStruct'. I then loop through the structure, and populate a SQL query using the keys from a collection. The only logic is a check to see if it is the last structure element, as this controls the ',' placement.
2 <cfargument name="taskStruct" type="struct" required="yes">
3 <cfset var count = 0>
4
5 <cfdump var="#arguments.taskStruct#">
6 <cfset variables.structSize = structCount(arguments.taskStruct)>
7
8 <cfquery datasource="#application.dsn#">
9 INSERT INTO [dbo].[timesheet]
10 (<cfloop collection="#arguments.taskStruct#" item="key">
11 [#key#]
12 <cfset count = count + 1>
13 <cfif count LT variables.structSize>,</cfif>
14 </cfloop>)
15
16 <cfset count = 0>
17
18 VALUES(<cfloop collection="#arguments.taskStruct#" item="key">
19 '#arguments.taskStruct[key]#'
20 <cfset count = count + 1>
21 <cfif count LT variables.structSize>,</cfif>
22 </cfloop>)
23 </cfquery>
24
25 <cfreturn true>
26 </cffunction>
That will insert your Struct into a database, in small and tidy manner. It was somewhere around here that we started using cfproperty tags, and creating strongly typed objects for Flex.
|
AIR Phone Book application - Part 1 (CFC and GUI) |
I'm always asking what peoples phone numbers are in the office, we currently don't have any internal communications (like an intranet) so I thought I'd create a handy phone book application in AIR.
With FLEX of AIR applications I often wireframe them up with the data model in mind first. If you know what data you are going to display, and the format and delivery mechanism of that data, it can often have a large impact on the design and layout of your application.
In this instance I was just returning a simple query object of users and their phone numbers and a thumbnail image.
The CFC
My preferred server language is ColdFusion, so my service is a CFC object.
2
3 <cffunction name="getData" access="remote" hint="Gets phoneBook data" returntype="query">
4
5 <cfquery datasource="#application.dns#" name="qGetPB">
6 select id AS ID,
7 name AS Name,
8 number AS No,
9 image As Image
10 from phonebook
11 Order by name
12 </cfquery>
13
14 <cfreturn qGetPB>
15 </cffunction>
16
17</cfcomponent>
In my example I'm using an MS SQL database, so I have included the creation script here:
2GO
3SET QUOTED_IDENTIFIER ON
4GO
5SET ANSI_PADDING ON
6GO
7CREATE TABLE [dbo].[phonebook](
8 [id] [int] IDENTITY(1,1) NOT NULL,
9 [name] [varchar](20) NULL DEFAULT (NULL),
10 [number] [int] NULL DEFAULT (NULL),
11 [image] [varchar](55) NULL DEFAULT (NULL)
12) ON [PRIMARY]
13
14GO
15SET ANSI_PADDING OFF
Now that we know what the data will look like we can build the GUI front end.
My display layer is going to be a canvas, with another canvas inside it, to create a bordered effect.
Then I have a DataGrid, with a click event that will call an AS function. This will control the displaying of an image that corresponds to the user being clicked. Its always nice to see who you want to call!
2<mx:Fade id="fadeIn" duration="2000" alphaFrom="0.0" alphaTo="1.0"/>
3 <mx:Canvas id="outerCanvas" x="0" y="0" width="220" height="240" backgroundColor="#70c7f1" borderStyle="solid" cornerRadius="25" borderThickness="0">
4
5 <mx:Canvas id="innerCanvas" x="10" y="22" width="200" height="210" backgroundColor="#FFFFFF" borderStyle="solid" cornerRadius="25" borderThickness="0">
6
7 <mx:Label x="10" y="10" text="White label" id="header" styleName="header" fontWeight="bold"/>
8 <mx:Label x="78" y="10" text="Dating PhoneBook" styleName="greyHeader" fontWeight="bold"/>
9 <mx:DataGrid id="displayPeople" x="10" y="32" width="180" height="108" itemClick="changeImage(displayPeople.selectedItem.IMAGE)">
10 <mx:columns>
11 <mx:DataGridColumn headerText="Name" width="140" dataField="NAME"/>
12 <mx:DataGridColumn headerText="No." width="40" dataField="NO"/>
13 <mx:DataGridColumn headerText="Img" width="40" dataField="IMAGE" visible="false"/>
14 </mx:columns>
15 </mx:DataGrid>
16 <mx:Image x="138" y="150" source="@Embed(source='wldLogoTiny.png')" />
17 <mx:Image x="25" y="144" toolTip="{displayPeople.selectedItem.NAME}" id="userImage" visible="true" showEffect="{fadeIn}" />
18 </mx:Canvas>
19 <mx:Label text="_" styleName="controls" toolTip="Minimize" x="173" y="-2" click="onMinimize()" />
20 <mx:Label text="X" styleName="controls" toolTip="Close" x="184" y="1" click="onClose()" />
21
22 </mx:Canvas>
My 'userImage'has a showEffect attribute, that uses an image fadeIn method. It fades in the first image called, but not any others, I've had a play around with this, and I can't get it to fade in subsequent images, so if anyone has any ideas let me know!
Lastly I have added some chrome controls, as I will be removing the standard chrome, and building my own.
Now, on to the functions.
|
SQL Stored Procedures, UPDATE Template script |
This article deals with creating a SQL stored procedure for Updating a record.
In each of these stored procedure templates I am declaring a variety of documentation parameters in the header.
I've found these handy in the past when you are working in a team environment, or when you go back to a procedure at a later date. Its much easier to read a simple description in the header, than trawl through the SQL code looking for what it is doing.
So, this declares the procedure name, any parameters and return codes, and also details what it does, and who made it.
In a modified version of this I also hold the SVN revision number here.
2/* Company Name */
3/********************************************************************************/
4/* Procedure Name : dbo.ssp_stored_procname */
5/* Parameters : */
6/* Return Codes : */
7/* */
8/* Description : Description of what it does, params etc */
9/* */
10/* */
11/* */
12/* */
13/* */
14/* Author : Authorname */
15/* Date written : Date */
16/* History : version number */
17/* */
18/********************************************************************************/
The next block of code performs a select on the sysObjects table (part of the Master database). It is checking for the existence of itself. If it finds itself, it will drop the procedure. Note that throughout all of these scripts we are telling the user at each stage what is going on, by printing useful english output back to the screen.
2BEGIN
3 PRINT 'Dropping old version of dbo.ssp_stored_procname'
4 DROP PROCEDURE dbo.ssp_stored_procname
5END
6GO
By now we have identified whether or not the procedure previously existed, and if it did, we have dropped it, so we know that we are all good to go. So to create our Update procedure, we print out a message to the user, then using the "CREATE PROCEDURE" command we create our procedure.
At this point you substitute the "@field" value with your field name, and the [datatype] and (datasize) with the correct values. Just list your fields one after another, seperating with a comma. As this is creating an Update stored procedure I will list any of the values to update in the query here.
2GO
3
4CREATE PROCEDURE dbo.ssp_stored_procname
5 (@field [datatype](datasize),
6 @field [datatype],
7 @field [datatype](datasize),
8 @field [datatype](datasize),
9 @field [datatype],
10 @field [datatype])
After that we create the SQL code, as per usual. We have an Update statement, using the variables declared above in the SQL variable declaration (@var). Just write out your update like you normally would here. Then we check for any errors, and return a success message if it all worked ok!
2SET [field] = @field,
3 [field] = @field,
4 [field] = @field,
5 [field] = @field,
6 [field] = @field
7WHERE
8 ( [field] = @conditions)
9RETURN @@ERROR
10GO
11PRINT 'Creating procedure dbo.ssp_stored_procname - END'
12GO
Download the full template here.
|
SQL Stored Procedures, DELETE Template script |
This article deals with creating a SQL stored procedure for deleting a record.
In each of these stored procedure templates I am declaring a variety of documentation parameters in the header.
I've found these handy in the past when you are working in a team environment, or when you go back to a procedure at a later date. Its much easier to read a simple description in the header, than trawl through the SQL code looking for what it is doing.
So, this declares the procedure name, any parameters and return codes, and also details what it does, and who made it.
In a modified version of this I also hold the SVN revision number here.
2/* Company Name */
3/********************************************************************************/
4/* Procedure Name : dbo.ssp_stored_procname */
5/* Parameters : */
6/* Return Codes : */
7/* */
8/* Description : Description of what it does, params etc */
9/* */
10/* */
11/* */
12/* */
13/* */
14/* Author : Authorname */
15/* Date written : Date */
16/* History : version number */
17/* */
18/********************************************************************************/
The next block of code performs a select on the sysObjects table (part of the Master database). It is checking for the existence of itself. If it finds itself, it will drop the procedure. Note that throughout all of these scripts we are telling the user at each stage what is going on, by printing useful english output back to the screen.
2BEGIN
3 PRINT 'Dropping old version of dbo.ssp_stored_procname'
4 DROP PROCEDURE dbo.ssp_stored_procname
5END
6GO
By now we have identified wether or not the procedure previously existed, and if it did, we have dropped it, so we know that we are all good to go. So to create our Insert procedure, we print out a message to the user, then using the "CREATE PROCEDURE" command we create our procedure.
At this point you substitute the "@field" value with your field name, and the [datatype] and (datasize) with the correct values. Just list your fields one after another, seperating with a comma. As this is creating a delete stored procedure I will only be inserting one variable into the query.
2GO
3
4CREATE PROCEDURE dbo.ssp_stored_procname
5 (@field [datatype](datasize))
After that we create the SQL code, as per usual. We have a Delete statement, using the variable declared above in the SQL variable declaration (@var). Just write out your delete like you normally would here. Then we check for any errors, and return a success message if it all worked ok!
2WHERE (conditions = @var)
3RETURN @@ERROR
4GO
5
6PRINT 'Creating procedure dbo.ssp_stored_procname - END'
7GO
By using a script like this I've found that its really simple to have a repeatable standard process that is easy to implement across a team of developers, ensuring you get the same results, no matter who writes the query. It is also very useful if you have a seperate implementation team, as these scripts are re-runnable, they clear up after themselves.
Download the full template here.