I have a VC# application that tries to open an Oracle database, but when it calls OracleConnection.Open(), it throws, "Attempted to read or write protected memory."
Here is the stack trace of the error:
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at Oracle.DataAccess.Client.OpsCon.Open1(IntPtr& opsConCtx, IntPtr& opsErrCtx, OpoConValCtx* pOpoConValCtx, OpoConRefCtx& pOpoConRefCtx)
at Oracle.DataAccess.Client.OpsCon.Open(IntPtr& opsConCtx, IntPtr& opsErrCtx, OpoConValCtx* pOpoConValCtx, OpoConRefCtx& pOpoConRefCtx)
at Oracle.DataAccess.Client.ConnectionDispenser.CreateConnectionPool(OpoConCtx& opoConCtx)
at Oracle.DataAccess.Client.ConnectionDispenser.GetConnectionPool(OpoConCtx& opoConCtx, Boolean& bConObtained)
at Oracle.DataAccess.Client.ConnectionDispenser.Open(OpoConCtx opoConCtx, Int32 enlistAttrVal, Boolean& bGotEnlistedConnection)
at Oracle.DataAccess.Client.OracleConnectionOCP.Open(OracleConnection con)
at Oracle.DataAccess.Client.OracleConnection.Open()
at GenericOracleLogin.frmMain.btnLogin_Click(Object sender, EventArgs e)
in C:\VS\Workspaces\Visual Studio 2017\Projects\GenericOracleLogin\GenericOracleLogin\Form1.cs:line 56
Here is the relevant portion of the C# code:
OracleConnectionStringBuilder ConnString = new OracleConnectionStringBuilder();
ConnString.DataSource = txtDataSource.Text;
ConnString.UserID = txtUsername.Text;
ConnString.Password = txtPassword.Text;
String ConnectionString = ConnString.ToString();
Conn = new OracleConnection(ConnectionString);
Conn.Open();
The exception is thrown at Conn.Open()
I am using Oracle.DataAccess version 4.122.1.0; it is a 64-bit version running on a 64-bit app
Two things to note:
First, this is being done after Oracle was uninstalled and then reinstalled into a different directory. I can't find any references to "oracle.dataaccess" in any of the GAC directories. I also don't see any BindingRedirects in any readable machine.config files.
Second, when I use Oracle.ManagedDataAccess in place of Oracle.DataAccess, the code works.
I assume that the problem is, it is not using the specific version of Oracle.DataAccess.dll that I want it to use. How do I fix this?
I discovered that, while my main Oracle odp.net directory had Oracle.DataAccess.dll version 4.122.1.20161216, which is what I was using, my Oracle Data Toold odp.net directory had version 4.122.1.20170524. When I used the newer version, the app ran successfully.
Related
I download the Oracle client was downloaded from https://www.oracle.com/database/technologies/oracle19c-windows-downloads.html and select the file "NT_193000_client.zip" under the heading "Oracle Database 19c Client (19.3) for Microsoft Windows (32-bit)".
I then installed it on my server. When I run a TNSPing command to check the version number and bit-ness of the Oracle Client installed, I get:
TNS Ping Utility for 32-bit Windows: Version 19.0.0.0.0 - Production on 20-OCT-2022 22:50:49
I then used SQLPlus to verify that I could connect to the database.
Next, I compiled the following simple C# program that tests Oracle connectivity. The program was compiled as a 32-bit .NET 6 program.
using System;
namespace TestOracle
{
internal class Program
{
static void Main(string[] args)
{
string cs = "Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=servernm.sys.myco.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=MySERVICE.MYCO.com)));User Id=MYID;Password=MYPWD;Validate Connection=True;";
try
{
int count = Db.TestConnectivity(cs);
Console.WriteLine($"Count={count}");
}
catch (Exception e)
{
Console.WriteLine(e);
}
var key = Console.ReadKey();
}
}
}
using Oracle.DataAccess.Client;
using System;
using System.Data;
using System.Text;
namespace TestOracle
{
public static class Db
{
public static int TestConnectivity(string connectionString)
{
var sqlStringBuilder = new StringBuilder();
sqlStringBuilder.AppendLine($"SELECT 1 AS RecordCount FROM DUAL");
using (OracleConnection connection = new OracleConnection(connectionString))
{
connection.Open();
OracleCommand command = connection.CreateCommand();
command.Connection = connection;
var oleDbDataAdapter = new OracleDataAdapter(command);
command.CommandText = sqlStringBuilder.ToString();
DataSet dataset = new DataSet();
oleDbDataAdapter.Fill(dataset);
return Convert.ToInt32(dataset.Tables[0].Rows[0]["RecordCount"]);
}
}
}
}
When I ran the program, I get this error:
System.IO.FileNotFoundException: Could not load file or assembly 'Oracle.DataAccess, Version=2.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342' or one of its dependencies. The system cannot find the file specified.
File name: 'Oracle.DataAccess, Version=2.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342'
at TestOracle.Db.TestConnectivity(String connectionString)
at TestOracle.Program.Main(String[] args) in C:\Users\C39293\OneDrive - CIGNA\Documents\Visual Studio 2015\Projects\Dokmanovich.File2Table\TestOracle\Program.cs:line 13
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
I know that this is a common error and that the common issue is a mismatch of bitness or a version problem. In my case, the bitness of my program, 32, matches the bitness of the client installed. Furthermore, I expect that if the program runs on my machine with an Oracle client of 12.1, that a higher level client, 19, should also work. Is this assumption true? I was unable to find the exact same oracle Client.
What am I missing?
Update
When I looked in my C# project References, I saw that the Oracle.DataAccess.dll pointed to my 64 Oracle client folder on my machine, not my 32 bit one ( I have both clients). Since I want to run on a server that only has the 32 bit Oracle client, I changed the reference to point to the 32 bit dll and re-compiled it as before, as a 32 bit program.
When I reran the program on the server, I got a different error:
System.TypeInitializationException: The type initializer for 'Oracle.DataAccess.Client.OracleConnection' threw an exception. ---> Oracle.DataAccess.Client.OracleException: The provider is not compatible with the version of Oracle client
at Oracle.DataAccess.Client.OracleInit.Initialize()
at Oracle.DataAccess.Client.OracleConnection..cctor()
--- End of inner exception stack trace ---
at Oracle.DataAccess.Client.OracleConnection..ctor(String connectionString)
at TestOracle.Db.TestConnectivity(String connectionString) in C:\Users\Myid\OneDrive - CIGNA\Documents\Visual Studio 2015\Projects\MyName.File2Table\TestOracle\Db.cs:line 15
at TestOracle.Program.Main(String[] args) in C:\Users\MyId\OneDrive - CIGNA\Documents\Visual Studio 2015\Projects\MyName.File2Table\TestOracle\Program.cs:line 13
I guess this is suggesting that I have the wrong Client. What should I have installed so this code runs on the server?
Update 2
I had two version of the 32 Oracle.DataAccess.dll, version 2.121.20 and 4.121.2.0. The error was the same for both (the error message immediately above).
You may consider to use the Oracle Data Provider for .NET, Managed Driver (ODP.NET Managed Driver), then you have to copy only the Oracle.ManagedDataAccess.dll file without any further dependencies. It works for both, 32bit and 64bit.
Apart from 32/64 bit you need to consider a few more things.
If you like to use Oracle.DataAccess Version=2.xxx, then you must compile to .NET Framework 2.0. If you compile to .NET Framework 4.0 or higher, then the application will try to load Oracle.DataAccess Version=4.xxx (unless you load assemblies manually with Assembly.Load())
The version of Oracle.DataAccess has to match exactly the version of the Oracle client. Using version 2.121.x or 4.121.x with a Oracle 19 client does not work.
Assemblies (i.e. *.dll files) are loaded either from GAC or from folder of the application .exe. Well, in reality it is more complex (see How the Runtime Locates Assemblies), but let's keep it simple.
The DLL files from GAC take always precedence over the local files. However, in 12.1 and later ODP.NET is not added to GAC anymore by the installer. You need to add them manually, for example with the gacutil tool.
Looks like on your machine you had a 64-bit Oracle client installed. If you like to use 32-bit and 64-bit client on the same machine, follow this instruction: BadImageFormatException. This will occur when running in 64 bit mode with the 32 bit Oracle client components installed
You may also have a look at my Oracle Connection Tester, it should give you a hint where the problem is.
I am under pressure on this one so any help would be great. This seems a long question buts its not.. I have just included as much info as possible.. rgds M
I have an Web Application with a Webservice installed on 3 environments (Dev, UAT and Prod) The system calls the web service from an SSIS package on SQL 2008 and it hits the method no Problem on the web service on all environments. I then try and open an oracle connection within the method like in the simple code below using the Oracle Assembly : Oracle.DataAccess.Client;
Hers is Sample Code :
// Create and open a connection.
OracleConnection mConnection = new OracleConnection(sCnx);
mConnection.Open(); -- Fails at this call.
The Exception Message and number are blank as per this similar issue - Oracle.DataAccess.Client.OracleException at Connection.Open()
However I have checked the Pass through setting and its set to true on all environments.
This is my connection string
<add name="cnx" connectionString="DATA SOURCE=MYHUP1.US.COM;PASSWORD=456336;PERSIST SECURITY INFO=True;USER ID=MYAPPUSER" providerName="Oracle.DataAccess.Client"/>
This is the version of the DLL that I use below. All Dlls are built and deployed with my application and in a bin folder. I have also checked that the Oracle.DataAccess.dll gets loaded from the BIN folder and not the GAC or from the Oracle 11 (64 Bit) install on the server.
Oracle.DataAccess.dll
Version 2.112.3.0
32 Bit
These are also included in the bin oci.dll, ociw32.dll, orannzsbb11.dll, oraocci11.dll, OraOps11w.dll
My application runs on a 64 bit machine but is a 32 bit app and I have this set on the App pool. Again it runs fine On DEV but not Prod. It also runs under the same service account on all 3 environments.
The thing that hammers me is the error message is blank and I have had to put loads of code in to check loaded modules and the groups that the service is running under. These all look fine.
Error Message from the Exception: Note the Message is blank.. this is the info when that I get when I pump everything out
Oracle.DataAccess.Client.OracleException at
Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32
errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx*
pOpoSqlValCtx, Object src, String procedure, Boolean bCheck) at
Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode,
OracleConnection conn, IntPtr opsErrCtx, Object src) at
Oracle.DataAccess.Client.OracleConnection.Open() at
XXX.Business.XXXBO.TestConnectionAndDeleteData(Nullable`1 updateDate,
Int64 currentUserID) in C:\Development\XXX........
On my Dev and Prod Environment I have the following Version of Oracle installed but I am using my own Drivers in the Bin Directory as mentioned above so I didn't think this would matter..
DEV = Oracle Provider version 11.2.0.1.0
PROD = Oracle Provider Version 11.1.0.6.20
Would anyone have any ideas as to why this wont work on my Prod Environment. I have been over IIS with a fine comb and compared to the other environments and they are the same. Just trying to track this down to an IIS issue, or Oracle. Please note that I don't have access myself to the UAT environment which also does help!!
best regards Mick
this is what you will need to do to correct it .
Install the 32bit client along side the 64bit one.. The 64bit version does not work in regards to using standard connection string.. not sure how Oracle can let this bug go on for so long without fixing it.. installing side by side is what we did.. it will install into it's own folder so you should have no issues.. when you consume the .dll just set the copy to local = true and remove the old and re add the new .dll.. make sure you use navigate to the 4.x folder not the 2.x folder.
The 'Microsoft.ACE.OLEDB.12.0' provider is not registered on the local machine.
I know the common fix for this which is to install:
Microsoft Access Database Engine 2010 Redistributable
Or
2007 Office System Driver: Data Connectivity Components
Both are installed on my local PC. This is the code which I have
OleDbConnection conn = new OleDbConnection();
string fileName = "test.xlsx";
try
{
string connectString = String.Format(
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 12.0 Xml;HDR={1};'",
fileName, "YES");
conn.ConnectionString = connectString;
conn.Open(); //exception is thrown here !!!
OleDbCommand comm = new OleDbCommand();
comm.CommandText =
string.Format("CREATE TABLE [{0}] ", "Test");
comm.Connection = conn;
comm.ExecuteNonQuery();
OleDbDataAdapter ad = new OleDbDataAdapter(
string.Format("SELECT * FROM [{0}]", "Test"), conn);
OleDbCommandBuilder builder = new OleDbCommandBuilder(ad);
}
catch(Exception ex)
{
throw ex;
}
finally
{
conn.Close();
}
I try this code in other projects on my local machine and everything is working. I have project which creates excel exports and I don't have this problem.
The problem is in the project I don't understand how to fix it. Also on the current project I create one new .aspx page and in Page_Load put only this code, same exception.
Additional information: this project was written on vs 2008, convert to 2010 and after that used in vs 2012. Everything was working in the project till now.
Also same thing for JET connection string !
EDIT
After the answer of Joe I see that this project is run on 64bitProcess:
bool test = Environment.Is64BitProcess; //return true.
My driver is for 32bit. What I can do now, can I change the environment process. I can't install the driver for 64bit process because I have installed Office 2010 x32.
The OLEDB drivers for 32-bit and 64-bit applications are different.
If you only have the 32-bit driver installed, then 64-bit applications that attempt to use it will get this error. Similarly, if you have only the 64-bit version installed, then 32-bit applications that attempt to use it will get this error.
You say:
I try this code in other projects on my local machine and everything is working
Ergo, at least one of the two must be correctly installed.
To understand what's happening you could examine Environment.Is64BitProcess in both the application that works, and the one that doesn't. That will tell you which version is missing.
Then download and install the 32-bit or 64-bit version that's missing from:
http://www.microsoft.com/en-us/download/details.aspx?id=13255
You need AccessDatabaseEngine.exe (32-bit) or AccessDatabaseEngine_64.exe (64-bit)
Note that you may need to specify the provider as 'Microsoft.ACE.OLEDB.14.0' for the Office 2010 version (12.0 was for Office 2007).
After some hours I found a solution:
What were the steps, first I try to run the project on x86 - Properties/Build/Platform Target. Exception was thrown that I can't rebuild, because a registry was false. I create the registry. How to do it:
In notepad file paste this code and save it like reg file. Make the file name something to remember why you have it in the future(Fusion.reg).
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion]
"EnableLog"=dword:00000001
After that I had a problem because not all of my assemblies was readable by the application pool. Solution about that was going to IIS/Application Pools/Application Pool 4.0/General/Enable 32- Bit Applications. After that restart the IIS, close the project and open it again and everything was working with 32bit version.
Recently I moved some of my winform app data to SQLite. The app runs fine on all windows machines but Parallels on mac I am getting unable to open database file error. I can create the db file without any issues. But as soon as I check table exists I get the above error.
This file creation step works fine
SQLiteConnection.CreateFile(dbFile);
But new connection step is failing.
SQLiteConnection dbConnection = new SQLiteConnection("Data Source=mydb.db3;Version=3;");
Error Stack
System.Data.SQLite.SQLiteException: unable to open database file
at System.Data.SQLite.SQLite3.Open(String strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, Int32 maxPoolSize, Boolean usePool)
at System.Data.SQLite.SQLiteConnection.Open()
at App.clsSQLiteDB.CheckTableExists(String table)
I managed to solve the problem. Have to set the ParseViaFramework parameter true in the connection string.
SQLiteConnection dbConnection = new SQLiteConnection("Data Source=mydb.db3;Version=3;", true);
I'm trying to connect to my Oracle Database from my new PC. I've just installed Visual Studio and the ODAC. But when I try to do a simple connect Im getting an exception with an empty message, empty source, empty number, just with the error code which is -2147467259.
OracleConnection Prueba;
Prueba = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=XXX.XXX.XXX.XXX)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=XXXX)));User Id=XXX;Password=XXX;Pooling=true;Max Pool Size=10;Min Pool Size=1");
Prueba.Open();
Exception Details
This is the Exception.ToString() code:
"Oracle.DataAccess.Client.OracleException at
Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32
errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx*
pOpoSqlValCtx, Object src, String procedure)
at
Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode,
OracleConnection conn, IntPtr opsErrCtx, Object src)
at
Oracle.DataAccess.Client.OracleConnection.Open()
at
OracleConnectionS.Program.Main(String[] args) in
C:\Users\Simetri\Documents\Visual Studio
2010\Projects\OracleConnection\OracleConnection\Program.cs:line
19"
Any idea about why could this be happening?
UPDATE
If I run visual studio as Administrator I dont get the exception and I can connect to the database just fine.
I tried giving FULL CONTROL permission to the Oracle Directory C:\Oracle. But if I run Visual Studio in a normal way (not as administrator) I keep getting the exception.
Background Info
- I'm using Windows 7 64 bit
- Visual Studio 2010
- I can connect just find with SQL*PLUS
So after installing all sort of versions of ODAC and searching to every single post related to this.
At the end Clean Install of the 32bit version was the solution.
First you need to unistall all your other oracle client you have ever installed.
After that, look for any ODAC version you want (latest if posible) but be sure to download the 32 bit version.
WHY?
Well is something related to the version in which Visual Studio is developed in. If you are developing a console application you will have not problem with the client version, but if you are using a web project then you definitely need the 32 bit version.
Finally be sure that all of your projects in visual studio the target platform is "32 bit"
and reference the new Oracle.DataAccess.dll that you have just installed
Please try re-formatting your connection string into this form and see how it works
<add name="LoisDataAccess" connectionString="Data Source=LOISPRD;Persist Security Info=True;User ID=ABC;Password=DEF" providerName="System.Data.OracleClient" />
If the client you are using is an "Instant Client" then you might be better off by copying some Oracle-DLLs into your solution - for a walktrhough see this.
IF possible I would recommend to use a different .NET provider... in my experience most commercial ones are much less problematic than the Oracle .NET provider - see here on SO.