Oracle CLOBs, Enterprise Library, and Stored Procedure Output parameters — Oh, my!

Thursday, 30 June 2005 13:06 by Greg

Stored procedures are almost always the preferred place to put database intensive calculations.  Normally they do their thing and are done, and occasionally we get simple values out from them (strings and numbers).  And then there are the occasions where we want something more complex, like a LOB (large object binary) value.

If you were selecting a LOB value from a normal query, the code to fetch the value would look something like this:

byte[] binaryBlob = (Byte[])ds.Tables[0].Rows[0]["doc_bl"];

 But if your stored procedures looks like this:

PROCEDURE clob_out (OUT CLOB) is ...

things get much more complex. 

First, realize that passing out any LOB value from a stored procedure is essentially making it temporary, which means all your database code must be inside of a transaction.  If you forget to do this, you will get strange errors you will troubleshoot until you slap your forehead several hours later.

Second, you cannot use the GetOracleLob function that shows up in Visual Studio's help (and Enterprise Library's), as that is associated with a DataReader, which requires an output ref cursor from Oracle.  If you try it, you will get an error that says you do not have the right number of parameters associated with the stored procedure.  That's because Enterprise Library adds a cursor parameter for you!  (will remember that for future use!)

Onto the solution code:

db = DatabaseFactory.CreateDatabase() as OracleDatabase;

OracleCommandWrapper cmd = db.GetStoredProcCommandWrapper( "MyStoredProc" ) as OracleCommandWrapper;
cmd.AddParameter( "CLOB", System.Data.OracleClient.OracleType.Clob, 0, ParameterDirection.Output, true, 0, 0, "CLOB", DataRowVersion.Default, null );

using ( IDbConnection connection = db.GetConnection() )
{

connection.Open();
IDbTransaction transaction = connection.BeginTransaction();

try
{

db.ExecuteNonQuery( cmd, transaction );

Stream s = (Stream) cmd.GetParameterValue( "CLOB" );
Int32 clobSize = Convert.ToInt32( s.Length );
byte[] myValue = new byte[clobSize];
int read = s.Read( myValue , 0, clobSize );

}
finally
{

transaction.Commit();

}

}

 

Looks easy, right?  Note that there could be a potential error with the clobSize variable if your binary would exceed the Int32.MaxValue size, in which case you should implement some form of buffered reads.

Also note that I had to use the fully qualified AddParameter method.  That's because, for my situation, I needed a CLOB, not a regular BLOB. 

Enjoy!

 

 

 

 

 

 

 

Tags:   ,
Categories:   Professional
Actions:   E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

70-315 (ASP.NET/C#) Certification training guide recommendation

Monday, 27 June 2005 19:06 by Greg

This is the book I used to prepare for my certification exam, which helped a great deal.  Use the whole book, even if you think you know the material, and do all the exercises.  Take the quizzes.  When you are done, retake all the quizzes and then the practice exam.

You know you are ready if you score well on those quizzes and practice exam, and can pass any of the ones from Microsoft.

 

Tags:  
Categories:   Professional
Actions:   E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Using a configuration file other than app.config/web.config with Enterprise Library

Thursday, 23 June 2005 12:06 by Greg

One of the more fun things I get to do right now is design and build a brand spanking new application foundation for a very large ASP.NET application.  This is extra positive as this new foundation is being hashed out for a very small project, but will grow and evolve over time so when the big project comes along a lot of plumbing should already be in place.  Enterprise Library is going to be one of the major components of the new foundation.

Knowing this, I am building a number of class libraries and namespaces to segregate various pieces of functionality.  Along came the expected “foundation.data” class library and I hit a wall; Enterprise Library uses web.config (or app.config for WinForms) to store a key to where the rest of the Enterprise Library configuration is stored.  Foundation.data is just a class library and I really didn’t want to make it into something more than just that.  Besides, there is likelihood that this level of foundation would be used on both WinForms and Web apps.  No chance of hacking a solution with app.config or web.config.

I found my answer in a couple of blog entries relating to deploying Enterprise Library with beta2.  Not having played with it much yet I can’t comment on why this was needed, but James White came up with a number of source changes to make everything work in this post.  I messed up on implementing it the first time, placing my filename replace too late in the method.  I eventually downloaded James’s full beta 2 build of Enterprise Library and checked his code there.  That is displayed in its entirety below:

ConfigurationBuilder.cs :: LoadMetaConfiguration

private void LoadMetaConfiguration(string configurationFile)
{
    configFile = new ConfigurationFile();
    string machineFilename = MachineConfigurationFile;

    // make sure we don't load the machine file twice
    if (string.Compare(configurationFile, machineFilename, true, CultureInfo.InvariantCulture) != 0)
    {
        ConfigurationFile machineConfigFile = new ConfigurationFile();
        bool machineFileExists = machineConfigFile.Load(machineFilename);
        if (machineFileExists)
        {
            configFile = new ConfigurationFile(machineConfigFile);
        }
    }

    configurationFile = configurationFile.Replace("web.config", "enterpriseLibrary.config");
   
    configFile.Load(configurationFile);
   
    CreateMetaConfigChangeWatcher();
   
    this.currentConfigFileName = configurationFile;
    InitializeConfiguration(ReadMetaConfiguration());
}

The new configuration file (enterpriseLibrary.config) now contains only the Enterprise Library specific settings, looking something like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="enterpriselibrary.configurationSettings" type="Microsoft.Practices.EnterpriseLibrary.Configuration.ConfigurationManagerSectionHandler, Microsoft.Practices.EnterpriseLibrary.Configuration, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null" />
  </configSections>
  <enterpriselibrary.configurationSettings xmlns:xsd="
http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" applicationName="Application" xmlns="http://www.microsoft.com/practices/enterpriselibrary/08-31-2004/configuration">
  <configurationSections>
    <configurationSection xsi:type="ReadOnlyConfigurationSectionData" name="dataConfiguration" encrypt="false">
      <storageProvider xsi:type="XmlFileStorageProviderData" name="XML File Storage Provider" path="dataConfiguration.config" />
      <dataTransformer xsi:type="XmlSerializerTransformerData" name="Xml Serializer Transformer">
        <includeTypes />
      </dataTransformer>
    </configurationSection>
  </configurationSections>
  <includeTypes />
</enterpriselibrary.configurationSettings>
</configuration>

 

 

 

Note that the actual name and location of the new configuration file is entirely up to you.  James originally suggested placing it in its own folder, for now I am opting to keep it in the main application directory.

Here are a couple of notes on this whole process:

  • The Enterprise Library configuration tool filters only for app.config and web.config, so you will need to filter for all files.  You have the source to that application and can change it in your spare time if it really annoys you.
  • I changed all my revision numbers in Enterprise Library to differentiate it from the original release.
  • Changes made to enterpriseLibrary.config (or your new configuration file name) will not automatically reset a web application.  This likely means more during development than production, just something to note.
  • I have not yet tested to see if you can nest these new configuration files in subdirectories the way you can with web.config files.  For example, if a admin subdirectory needed additional configuration settings the main application would not want/use.  Not sure I really care as I haven’t yet found the need to nest web.config files.

Would be nice if future releases of Enterprise Library will make this a tad easier.  Hope this helps someone else, as it was a bear to find and implement just right.  Thanks James White and Scott Densmore!!!

Tags:  
Categories:   Professional
Actions:   E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Speaking at the next Richmond .NET user group

Wednesday, 22 June 2005 20:06 by Greg

I will be presenting at the next Richmond .NET user group meeting June 30th at 6:30 PM.  Below is the blurb on the presentation, but the real reason to come is we will have a ton of prizes from Microsoft (left over from the last meeting), INETA, and Wintellect to give away, to say nothing of the fantastic pizza Farrenheit Technologies buys for us.  Hope to see you there!

NET Tools, Toys, and Techniques: A Devscovery Recap

There are the things we all do to get the job done, then we hear about the "right" way to do things. So how exactly do we go from "normal" procedural (e.g. its all behind the button_click! ) code to something that is unit testable and more reusable?

Greg Postlewait will go over some of the things he learned at this past Devscovery, including architecture to support unit testing, exception-centric code development, source code performance differences, and tools that make our jobs easier.

For example:

  • NUnit
  • NDoc
  • FXCop
  • Resharper
  • CommenTater (?!)
Tags:   ,
Categories:   Professional
Actions:   E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

More comment anti spam

Wednesday, 22 June 2005 20:06 by Greg

Well that was “fun”.  The good news is everything is working pretty much as I had hoped.  The comment code is more readable and a length that seems reasonable.  No more crashes or unhandled exceptions being thrown around.

Here are the properties set on Migual's component:

<cc1:HIPControl id="HIPControl1" runat="server" TextPattern="Horizontal" TextColor="Red" CodeLength="4"     RandomCodeLength="False" TextPatternColor="Firebrick" TrustAuthenticatedUsers="True" ValidationMode="Forms"     PersistDotTextComments="True" ImageWidth="120" ValidationIgnoreCase="True" AutoRedirect="False"></cc1:HIPControl>

The major crashes were occurring due to a default ValidationMode being ViewState; Forms just works better.  All this came to pass by setting .Text up as a debuggable solution in Visual Studio.  Not hard, just time consuming, but it turned out to be a good thing.  For whatever reason, if you clicked on an article's feedback link (that links directly to the comments section of a post), the image would not come up.  If you went just to the article, the image would come up fine.  So I changed .Text to not display the section link and just the text.  Problem solved for now.

 

My only other request is to allow a ValidationControl to be used with this component.  That would flow nicer with the rest of the control layout.  Maybe he'll send me the source code (nudge, nudge, wink, wink...)

Tags:  
Categories:   Professional
Actions:   E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Preventing comment spam

Tuesday, 21 June 2005 08:06 by Greg

I am going to give this technique a try, as put together by Migual Jimenez (another version is here). The idea is to put a “code” in an image down by the submit button and require the user to enter it prior to form submission.  People can read it, machines cannot, so automated comment spam bots should, theoretically, be unable to spam my comments section.

I installed Migual's without having to make any code changes, but there are a few issues I want to address.  Its a bit hard to read and I'd prefer only 3-4 characters be required (instead of the occasional 6).  And I'd like the validation controls to work as well.

So, the good news is my new blog is relatively protected from 'bot comment spam.  And it discourages people spam as well.  Hmm...

Tags:  
Categories:   Professional
Actions:   E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed