blogs.conchango.com

welcome to the conchango blogging site
Welcome to blogs.conchango.com Sign in | Join | Help
in Search

SSIS Junkie

SSIS: Recordsets instead of raw files

Many moons ago on 8th February 2005 I posted a blog entry explaining how one could navigate over a recordset that is stored in an Object variable, created there by a Recordset destination. That blog entry is here: http://blogs.conchango.com/jamiethomson/archive/2005/02/08/960.aspx

As it transpired that blog entry became fairly redundant as new functionality appeared in the Foreach Loop container that allowed us to iterate over these recordsets using a Foreach enumerator (http://blogs.conchango.com/jamiethomson/archive/2005/05/30/1489.aspx).

Recently however people have started to question why, given the presence of a Recordset Destination, there isn't a Recordset Source. Well the main reasons are that:

  1. The Recordset Destination Adapter is not intended to be used for passing data between data-flows (that's what the raw file adapters are for)
  2. The structure of the recordset in the Object variable is not known at design-time so a Recordset Source Adapter would not be able to define its output metadata.

However, people are still asking for the implementation of a Recordset Source Adapter. A plausible reason for this may be that they don't like dropping data out to disk using a raw file - I can't think of any other possible reason.

So, given that the metadata of a Recordset stored in an Object variable is not known at design-time, there is no real need to build a custom adapter because we would still have to manually define the output metadata; therefore a scripted source component is more than adequate for our needs.

You may think that my method of doing this that I defined back in February 2005 would be adequate but frankly, it isn't! First of all it requires us to mess about with moving DLLs in order to use them and secondly the ADODB.dll doesn't exist anymore either, ADO functionality has been rolled into a different DLL. Thirdly it uses nasty, old and smelly ADO rather than shiny, new and snazzy ADO.Net. So all in all that's a very out of date blog post so we need a new method.

And here it is!!!

I'll assume that you know how a bit about building scripted source components so won't go into too much detail on that except to show the properties of our output:

20060105OutputProps.JPG

Our Recordset destintion is stored in an Object variable called "Recordset" and was populated by a previous data-flow. The recordset contains two fields: str_col and int_col.

Here is the code that iterates over the recordset, adding values into the pipeline as it does so. We use an OLEDB Data Adapter that has the capability to convert an ADO recordset (which is a COM object) into an ADO.Net DataTable. Like so...

20060105Code.JPG

 

It really as simple as that - the conversion from our COM Recordset to a navigable ADO.Net DataTable is just one simple line of code.

I'd like to give a big thanks to Larry Pope for helping me with this. It was he who came up with the code that allows you to do this.

 

If you want to see this working for yourself you can download the demo package from here: http://blogs.conchango.com/Admin/ImageGallery/blogs.conchango.com/jamie.thomson/20060105Recordsets.zip

-Jamie

UPDATE, 19th March 2008: I've just been using this same bit of code myself and got the following error:

The fix is as simple as it suggests. Make sure you add a reference to System.Xml.

-Jamie

 

Update 2, 19th March 2008: I've just found out that If a NULL DT_STR value is loaded into a recordset it won't still be a NULL when you consume it in another dataflow. In other words, this method of using the recordset will silently change NULL values. So my recommendation is now...DON'T EVER USE IT!

Published 04 January 2006 08:48 by jamie.thomson

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

SimonS said:

So why not use a raw file destination?

Personally I can't see the reason why the recordset destination was put in, just causes confusion.

Especially in your situation, as you are making a copy of the recordset as a data table. You are not maintaining type at all, recordset uses variants, which means the data table is using objects. So the amount of copying and conversions is really bad.

I think this is a good example of the flexibility of SSIS but should not be advised as a good solution.
January 5, 2006 22:52
 

jamie.thomson said:

Simon,
I agree...put people do want to do this. I would never recommend it though.

Recordset destinations definately have a use - for populating a recordset to be iterated over in a Foreach loop.

-Jamie
January 6, 2006 00:20
 

HarshB said:

Rather than the script source task, if Microsoft really tried - there must be a solution for the following problem:

"The structure of the recordset in the Object variable is not known at design-time so a Recordset Source Adapter would not be able to define its output metadata."

What I don't like about Raw File destination is that now I need to promote another file to my server, along with my package. Is there a way to avoid that?
January 19, 2006 20:03
 

Jamie Thomson - Life, the universe and SSIS! said:

January 23, 2006 20:07
 

Jamie Thomson - Life, the universe and SSIS! said:

January 23, 2006 20:08
 

Jamie Thomson - Life, the universe and SSIS! said:

January 23, 2006 20:30
 

Jamie Thomson - Life, the universe and SSIS! said:

Peter (sorry, don't know your surname) made a very good comment here: http://blogs.conchango.com/jamiethomson/archive/2006/02/20/2895.aspx#2903 that...
February 20, 2006 17:18
 

Jamie Thomson - Life, the universe and SSIS! said:

Peter (sorry, don't know your surname) made a very good comment here: http://blogs.conchango.com/jamiethomson/archive/2006/02/20/2895.aspx#2903 that...
February 20, 2006 17:24
 

Jamie Thomson - Life, the universe and SSIS! said:

Peter (sorry, don't know your surname) made a very good comment here: http://blogs.conchango.com/jamiethomson/archive/2006/02/20/2895.aspx#2903 that...
February 20, 2006 17:51
 

Jamie Thomson - Life, the universe and SSIS! said:

Peter (sorry, don't know your surname) made a very good comment here: http://blogs.conchango.com/jamiethomson/archive/2006/02/20/2895.aspx#2903 that...
March 10, 2006 09:20
 

Mark Garner’s Business Intelligence Blog » Blog Archive » SSIS Recordset Destination as Source? said:

May 15, 2006 22:14
 

jamie.thomson said:

HarshB,
There is no need to promote a raw file to your environment. All you need to do is set DelayValidation=TRUE on the data-flow that consumes the raw file.

-Jamie
May 30, 2006 10:20
 

Srinivas Sampath's Blog said:

I recently wanted to solve a problem. Basically I had employee data with me in one table and their attendance

November 3, 2006 10:00
 

Braulio_Malaga said:

With SSIS is easy to get a recordset in a variable, then you can play with it.. assign it to a loop,...

December 20, 2006 15:22
 

SSIS Junkie said:

Peter (sorry, don't know your surname) made a very good comment here: http://blogs.conchango.com/jamiethomson/archive/2006/02/20/2895.aspx#2903

January 8, 2007 14:42
 

LarryC said:

I noticed here: http://sqljunkies.com/WebLog/knight_reign/comments/7410.aspx you mentioned getting a OLEDB connection.  I'm not having any more luck than Kirk at getting it working.  I'm connecting to Oracle and using either the IDbConnection or the OleDbConnection type results in an invalid cast from a COM object.  I'm attempting to connect to Oracle.

As an alternative is there a way to use built in functionality to execute an Oracle stored procedure that has output parameters?  I keep getting invalid SQL Statement for pretty much anything I try.

February 6, 2007 14:41
 

Simon Givoni said:

Hi Jamie,

Thank you for this blog which I've been using intensively in the last year - you have a lot of very good articles here.

Why I don't use RAW-files:

I'm using configuration files to populate different project variables as where to put temporary data files etc. and I have a variable named: TempDir

Everytime I want to access a file in the TempDir I use the expression for Connection String to add the filename to the TempDir. Example:  TempDir + "myfilename.txt"

The Raw File Source dosn't have a Connection Manager but refers directly to a file in the filesystem (or a variable). So if i want to use a Raw File Source with my project I first need to create a new variable to hold the TempDir AND my filename for every new Raw file source I want to use (at least if I want to run them in parallel). Then I need to make a Script Task that puts these two strings togeter.

For me it seems like a lot of work for something that could be rather straigt forward with a connection manager or a expression directly in the Raw file source. Therefore I instead use CSV files which are easier to use.

Also if I want to append data to the raw file destination i need to do some "hack" to make it work because there isn't an option to: Create if new else append.

Regards

Simon

February 7, 2007 09:09
 

jamie.thomson said:

Hi Simon,

Thanks for your comments.

Don't fret. It is possible to set the location of a raw file dynamically just as it is with a connection manager. Are you aware they you can set the value of a variable using an expression? Hopfeully you'll be able to workout how this will be beneficial in your situation. You don't need to use a script task to do it.

The option to "create if new else append" IS actually there but I know what you mean. I assume the "hack" that you talk about is this: http://blogs.conchango.com/jamiethomson/archive/2006/06/22/SSIS_3A00_-Append-to-a-raw-file.aspx i.e. setting ValidateexternslMetadata=FALSE.  I wouldn't say "hack" is the word I would use - its more a necassary evil. Is this really a big problem to you?

Regards

Jamie

February 7, 2007 18:39
 

Simon Givoni said:

Hi Jamie,

Thank you for your response!

No I was actually not aware of how to set a variable with an expression - seem like a thing that is useful in many situations, my apology.

Yes it is not a "hack" but just very awkward.

Jamie wrote: "Is this really a big problem to you?"

Well, as any developer I try to be as "lazy" as possible and if I need to do a lot of setting up before I can use the component - specially if I add more columns under development it is too much hassle and I find other easier ways to do it (use CSV files). But I think it was partly my first problem, partly this problem that made me give up on the component.

Now you've informed me that I can use expressions to add values to variables - I will see if I can find some information on that. Do you have any blogs that describes this?

Regards

Simon

February 9, 2007 09:12
 

jamie.thomson said:

Simon,

No apologies necassary :)

Here is all my material pertinent to raw files: http://blogs.conchango.com/jamiethomson/archive/tags/raw+files/default.aspx   You may find something useful there.

And here's everything related to expressions: http://blogs.conchango.com/search/SearchResults.aspx?q=expressions&s=24

-Jamie

February 9, 2007 15:17
 

Scotty said:

good article, and i think this is what im looking for.  can i then refernce the fields in another script outside of the data flow task.  I want to put n a script compentant and complie text based on the data in the resultset?  

also, im getting an error(in short)   of   "class .variables cannot be indexed because no default property"

does anyone know what this means??

February 23, 2007 03:32
 

BI Thoughts and Theories said:

This is another example package. This one retrieves a resultset and stores it in a variable. It then

March 22, 2007 00:24
 

Jonathan said:

This is very useful - I am manipulating a dataset in memory via a script to combine data from a database source and a web service source into one along with some other transformations that I couldn't find any way to do with the included tools, but I couldn't find a way to get it back into the database efficiently - using a for-each iterator with a stored proc took about 20 minutes to finish, and I was only dealing with a few thousand rows.  I ended up using the dataset's ".GetXML" method and writing that to a string variable, and using an XML source, but I figured that they would have to be a better way.  Writing files to disc is not an easy option in my environment, especially in light of the fact that I need to get this in prod by the end of next week, and getting access to things generally takes longer than that :) Thanks!

May 17, 2007 19:55
 

Brian Laws said:

I've got a good usage for recordsets instead of raw files: the WMI Data Reader Task. You've only got two output options for this one: a variable or a text file connection. Raw files are not an option.

Let me tell you, this has been extremely frustrating. I am trying to create an application which will automatically pull down server log events. I'm using WMI and Win32_NTLogEvent to get this data. I would absolutely love to get this as a single, intact recordset as a source in a dataflow, but the solution above is the only I could find (and I looked hard). When you're dealing with many thousands of records (could easily by over 100k), it is obviously inefficient. Since the WMI data structures are clearly known and documented on MSDN, it's kind of remarkable, I think, that there isn't a better way to access the data. I definitely understand the argument about the recordset object not having defined types, but, like I said, the types are known for WMI classes.

I suppose I can use a flat file connection, but I'm very hesitant to do it for the dependency on structures on the disk. It's one more thing that needs to be properly configured. The filenames will also have to be dynamically generated. I'm also worried about the performance impact of using them. I'll give it a try, though, and see what happens.

But this really is a fantastic and very helpful article. It's just a bummer that I'm pretty much forced to have to use it. Good work, Jamie!

Brian

July 12, 2007 20:37
 

bhlaws said:

Actually, I don't think that flat files will work here either. I believe event logs contain a lot of line feeds, which would throw off the records. But I'll give it a shot now.

July 12, 2007 21:13
 

jamie.thomson said:

Hi Brian,

You raise a really really good point. Let me make sure I understand you correctly though. Are you basically saying that there's no way of accessing the results of a WMI query in the pipeline without resorting to a recordset or a text file? That's not great.

You have an interesting idea about outputting to a raw file. Very interesting indeed. I'm going to chew that one over for a bit and maybe submit something to Connect.

-Jamie

July 12, 2007 21:13
 

bhlaws said:

Thanks for the quick response!

Yes, you understand me correctly. I've found no way of using WMI in a data flow source short of the recordset or file. WMI apparently has no provider to connect to (it's always loading the winmgmt object). I can get LDAP but not WMI.

I personally think you'll see a lot more use of WMI (which is great, BTW) if an object model can be presented. The WMI classes are practically tables in a database (vast simplification, of course), so it would be awesome to interact with them as such.

Brian

July 12, 2007 21:18
 

bhlaws said:

Hmmm... it doesn't look my previous message posted. Sorry for the re-post if it did afterall.

But yes, you understand me correctly. I have no means of using WMI data as a source in a dataflow other than the recordset variable or the flat file. There is no WMI provider to connect to (that I can find). The only way I know to connect is with winmgmt and the WMI Data Reader task. I can connect to LDAP in a source, but not WMI.

I  think WMI would be used more (and I think WMI is great) if the class model was more easily accessible. Most (if not all) WMI classes are effectively tables in a big database (namely, the server). It's a vast simplification, of course. The structures of those tables are documented. I would absolutely love to see a straight-forward connection manager and data source where you can interact with WMI classes the same as you would with a SQL database.

Or perhaps just move the WMI Data Reader task into the Data Flow section as a Data Flow Source? That seems much more logical to me than having it as a Control Flow task.

Thanks for the quick reply!

Brian

July 12, 2007 21:42
 

bhlaws said:

BTW, I'm trying to handle the WMI problem a little differently. The WMI Scripting Guide : Part 3 (http://msdn2.microsoft.com/en-us/library/ms974547.aspx) discusses the use of the wbemFlagForwardOnly flag, which can dramatically speed queries. It even uses the Win32_NTLogEvent class as an example. So, since the WMI Provider doesn't have any place to set that flag, I'm thinking of ditching the WMI Data Reader task altogether and create the recordset directly from the script source component. I can then add the results to the output buffer.

Question: Do you know if it is possible to fill the output buffer without having to loop through and create rows? I found that it's a BufferWrapper class which wraps ScriptBuffer. Is there anyway to assign an entire recordset to the BufferWrapper class (such as converting the recordset into BufferWrapper)?

Brian

July 13, 2007 21:02
 

jamie.thomson said:

Brian,

I can't say with 100% certainty that its not possible but I'd be amazed if it was. That's the best answer I can give I guess.

Try asking on the SSIS forum.

-Jamie

July 13, 2007 22:01
 

Phil said:

I have found that if I use the above method in a script task and subsequently try populate a second data table with the same recordset, I get no data e.g.

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Dim ad As New OleDb.OleDbDataAdapter

Dim dt1 As New DataTable

ad.Fill(dt1, ReadVariable("myRecordset"))

System.Windows.Forms.MessageBox.Show("dt1 Count: " + dt1.Rows.Count.ToString) 'returns 5500 records

Dim dt2 As New DataTable

ad.Fill(dt2, ReadVariable("myRecordset"))

System.Windows.Forms.MessageBox.Show("dt2 Count: " + dt2.Rows.Count.ToString) 'returns 0 records

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Any ideas?

Phil.

July 18, 2007 17:35
 

Phil said:

ReadVariable method can be found at:

http://www.developerdotstar.com/community/node/512

July 18, 2007 17:37
 

Caesar said:

Jamie, Much obliged, once again for the terrific insight into SSIS. You helped me a while back with the flat file connector. Now I'm into Variables. I read an article about Shredding a REcordset by Allan Mitchell http://www.sqlis.com/59.aspx but it did not indicate we couldn't use the variable from a recordset in another data flow since recordsets are Object based. UGH!!!

So here's my Q: I want to set the precedence of a SENDMAIL task based on if an Error Table has a count > 0 in it.  I can't seem to figure out how to create a variable using a "Select count(*) ERRCount from ErrorCount" query. Once I can do that, I'll need to set the Precedence of the send mail if the count variable reaches > 0 i.e. @ErrCount > 0....  Can you provide any direction?

August 9, 2007 21:45
 

jamie.thomson said:

Caeser,

Is this any use: http://www.sqlis.com/306-1.aspx

-Jamie

August 9, 2007 21:55
 

Caesar said:

Hi Jamie,

Yes, thank you. That got me part way. I now see and understand how the variable is set using hard coded values. Where I hit the wall is setting my variable MyCount = an existing DTS Connection Manager in my package called 'MyServer.DatabaseName'.  I found an article that basically does what I want, but establishes the connection using an ODBC connection manager option. (http://blogs.simplifi.com/brucet/archive/2006/01/27/668.aspx) I had to add the SQL.XML reference to get that to compile. But I want to connect using an existing ADO.NET:System.Data.SQLClient.SQLConnection Connection manager set to my local SQL Server database called MyServer.DatabaseName.  I was able to compile the ODBC version but when I execute the task an error comes up stating: UNABLE to case object of type 'System.DAta.OracleClient.OracleConnection' to type 'System.Data.odbc.odbcConnection'.  I figure that has something to do with the sequence order of my connection mangers. Yet, when I cycle through DTS.Connections(0) ...(7), they all get the same error. I have 3 Oracle connections, 2 SQL, 2 flat file and the 1 ODBC (which I thought would be connection 7). Can you provide a reference article that explains how to set the variable using an existing .net connection manager?  Much obliged.

August 10, 2007 20:31
 

Caesar said:

PS: here's the code I lifted off using the ODBC example, but altered to suit my needs. Note the : DTS.Connections(1). I used (0)....through(7). All got the same Oracle related error message.  When I got to (8) the error was there was no #8 connection available.  I want to do Dim Conn as SQLClient.ConnectionManager or whatever the option is. Is this possible?

Public Sub Main()

Dim connName As String = Dts.Connections(0).Name

Dim conn As Odbc.OdbcConnection = CType(Dts.Connections(0).AcquireConnection(Nothing), Odbc.OdbcConnection)

Dim da As Odbc.OdbcDataAdapter = New Odbc.OdbcDataAdapter("select count(*) from mytable", conn)

Dim ds As Data.DataSet = New Data.DataSet()

Try

    da.Fill(ds)

    Dts.Variables("MyCount").Value = ds

Catch ex As Exception

    Dts.TaskResult = Dts.Results.Failure

    Return

Finally

    da.Dispose()

End Try

Dts.TaskResult = Dts.Results.Success

End Sub

August 10, 2007 20:35
 

Caesar said:

Hi Jamie,

Last update. I went another route using Execute SQL Task and set the variable using a SQL Query to load the variable. For others to reference, the link I used was:             http://www.sqlis.com/58.aspx    Then I set the precedence of the next step = Expresssion based where @MyCount > 0.

I do believe setting the variable can be done through script task as well but I was never able to figure out the VB.NET syntax to connect to an existing Connection Manager and run a query against it.  Thank you for your help, Jamie, as always.

August 14, 2007 15:10
 

jamie.thomson said:

Hi Caeser,

Yeah, the script task should work as well. There's some code on my blog that shows how to do it. Somewhere, I don't know where :)

Glad you got it working!

-Jamie

August 14, 2007 16:22
 

Rodney Kendall said:

Phil,

I realize it has been months since your post, but this is the first time I've found this.  Once you read a recordset, you have to 'reset' it to the beginning, or you will continue to read after the end.  Since the recordset was already read once, the second attempt actually starts at the end of the recordset, thus no results.

September 24, 2007 15:00
 

Julia said:

Hi Jamie

I'm trying to use your code pass on the results from a WMI Data Reader Task (just like  Brian), except when I use your code I'm getting this error:

 Object is not an ADODB.RecordSet or an ADODB.Record.

 Parameter name: adodb

I downloaded the package and on closer inspection it seems that the WMI Data Reader Task creates a variable that is DataTable rather than the __ComObject one in your download.

At least I think that must be the problem, I'm pretty new to this. Any ideas how I can code round this?

Julia.

October 14, 2007 18:17
 

Hery said:

Hi Jamie,

Thanks for this good article. I also have a problem with retrieving data row by row. Which is better using your method ini this article or using Recordset Destination ? I've tried using Recordset Destination and throw the data into a variable but it took time.

Best regards,

Hery

October 25, 2007 07:33
 

viswa said:

Hi Jamie,

Thanks for the good article.  I am using your code to read thru the recrodset but my requirement is to use the recordset in a loop.  Once the data is read from the global variable, it is getting empty and in the next run when I use it, I see no data.  Can you tell me, how do I persist data in the global varaible (recorset object) so that I can use it multiple times

Thanks

viswa

November 15, 2007 03:54
 

jamie.thomson said:

Hi Viswa,

Unfortunately you can't. I've looked into cloning the variable but can't figure out how to do that either. I ahve a Conenct submission asking for this functionality to be enhanced so you can do what your equire. Unfortunately Connect (http://connect.microsoft.com) is down at the moment so I can't link to it.

-Jamie

November 15, 2007 15:09
 

jamie.thomson said:

November 15, 2007 15:09
 

Mahi said:

Hi Jamie,

Can you Please help me on this..

I have a small req..like Sync between two databases based on time stamp of Source

this is my logic in dataflow task.

Data Reader Source ->Conditional Split ->two operations

1.Insert

2.Updates

if insert fails it needs to rollback the entire process..

i tried using the transactions at Sql task level (which is in a container ) and couldnt get success...

Now i am thinking to hold the result set of inserts into a recordset destination and then calling a script component and write the transaction logic...

wat do you say guyz...is this the best way to perform or any better ways??

Plz lemme know if  i shall explain you even more in detail..

Thanks,

Mahi

December 4, 2007 21:52
 

jamie.thomson said:

Mahi,

You haven't explained why you didn't have any success. It would help to know.

You may want to pose this question on the SSIS forum.

-Jamie

December 5, 2007 13:41
 

Matt Olson said:

I breezed through all the comments and I didn't see anything that really tells why it would be good to have a recordset source.  The scenario is this:

Without recordset source I would normally have to write to a file system.  This is an expensive time consuming operation to do, when we already have that data in memory, therefore keeping it in memory is the better way to do it, therefore recordset source is a better avenue.  Because after writing, we then have to READ it in again, hard drives are slow, memory is fast, writing to binary files makes no sense as it will take more CPU cycles and hard drive spinning to do that.

May 15, 2008 21:19
 

Matt Olson said:

Okay I see above where you did a performance comparison.  That performance comparison is counterintuitive.  I think if you made a managed recordset source the performance would be on par or greater then that for the reasons of not having to go back to the disk and write and read the data again which is a redundant operation.

May 15, 2008 22:00
 

jamie.thomson said:

Matt,

Feel free to give it (i.e. a managed recordset) a try and let us know.

-Jamie

May 15, 2008 22:05
 

Reza Alemi said:

Thank you Jamie for your great post, your site has been invaluable for me as a novice SSIS developer. this post was no exception. however, for all other novices out there, make sure to read <a href="http://forums.microsoft.com/TechNet/ShowPost.aspx?PostID=1406175&SiteID=17">this discussion</a> too. it took me two days to reach the exact same conclusion, and hopefully this doesn't happen to you. if it does, just use the ADO.NET connection type in source and it will give you ADO.NET DataTable in your variable, which you can reuse multiple times inside a loop. no need to refill it!

July 3, 2008 19:30
 

Jim Russell said:

Your code solved my problem. Because of the horrible flaw which keeps the SSIS FTP task from accessing mainframe files, it was necessary for me to build an FTP control file, and then use an execute process task to invoke an FTP command.

The flaw in the For Each Container approach (or at least my understanding of it) is that I needed some preprocessing (add FTP Commands to connect) then an FTP command line for each of the files to transfer (which I get from a script task) and then post process by adding a "BYE" command. I couldn't find a way to preserve a file number across a preprocess, for each, and post process task, and I didn't want to reopen the command file to append the command line for each source file, I needed to have the foreach code within my task to generate the FTP command lines.

You code gave me the approach I needed:

1. The execute sql task to return the source file name prefixes from a table

2. A script task to build the FTP Command file (with an inner foreach loop to get and process the source file prefixes)

3. An execute Process task to call FTP, saving std out and std error to variables

4. A final script task to write the std out and error variables to files.

(in case you noticed I have yet to define the data flow tasks to work with those input files I got via FTP, but that is next on the agenda!)

Thanks again!

September 10, 2008 19:52
 

DaveG said:

Can we see complete pacakge...?

I am trying to roll my own Cache object, in 2005...

and not having much luck :)-

Thx,

DG / FT. W, TX/ US

October 13, 2008 23:28

Leave a Comment

(required) 
(optional)
(required) 
Submit

This Blog

Syndication

News

Powered by Community Server (Personal Edition), by Telligent Systems