Introduction
This is actually my first CodeProject article and my first attempt at writing C# code, so if I have made any mistakes along the way, please feel free to comment. I won't get offended ;)
The idea behind this article was prompted because I found only one article that deals with C# and Oracle on this site (which is unrelated to my needs), and I haven't been able to find any articles anywhere else on the internet regarding this specific topic and platform.
In order to properly use the information contained in this article, I am going to assume the following:
- You have at least a basic understanding of C# and have written code in it or some other language such as C++ or Java.
- You have a basic understanding of writing SQL commands.
- Have an Oracle database to connect to.
- If your database is at your place of work, a copy of tsanames.ora provided by the DB admin or whomever. (And hopefully, permission to access the database!)
So without any further introduction, let me get into a little background.
Background
There is an Oracle database at the company I work for that contains customer case information which I wanted to access in order to query information from. I had, in the past, created an MFC application and used Oracle Objects for OLE to connect to the database in order to run my queries. While this worked, it required an insane amount of files to be installed along with my application, as well as some Registry entries. I really hated having to distribute all the extra files and complications along with it, but had no choice at the time. To put it simply, it required about 590 files totaling in the area of 40MB. Not exactly what I had in mind, but the documentation I had on how to use it wasn't very clear. And, I don't think there's an article to date on CodeProject on how to properly use it and what the client requires to have installed on his/her machine. Perhaps, someone will take up the challenge.
In any case, now that I am gravitating towards using C#, I wanted to reattempt a few things I have done with Oracle, but leaving as little a footprint as possible on the client's computer. Just a few months prior to this article being written, I came across Oracle Instant Client (http://www.oracle.com/technology/tech/oci/instantclient/index.html). This seemed like just what I was looking for. I spent the next few days trying to figure out how to use it with MFC. I can't recall the exact amount of time, but I can say this, it was far easier to implement with C# than C++, at least in my opinion.
Oracle Instant Client uses OCI (Oracle call-level interface) for accessing Oracle databases.
What is the Oracle Call Interface?
The Oracle Call Interface (OCI) is an application programming interface (API) that allows applications written in C to interact with one or more Oracle servers. OCI gives your programs the capability to perform the full range of database operations that are possible with the Oracle9i database, including SQL statement processing and object manipulation.
What you need?
You will need to create a free account on Oracle's site (below) and agree to their terms to be able to download the client.
Download Oracle Instant Client for Microsoft Windows (32-bit) here. There are other platforms available, and a 64-bit version for Windows, but I haven't looked at the contents of any of those and they are outside the scope of this document anyhow.
There are two versions you can choose from. They are: Basic and Basic-Lite. I recommend getting the Basic Lite version, unless you need to support more than the English language.
OCCI requires only four dynamic link libraries to be loaded by the dynamic loader of the Operating System. When this article was written, it is using the 10.2 version.
They are as follows:
- OCI Instant Client Data Shared Library
- oraociicus10.dll (Basic-Lite version)
- oraociei10.dll (Basic version)
- Client Code Library
- Security Library
- OCCI Library
The main difference between the two Instant Client packages is the size of the OCI Instant Client Data Shared Library files. The Lite version is roughly 17MB, whereas the Basic version is almost 90MB since it contains more than just the English version.
Once you have these files, simply copy them into the same directory as your executable. You could possibly put them in another folder as long as your environmental variables are set to point to its path, but I found it easiest to do it this way. After all, it is only four files.
The only other required file you will need to have is tsanames.ora which is simply a text file that looks similar to this:
myserver.server.com = (DESCRIPTION = (ADDRESS = (PROTOCOL= TCP)
(Host= myserver.server.com)(Port= yourPort#))(CONNECT_DATA = (SID = yourSID)) )
This will be different for everyone, but I am posting the sample so you know what to expect in this file if you are new to this subject. Also, you can expect to find multiple entries in this file so don't be surprised if there is more than one set.
An alternative to including the tsanames.ora file is to include it within your connection string, as the following snippet demonstrates:
private static string CONNECTION_STRING =
"User Id=myUserID;Password=myPassword;Data Source=(DESCRIPTION=" +
"(ADDRESS=(PROTOCOL=TCP)(HOST=myserver.server.com)(PORT=yourPort#))" +
"(CONNECT_DATA=(SID=yourSID)));";
Connection string parameters
| Parameter Definition |
Description |
Example |
| Server or Data Source |
TNS name or network address of the Oracle instance to connect |
Server=TESTDB |
| User ID |
Name of the Oracle database user |
User ID=myUserID |
| Password |
Password for the Oracle database user |
Password=myPassword |
| Integrated Security |
To connect using external authentication or not. Valid values for Integrated Security are: YES or TRUE to use external authentication, NO or FALSE to not use external authentication. The default is false. |
Integrated Security=true |
| Min Pool Size |
Specifies the minimum number of connections in the connection pool. Default is 0. |
Min Pool Size=0 |
| Max Pool Size |
Specifies the maximum number of connections in the connection pool. Default is 100. |
Max Pool Size=100 |
| Pooling |
Specifies whether or not to use connection pooling. Valid values are TRUE or YES to use connection pooling, or FALSE or NOT to not use connection pooling. Default is TRUE. |
Pooling=true |
If you use Integrated Security, make sure you have a user created externally. Also, make sure you know what you are doing if you use external authentication - there are security implications. Read the Oracle Database Advanced Security Administrator's Guide for more info about external authentication.
Code example - Connecting to Oracle and running a simple query
Once you have the above, the rest is easy.
Create a new C# application. For this example, let's keep it simple and create it as a console application.
Be sure to include a reference to System.Data.OracleClient.dll, and place the following at the top of your code along with all the other using statements:
using System.Data.OracleClient;
This is a standard library provided by Microsoft. No voodoo witchcraft or additional Oracle library references are required. More information about this library can be found here.
The following section of code should be all you need to get yourself started. This is simply an exercise in connecting to the database and running a simple SELECT query to return some data. The purpose of this article is to establish a connection to Oracle, installing as little as possible on a user's machine. You won't be seeing anything more complicated than that. We can save the rest for another article.
We will start by creating two methods: static private string GetConnectionString() and static private void ConnectAndQuery(). I won't be going into any specific details regarding any of the code provided. There's plenty of documentation available to explain what can be done with System.Data.OracleClient, if you want more information.
static private string GetConnectionString()
{
return "Data Source=myserver.server.com;Persist Security Info=True;" +
"User ID=myUserID;Password=myPassword;Unicode=True";
}
static private void ConnectAndQuery()
{
string connectionString = GetConnectionString();
using (OracleConnection connection = new OracleConnection())
{
connection.ConnectionString = connectionString;
connection.Open();
Console.WriteLine("State: {0}", connection.State);
Console.WriteLine("ConnectionString: {0}",
connection.ConnectionString);
OracleCommand command = connection.CreateCommand();
string sql = "SELECT * FROM MYTABLE";
command.CommandText = sql;
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
string myField = (string)reader["MYFIELD"];
Console.WriteLine(myField);
}
}
}
I will assume you can make the necessary modifications to the connection string and your query. The code should otherwise be self-explanatory.
All that remains is a call to ConnectAndQuery() from Main.
Errors you may run into at runtime
Error: Unhandled Exception: System.Data.OracleClient.OracleException:
ORA-12154: TNS:could not resolve the connect identifier specified
Cause:
- Your connection string is invalid.
- Missing the tsanames.ora file.
Resolution:
- Fix the connection string making sure the server name and/or credentials are correct.
- Make sure the tsanames.ora file is present in the application path and contains valid data.
Error: Unhandled Exception: System.Exception:
OCIEnvNlsCreate failed with return code - 1 but error message
text was not available.
Cause:
- One or both of the required Oracle Instant Client DLLs are missing from the application's path.
- There is no 'PATH=' environmental variable set that points to these files should they not reside in the application's path.
Resolution:
- Copy the DLLs into the application's path or modify your PATH= to include the directory where these files reside.
Error: Unhandled Exception: System.Data.OracleClient.OracleException:
ORA-12705: Cannot access NLS data files or invalid environment specified
Cause:
- You have Oracle or Oracle development tools installed locally (or on the machine running the application).
Resolution:
- Check to see if [HKLM/Software/Oracle] exists. Chances are it does.
- Within the Oracle key, look to see if
NLS_LANG exists.
- If it does, do one of the following: rename to NLS_LANG.OLD, or delete it entirely. Providing a valid language such as AMERICAN_AMERICA.WE8MSWIN1252 would also resolve the issue. Single-byte character sets include
US7ASCII, WE8DEC, WE8MSWIN1252, and WE8ISO8859P1. Unicode character sets include UTF8, AL16UTF16, and AL32UTF8.
Performance issues
I used both Oracle Developer Tools for Visual Studio .NET and Oracle Instant Client to experiment with. I did not noticeably see any performance differences during these tests although there may be some depending on what you are trying to do. For my purposes, there would be little gained by using the developer tools since it requires a more complex install and no noticeable performance gain. If anyone has any experiences they can share, please do.
Conclusion
I hope this will help someone who needs to establish a connection to Oracle with their application and wishes to distribute it without any complicated client installs and with only a small footprint on the client's machine. Please feel free to leave comments and/or questions. If you have anything negative to say, please leave an explanation why. Otherwise, no one will learn from it.
| You must Sign In to use this message board. |
|
|
 |
 | thanks  Member 4725117 | 1:20 27 Oct '09 |
|
 |
I'm searching this topic many times in past but I didn't get any post until your post. So great 
it's work well in almost version of Oracle 9i,10g,11g etc...
thanks thanks thanks
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You article rocks!
Thanks for sharing such a remarkable information.
Is there a way to connect oracle database remotley I mean through web service? if it is a web service then what exactly I instruct web service to do?
I want to inetract with oracle database through client machine? Installing oracle client i.e ODp.net or OCI is hectic. I have more than 200 clients and they wanted to interact with one database.
I will highly appreciate if you propse me any solution!
Thanks in advance.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
 | Thanks  Pablo Grisafi | 7:03 9 Dec '08 |
|
 |
Excelent article, I love the non-tsnames.ora way of making connections. Im using it with version 11 of OCI, works just fine However, oraociei11.dll is a really large file: 104 MB No one to blame here, but oracle.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Maybe I'm missing something. I have my exe, 4 Dlls, tnsnames.ora all in the same directory. When I run my .exe, I receive: "System.Data.OracleClient requires Oracle client software version 8.1.7 or greater". I'm attempting to connect to Oracle 10g. Everything works on my development system, but I also have the Oracle 10g client software installed. The error is from a virgin PC with no Oracle software on it. Hints? 
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Same thing here... Works fine when I'm in VS but when I try to browse the website on the server I got the "client must be install" message. MAybe it's because i'm using the "file system" to develop the website?
Let me know, have a nice day!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Alright, I think I got it... Instead of using the bin directory, I just copied it somewhere on the server ("E:\ORACLE\instantclient_11_1") and change the "PATH" variable to include it... After restating IIS, all was good! I did have to forget about using the tnsnames.ora file... just adjust the connection string instead. I'm pretty that the other solution with the c:\WINDOWS\server32 would have worked fine... They are just a bit touchy on that folder here I work 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thing is, the article says the DLLs should be in the same directory as the exe. I have done that. I have even put the path to this directory in my PATH environment. 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Did you figure this out? I have the same problem. I get the same error whether I place the files in the same folder as the .exe or in the windows\system32 folder.I have the same problem. I get the same error whether I place the files in the same folder as the .exe or in the windows\system32 folder. This is while trying to test the sample code from visual studio.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Nevermind. After I displayed the bin folder in the solution explorer and chose "Include in Project" for each of the files, it worked.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You need this solution if you have more than one application, instead of copying the dll files in each one do the following:- - Copy the 4 dll files + ociw32.dll to: WINDOWS\system32 directory - Create the folder: WINDOWS\system32\network\admin and locate the tnsnames.ora inside that folder Now you don't need to copy the dll files to each application directory. In addition, if your application has a crystal report it will run. Thank you all 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,
This is great and I am excited to use it. However I have a few questions. I downloaded the zip file and included the 4 files you specified and already included the TNS information in the connection string prior to this (which for some reason required that there be a TNSNAMES.ORA file on the machine which I have not figured out yet but that is another topic for another day).
First, I was wondering if you know how I can test it on a machine that already has Oracle installed.
Second, I guess I don't understand how the application knows that the files are there just by copying them into the project directory. Do I have to link to them through the "references" dialog?
Thanks Patrick
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi Patrick,
I'll try to answer your questions as easy to understand as possible... if not let me know if you need further clarification.
patrickst1 wrote: First, I was wondering if you know how I can test it on a machine that already has Oracle installed.
It doesn't really matter where Oracle is installed. As long as your connection string/tnsnames.ora specifies the location as the server you are also testing from as the same computer, it will know where to look. Much like mailing yourself a letter. The post office doesn't care what the address is as long as it knows where it'll end up. If your program isn't connecting, chances are you are getting once of the errors covered in the article and you'll need to correct the connection string and/or the tsanames.ora file (you don't really need this if you build it into your connection string as shown in the article)
patrickst1 wrote: Second, I guess I don't understand how the application knows that the files are there just by copying them into the project directory. Do I have to link to them through the "references" dialog?
You don't need to do anything, this is just how the operating system works. Basically if your application needs a DLL, it will typically begin by looking in the same path as that the program resides in. If it wasn't found it will go look in the windows system folders and if it hasn't been found there it may even look in all the folders that are set up in the OS's 'Path' (run a command window and type PATH at the prompt to see all the places your computer will check for files).
Hope that helped clear things up.
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Thanks, that helps a lot, especially #2.
It is interesting about the TNSNAMES.ORA though, I have the exact information in the connection string as is in my TNSNAMES.ORA file, but when the app was installed on a computer with oracle installed but not the ora file then it would not connect to the server, once the ora file was there then it would connect. Here is an example, maybe I am doing something wrong, can you take a look?
The username and password placement shouldn't matter should it? What about the white space?
string serverConnStr = "Data Source=(DESCRIPTION=(ADDRESS_LIST=" + "(ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1234))" + "(ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1235))" + "(LOAD_BALANCE = yes))(SDU = 54321)(CONNECT_DATA =(SERVICE_NAME = xxxx1234.corp.company.com)));" + "User Id=username1;Password=password2;";
xxx1234.corp.company.com = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1234)) (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1235)) (LOAD_BALANCE = yes)) (SDU = 54321) (CONNECT_DATA = (SERVICE_NAME = xxx1234.corp.company.com) (INSTANCE_NAME = xxxx1234) ) )
Thanks again for your help and this article, now that I have the dll files and once I get this figured out then I think I will be set. Patrick
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
patrickst1 wrote: xxx1234.corp.company.com = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1234)) (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1235)) (LOAD_BALANCE = yes)) (SDU = 54321) (CONNECT_DATA = (SERVICE_NAME = xxx1234.corp.company.com) (INSTANCE_NAME = xxxx1234)
I take it that is your working tnsnames.ora file contents?
Try this connection string: (And instead of using string = "text1" + "text2" + "more text"; you can use an @ symbol before the beginning quote so you can spread the text over several lines w/o having to add it all together. And you won't need to worry about white space.)
private static string CONNECTION_STRING = @"User Id=myUserID;Password=myPassword; Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1234)) (ADDRESS = (PROTOCOL = TCP)(HOST = xxxx1234.corp.company.com)(PORT = 1235)) (LOAD_BALANCE = yes))(SDU = 54321) (CONNECT_DATA = (SERVICE_NAME = xxx1234.corp.company.com) (INSTANCE_NAME = xxxx1234)));";
The only differences from yours is I placed the username/password first, and I used @ to make my string instead of adding various text strings together. Also I defined it as a static string.
Given you've followed the steps in the article & made the connection string properly, this should work. If it doesn't you should get some sort of error like the ones mentioned in the article which I would need for analysis to determine why it's not working.
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
 |
Hi,
Well I got it to work, for some reason my instance_name was throwing an error but after removing it and trying again it worked. Thank you, I really appreciate all your help!
Patrick
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
It is fantastic; I can connect to oracle without installing anything Is there any similar solution to do the same thing with crystal reports? Because I have an application developed by C#.net with oracle 8i installed on the server, however my PC dose not have any oracle installed but use the above mentioned dll files the application can connect to oracle server perfectly but the problem is that the application have a crystal reports which unable to connect to oracle server. Please help
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
You could still use this article to build your client application. That's what it's meant for actually. In your case, the only difference is that your computer would also need to have Oracle installed on it so that you have a database to attach to. You'd then point to that 'server' in the connection string or tsanames.ora file (however you choose to do it) as shown in the article.
Paul
|
| Sign In·View Thread·PermaLink | 5.00/5 |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
Your solution is no different than that of which my article presents. In beginning of your blog you say you don't need any files, yet in the very next paragraph you specify you need to grab a few files from Oracle (how's that different from this article?) and you don't need a tnsnames.ora file. That's already been covered in the comments section by incorporating that into the connection string.
At the very least I would say it's an exact copy of my work. The word plagiarism comes to mind....
modified on Monday, June 16, 2008 2:11 PM
|
| Sign In·View Thread·PermaLink | 3.67/5 |
|
|
|
 |
|
 |
This is EXACTLY like this article. You quote in your blog: "the difference with the method described below is that no oracle client installation or tsanames.ora is needed." That is the basis of this article. I suggest you go back and take another look!
If you took out the 'Oracle Bits' section, your article would not even work! The remaining bits of the article showing your code, while coded differently achieve the same results. Six in one hand, half a dozen in the other. The results are the same!
Give full credit where FULL credit is due. Your article is nothing more than a cheap knock off.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|