Oracle Client Tools and the .NET System.Data.OracleClient dll

Remember next time you use OracleClient namespace. This dll depends on the Client Tools from Oracle, so that has to be installed in the server and the folder has to have the proper security settings.
If you get the error:

System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.

and your tnsnames.ora file is fine, your connection strings look good, the client tools you have are for sure of a higher version than 8.1.7 then check the permissions of the folder where the Oracle Client Tools are installed.

Problem
When usign System.Data.OracleClient with Oracle9i client, i got the following message while connecting to the Oracle database from and ASP.NET application.

System.Data.OracleClient requires Oracle client software version 8.1.7 or greater.

Cause
Security permissions were not properly set when the Oracle Client was installed on Windows with NTFS. The result of this is that content of the ORACLE_HOME directory is not visible to Authenticated Users on the machine; this again causes an error while the System.Data.OracleClient is communicating with the Oracle Connectivity software from an ASP.NET using Authenticated User privileges.

Solution
To fix the problem you have to give the Authenticated Users group privilege to the Oracle Home directory.

  • Log on to Windwos as a user with Administrator privileges.
  • Start Window Explorer and navigate to the ORACLE_HOME folder.
  • Choose properties on the ORACLE_HOME folder.
  • Click the “Security” tab of the “Properties” window.
  • Click on “Authenticated Users” item in the “Name” list.
  • Uncheck the “Read and Execute” box in the “Permissions” list under the “Allow” column.
  • Re-check the “Read and Execute” box under the “Allow” column
  • Click the “Advanced” button and in the “Permission Entries” verify that “Authenticated Users” are listed with permission = “Read & Execute”, and Apply To = “This folder, subfolders and files”. If not, edit that line and make sure that “Apply To” drop-down box is set to “This folder, subfolders and files”. This should already be set properly but it is important that you verify it.
  • Click the “Ok” button until you close out all of the security properties windows. The cursor may present the hour glass for a few seconds as it applies the permissions you just changed to all subfolders and files.
  • Reboot, to assure that the changes have taken effect.

Try your application again.

DAAB 1.1 notes

Tsk Tsk Tsk. I put my hands recently on the DAAB 1.1. i had used it before with SQL Server and indeed was a great experience.
I got quite a disappointment when i tried this block against Oracle 9i.
I used System.Data.oracle client as provider to form my OracleCommand and to my surprise I wasn’t able to bind System. Int32 data types to OracleType.Number and the parameters marked with output direction always returned the error of buffer to small to allocate the response.
My hunch is the DBCommandWrapper class of the DAAB 1.1 block has something missing…
I tried using a different provider and downloaded ODP.NET from Oracle site. This will incurr on having an extra dll to deploy with my project, but that didn’t work either.

The scenario to reproduce the errors is as follows:

In the method that calls the SPROC I have the following:

Dim IObject As ICommonFactory

Dim cmd As New OracleClient.OracleCommand

Dim myQuote As New DataSet

Try

‘Write to Trace if Enabled

ServiceHelper.RoutineBegin(Debug)

cmd.CommandText = “web.sproc_request”

cmd.CommandType = CommandType.StoredProcedure

With cmd

.Parameters.Add(“NO”, OracleType.VarChar).Value = “333-333333-333”

.Parameters.Add(“iTEMPLATE”, OracleType.VarChar).Value = “XX_XX_COMBINED_ENGLISH”

Dim parameter As New OracleParameter

parameter.ParameterName = “oXML_STRING”

parameter.OracleType = OracleType.VarChar

parameter.Size = 10000

parameter.Direction = ParameterDirection.Output

.Parameters.Add(parameter)

End With

IObject = ObjectCreator.CreateObject(“MyApp”, “Factory”)

Quote_InitialRequest = IObject.GetList(cmd)

‘Write to Trace if Enabled

ServiceHelper.RoutineEnd(Debug)

Catch ex As Exception

Throw

End Try

The GetList Method of the factory looks like this:

Imports Microsoft.Practices.EnterpriseLibrary.Data

Public Function GetList(ByVal cmd As
System.Data.OracleClient.OracleCommand) As System.Data.DataSet Implements ICommonFactory.GetList

Dim db As Database =
DatabaseFactory.CreateDatabase(System.Configuration.ConfigurationSetting
s.AppSettings(“MyApp”), “Common”)

db.ExecuteNonQuery(CommonCmdWrapper.PrepareCommand(db, cmd))

Dim myData As New DataSet

GetList = CType(cmd.Parameters(2).Value, System.Data.DataSet)

End Function

The exception is thrown in the lne db.ExecuteNonQuery and the exception message is as follows:

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

ORA-06512: at “MyApp.WEB”, line 990

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

ORA-06512: at line 1

” String

The stack trace is as follows:

StackTrace ” at
System.Data.OracleClient.OracleConnection.CheckError(OciErrorHandle
errorHandle, Int32 rc)

at System.Data.OracleClient.OracleCommand.Execute(OciHandle
statementHandle, CommandBehavior behavior, Boolean isReader, Boolean needRowid, OciHandle& rowidDescriptor, ArrayList&
refCursorParameterOrdinals)

at System.Data.OracleClient.OracleCommand.Execute(OciHandle
statementHandle, CommandBehavior behavior, Boolean needRowid, OciHandle&
rowidDescriptor)

at
System.Data.OracleClient.OracleCommand.ExecuteNonQueryInternal(Boolean
needRowid, OciHandle& rowidDescriptor)

at System.Data.OracleClient.OracleCommand.ExecuteNonQuery()

at
Microsoft.Practices.EnterpriseLibrary.Data.Database.DoExecuteNonQuery(DB
CommandWrapper command)

at
Microsoft.Practices.EnterpriseLibrary.Data.Database.ExecuteNonQuery(DBCo
mmandWrapper command)

at
CIT.EAI.CS.ECS.OracleObjectFactory.PQSFactory.GetList(OracleCommand cmd) in C:\CIT.EAI.CS.ECS.OracleObjectFactory\PQSDEV\PQSFactory.vb:line 27

at QuoteSystem.QuoteSystem.Quote_InitialRequest(String ContractNo, String TemplateName, String BuyOutType, Boolean Debug) in c:\inetpub\wwwroot\QuoteSystem\QuoteSystem.asmx.vb:line 90″
String

No matter how much I increase the size of the varchars I always have the same error.

I executed the Oracle command in SQL Navigator and it only returns the
ORA-06502: PL/SQL: numeric or value error: character string buffer too small when the output parameter has a size smaller than 2000.

The CommonCmdWrapper is part of the
Microsoft.Practices.EnterpriseLibrary.Data and it seems to be the layer causing the problem.

When using only the System.Data.OracleClient namespace, the call goes through without problems.

I tried contacting the Pattern & Practices team unsuccessfully…

Membership and Roles API and the WSAT

Last June 3rd I flew Saskatoon for the day and met with the .NET Users Group. It was good to see colleagues and ex-coworkers. I was presenting four demos regarding VS 2005 and SQL server 2005 with Service Broker. The presentation didn’t go very well as I had a hard drive error on one of my VPC images. Apart from that I noticed a great interest in the new technology, specially SQL Server 2005 Service Broker and web services support.
I also got very interesting questions from the audience. One of them was regarding the ASP.NEt Configuration tool or WSAT, Web Site Administration Tool.
The original question was:

We are planning to extend the Membership API to use it on our own intranet with existing databases; however, one of the advantages of using this API is also having the Web Site Administration Tool available to manage Memberships and Roles.

After a short investigation, especially reading this article:

http://msdn.microsoft.com/msdnmag/issues/05/04/Security/

and this one:

http://www.devx.com/codemag/Article/30087/0/page/3

we realized this WSAT tool is only available with VS 2005. We would like to know though, why isn’t this application available outside VS 2005. What dependencies are shared with VS 2005, so this application cannot be deployed as a stand alone solution?

You can call the tool outside VS 2005, by typing http://localhost/MyWebSite/Webadmin.axd on your web browser.

Juval Lowy’s replies:

In any event, I solved the problem you describe using my Credentials Manager tool described in this article:

http://www.code-magazine.com/Article.aspx?quickid=0511031

Unless you do some hacking, the admin pages (besides not providing all the required features) can only work with Cassini.

The WSAT does not use IIS both for security reasons and because many developers are not allowed to have IIS installed. The ASP.NET team recommends you use Credential Manager for real life admin.

You can use Credentials Manager freely (make sure you get the latest version from www.idesign.net) and even modify it as long as you maintain our copy rights and give credit to IDesign in your docs.

And Jeff Prosise’s replies:

WSAT was originally intended to work locally or remotely, but the ASP.NET team grew concerned about security, so in the final release, it only works against local Web servers. You can modify the source code to work against local servers, but in general your best bet is to use the membership and roles APIs to write your own targeted remote admin tool.

The source code is in the ASP.NETWebAdminFiles directory (e.g., C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles). You can install it in a virtual directory and run it without Visual Studio.

You can modify it to work against remote servers if you wish.

I hope this helps the Community and also stays here on this blog for my own future reference.
Thank you guys and thanks to Saskatoon .NET User Group for their understanding and support during the hard drive failure.

INETA launch, 2nd part, Saskatoon, Sat June 3rd.

Saskatoon there I go on Saturday!
I’d like to invite all the .Net developers in the Saskatoon area to a short presentation I’ll be giving this Saturday on the U of S, College of Enginering. Details of the event can be found here.
I’ll be doing 5 demos in total regarding Data Access, Membership, Profiles APIs in ASP.NET 2.0 and XML Support and Web Services in SQL Server 2005.
I upgraded my laptop last night to 1.5GB or RAM, so hopefully the VPC will run faster this time.
I would like to thank Bob Beauchemin
for his help preparing the SQL Server 2005 demos, he is a well known speaker and wrote the original Data Platform Series for Microsoft Launch. I appreciate the time he took to answer my questions regarding the CacheSync demo and the tips he gave me for optimizing the VPC.

I still have to prepare myself more tonight and take the time for the final presentation. I hope the audience enjoys the content as much as I did when I attended the Data Platform and Developer Track training.

Cheers!

Database dump in MySQL vs SQL Server 2000

Last Friday before leaving work, I had to make a database dump to copy some data over another SQL Server. I had always used the DTS packages to export or import data, however when using a DTS package you need to know the Server Name and login credentials for both the source server and the destination. You can also import or export to different file formats such as excel sheets, access databases, comma separated files .csv or text files.
I didn’t know the name of the destination sql server, nor the credentials to log into that server, one of the requirements from the other team was to get the DTS package already, not only the files with the data.
I then though, well, I should be able to generate a .sql file with the insert statements, this way all they have to do is run the query in the Query Analyzer. To my entire surprise, I was totally unable to do that with the Enterprise Manager or the Query Analyzer. The Query Analyzer would only give me an insert template whenever I right click on the table name and selected the insert statement.
I ended up creating a .dts file to import data from a previously generated .cvs file. On this package, the server name and credentials have to be edited before running in the final environment.

I then thought, well, wouldn’t it be a lot easier to just have the insert statements. Let’s take a look at MySQL and the most primitive manager it has, phpMyAdmin. I can generate a .sql file that will include the DDL for creating a table or not, and the data for populating that table as a group of inserts.

And save the file with a .sql extension:


It is true that MS SQL Server will let you copy objects among databases, it is true that there is a greater complexity of those objects and the data transformation that you can make with a DTS, but the point is, why they didn’t keep the simplest as well.

Rough day and conditional server side includes

My day began with a heavy rain. I don’t like driving in the rain, mostly because I need better windshield wipers. While I was driving to work a car hit me on the back. It was only a few scratches but that made me moody.
I got to work and the morning passed without major events, just coding and reviewing.
The whole team was invited to a lunch out for our good performance so we decided to go for Japanese food.
When I read the menu I saw that most of the plates said “Entrees”, except the Specials. Coming from a Latin culture, and read Latin as the Roman Empire official Language not as in Latin America, I thought, ok, entrees, that’s French and means entrance, or as in Spanish, entrante…so lets ask two and that’s it because I’m not too hungry. Oh well, in the Anglosaxon culture an Entree is a main course dish and the waitress kept going for an hour that I had ordered two entrees and I replied that yes, that I wasn’t too hungry…LOL

Anyways…my main problem today was a broken code.
I think I blogged before about conditional includes in classic ASP.
This morning I had to add some code for my part of the project in a common file that is shared among several sites.

The code looked like this:

<% Select myReport
Case “Report1”: %> <!–#include virtual=’Report1.asp’–>
<% Case “Lizis_Report” %> <!–#include virtual=’Lizis_Report.asp’ –>
<% End Select %>

It was an innocent extra case in a conditional statement. The thing is, conditional includes doesn’t work in ASP and I should have known better as I have read this article on 4GuysFromRolla

My innocent Lizis_Report.asp had functions with the same name and signature than the functions in Report1.asp so the original ones got overwritten. The reason: IIS processes SSI before it processes ASP code, so both files are included at the same time.

I came home decided to make a small test in PHP with Apache:
I created a mytest.php with the following content:

<?php if(false){ ?> <!–#include virtual=’file1.shtml’ –> <? } else{ ?> <!–#include virtual=’file2.shtml’ –> <? } ?>


After testing it the output to the browser is
<!–#include virtual=’file1.shtml’ –>

So I guess it works in Apache but IIS is kinda lazy…
I better go swimming for a while to burn out the two “Entrees” I ate today 😛

See you later!

ASP and ASP.NET

I’m currently working on branching an asp project, hopefully not for long. It took me some time to adapt myself back to its programming style, but I’m longing to go back to .NET.
This post is not about how to convince the stockholders than migrating a project saves money in the long run and allows branching a lot easier. It’s not about how adding branches to old hard to maintain code increases costs, it might give money right away when you sell that branch in a direct proportion, but increases maintainability costs in an exponential way. I don’t know how long it would take for you, humble programmer, to explain the difference between exponential and direct proportion.

As usual, I would like to summarize why I moved away from ASP 6 years ago, and why I look forward to move away from it today, the farther the better.

  1. Classic ASP is hard to debug and maintain. Probably because of its own programming model. The mixture of asp code with HTML in a single .ASP page, the lack of a well defined object oriented hierarchy et-cetera.
  2. Everything is interpreted script, in order to increase performance the best bet is to move part of the logic or functionality to COM components.
  3. COM components require the components to be registered on the server, what brings into account the well known DLL hell and adds deployment complexity. It also makes debugging more complex, you cannot debug locally unless you have the COM components registered on your machine. You have to have exact versions of the COM components in the development and production environments. This rules out shared web hosting.
  4. VBScript is not strong typed. Syntax errors are discovered most of the time when the call to your script shows a 500 http error. There is no way to discover any error at compilation time, because there is no compilation time :-p.
  5. In order to debug your script, you’re better off writing response.writes to the screen or taking guerrilla techniques.
    Definition of Guerrilla Technique: Select the whole content of your script, cut it and paste it in an open notepad windows. Type in a Response.Write (“I’m Here. I made it into MyScript.asp”) and request the page after saving it in your IIS box. Then start copying and pasting small chunks of the original code at a time till you no longer see the “I’m Here…” So you can determine the failing line of code.
  6. Classic ASP is not event driven programming, if you want event driven response, you better get a JavaScript book or bookmark a good online reference. It’s true that you should know JavaScript no matter what, some .NET programmers abuse the numbers of trips to the server that could be saved with some client side logic.
  7. In order to have a nice grid that you can re-use in your daily reports you have to write humongous amounts of code, even more if the grid has pagination or sorting capabilities.
  8. Option Explicit is off by default in classic ASP, oh no! (Note: it becomes Off by default since VS 2003 if I remember correct)

I’m sure some people will point out some advantages. I can hardly think of two of them:

  1. When you set the form action attribute in html to a certain script, it certainly requests that script on the server, it doesn’t go to the same original page that contents the form. Ok, ok, without removing the feature, it wouldn’t be possible a Page.IsPostback property in .NET. Have you ever tried that in .NET? I mean setting the action attribute, not the Page.IsPostback, dummy.
  2. Some coworkers have said the OnError type of error treatment is better than the Try Catch because it lets you Resume Next. To be honest, I’m quite fond to do proper Exception Handling so no thanks.