Overloading Methods Must Be New To Oracle!

After loosing almost two days of work after getting the following error, I found what the real issue was.

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

The issue is being the code optimizer that I am, I wrote the following line of code to create an out parameter:

OracleParameter parameterModuleID = new OracleParameter("@o_someoutdata", OracleDbType.Int32, 4, ParameterDirection.Output);

I based this decision on the intellisense I got from the Oracle object below:

As you can see, the third parameter is the length of the parameters. This is very important for out parameters because it sets up a buffer. After almost two days of not understanding why the stored procedure was not working, checking and rechecking the parameters lengths about ten times and banging my head against the desk… I found the problem.

Enter the genius of Oracle method overloading:

As you can see, the third parameter is defined as object and is actually the value of the parameter! WHAT? Doesn’t Oracle know that every type is basically an object in .NET and they have screwed this up? What morons!

The Solution

Go back to SQL Server! Well, if you cannot do that, the Microsoft Oracle namespace does not suffer from this stupid mistake, only the namespace from Oracle. The other solution is just to define the parameter on two lines:

OracleParameter parameterModuleID = new OracleParameter("@o_ someoutdata", OracleDbType.Int32, 4);
parameterModuleID.Direction = ParameterDirection.Output;

Alternatively, just use this overloaded method:

OracleParameter parameterModuleID = new OracleParameter("@o_someoutdata", OracleDbType.Int32, 4,
DBNull.Value, ParameterDirection.Output);

The forth parameter “null” is the value of the parameter. Have fun!

Lockup’s Rule My Life Now

Another thing I have noticed is that my computer locks up three or more times a day now since I have started to use the Oracle namespace! For some reason I am suspecting that it is pegging out the CPU via the aspnet_wp.exe process. I am converting an ASP.NET portal application from SQL Server to Oracle. This did not start happening until I started to implement the Oracle code. It is not just me! The two other people where I work using the Oracle namespace are having the same issue.

 

Order DOES Matter?

Here is a gotcha, when adding parameters to the command object with the Oracle namespace, they must be in the same order as defined in the stored procedure!?!? Get just one out of order and you will not get back the expected results. What is the point in naming the parameters then? SQL Server does not work this way, you can send in the parameters any way that you want... as long as they are all there and named correctly.

 

Oracle Stored Procedures are Impotent

Stored procedure names in Oracle can only be 30 characters long while SQL Server allows for 128 characters. I hope to never see a stored procedure 128 characters in length, but 30 characters is way too short to name many stored procedures descriptively and easy to read (no abbreviations)!

 

Me No Like GUID’s

When the SQL Server database we are using was converted to Oracle, a few tables had a column in it with a GUID (not used as a unique identifier) type (uniqueidentifier in SQL Server). Well, come to find out Oracle does not have any knowledge of GUID’s, so on the Oracle side the data type of those columns were changed to RAW. While this holds the GUID just fine, using the GUID is not so easy.

When I get the data out as a DataSet, it looks like this (when I output my DataSet as xml):

<SOMEGUID>+FTyMzclhkSpHehUTUByAA==</SOMEGUID>

It should really look like this:

<SOMEGUID>CE55A821-2449-4903-BA1A-EC16DB93F8DB</SOMEGUID>

As you can see, the GUID from Oracle is useless. What to do? Well, not knowing how this can be fixed on the Oracle side (no one else where I worked seemed to know either), I wrote nifty little method that will fix a table.

public static void ConvertGuidColumns(DataTable data, params string[] columnNames)
{
  foreach (DataRow row in data.Rows)
  {
   foreach(string columnName in columnNames)
   {
    try
    {
     row[columnName] = new Guid((byte[])row[columnName]);
    }
    catch
{}
   }
  }
}

This simply takes in a DataTable and a list of column names. Loops though the rows and converts any column from the Oracle RAW (really a Byte array) to a GUID .NET can use.

You need to also watch out when saving GUID’s to the database via a stored procedure. This won’t work:

OracleParameter parameterGUID = new OracleParameter("@I_SOMEGUID", OracleDbType.Raw);
parameterGUID.Value = someGUID;

This will:

OracleParameter parameterGUID = new OracleParameter("@I_SOMEGUID", OracleDbType.Raw);
parameterGUID.Value = someGUID.ToByteArray();

 

Tip By: David McCarter


 
Categories: ADO.NET

SP1 includes a variety of improvements to the inital product release. Documentation for this release is provided in the SP1readme_lang.htm file which can be downloaded below or found in the Reporting Services installation directory after Setup is complete.

  • To view a list of the bug fixes in SP1, see Microsoft Knowledge Base article 839796.
  • Late-breaking information that was not available in time to be included in this readme file will be published on the Microsoft Product Support Services Web site in Microsoft Knowledge Base article 843369.
  • To get the complete set of installation instructions, see Microsoft Knowledge Base article 842857.

For the complete article, go to: http://www.microsoft.com/downloads/details.aspx?familyid=580febf7-2972-40e7-bccf-6cd90ac2f464&displaylang=en


 
Categories: ADO.NET | News

The Power Pack controls consist of:

  • BlendPanel. This provides a background for a form where the color fades from one shade to another.
  • UtilityToolbar. This is a toolbar whose look and feel is similar to the Internet Explorer toolbar.
  • ImageButton. This is a button that displays a graphic over a transparent background.
  • NotificationWindow. This displays text and graphics in a pop-up window (commonly known as "toast").
  • TaskPane. This is a container that provides collapsible frames for displaying additional information on a form.
  • FolderViewer. This displays directories in a hierarchical format.
  • FileViewer. This displays a list of the files in a specified directory.

For more information, go to: http://msdn.microsoft.com/vbasic/default.aspx?pull=/library/en-us/dv_vstechart/html/vbpowerpack.asp


 
Categories: dotNetDave | Link | VB.NET | WinForms

The exception would be on a (different) strange looking file name each time I would run the web service. For example the file name would be 4drv23rf.dll. Below is the entire error:

System.IO.FileNotFoundException: File or assembly name 4drv23rf.dll, or one of its dependencies, was not found.
File name: "4drv23rf.dll"
   at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase,
Boolean isStringized, Evidence assemblySecurity, Boolean throwOnFileNotFound,
Assembly locationHint, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Boolean stringized,
Evidence assemblySecurity, StackCrawlMark& stackMark)
   at System.Reflection.Assembly.Load(AssemblyName assemblyRef, Evidence assemblySecurity)
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly()
   at System.CodeDom.Compiler.CompilerResults.get_CompiledAssembly()
   at System.Xml.Serialization.Compiler.Compile()
   at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings)
   at System.Xml.Serialization.XmlSerializer.FromMappings(XmlMapping[] mappings)
   at System.Web.Services.Protocols.XmlReturn.GetInitializers(LogicalMethodInfo[] methodInfos)
   at System.Web.Services.Protocols.XmlReturnWriter.GetInitializers(LogicalMethodInfo[] methodInfos)
   at System.Web.Services.Protocols.MimeFormatter.GetInitializers(Type type,
LogicalMethodInfo[] methodInfos)
   at System.Web.Services.Protocols.HttpServerType..ctor(Type type)
   at System.Web.Services.Protocols.HttpServerProtocol.Initialize()
   at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context,
HttpRequest request, HttpResponse response)
   at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context,
HttpRequest request, HttpResponse response, Boolean& abortProcessing)
=== Pre-bind state information ===
LOG: Where-ref bind. Location = 4drv23rf.dll
LOG: Appbase = file:///c:/inetpub/wwwroot/WebService1
LOG: Initial PrivatePath = bin
Calling assembly : (Unknown).
===
LOG: Policy not being applied to reference at this time (private, custom, partial, 
or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/WINDOWS/Temp/4drv23rf.dll.

As you can see from above, the file was always located in my C:\WINDOWS\Temp\ directory. I really have no idea what this file is or why it’s placed in this directory. I thought all temporary ASP.NET files were saved to the C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files location.

After using Google for about an hour to search for solutions, I really did not find anything that seemed to fit my particular problem. Then on the way out the door (from work), I mentioned it to my co-worker. It seems he has had the same issue.

The Solution

It seems that the ASP.NET Machine Account (<machine name>\ASPNET) needs to have read/write access to the Windows temporary directory to create these temporary dll’s. Simply go to that directory, bring up the properties dialog and click on the Security tab. Click Add and add the ASPNET account. Make sure “Write” is checked and press Apply.

Tip By: David McCarter/ Mike Carr


 
Categories: Web Services