9

I'm having trouble connecting to an Oracle database from Powershell using the Oracle.ManagedDataAccess.dll.

I followed this tutorial on Technet and ended up with this code:

add-type -path "C:\oracle\product\12.1.0\client_1\ODP.NET\managed\common\Oracle.ManagedDataAccess.dll"
$username = "XXXX"
$password = "XXXX"
$data_source = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX)(PORT=XXXX))(CONNECT_DATA = (SERVER=dedicated)(SERVICE_NAME=XXXX)))"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"

try{
    $con = New-Object Oracle.ManagedDataAccess.Client.OracleConnection($connection_string)

    $con.Open()
} catch {
    Write-Error (“Can’t open connection: {0}`n{1}” -f `
        $con.ConnectionString, $_.Exception.ToString())
} finally{
    if ($con.State -eq ‘Open’) { $con.close() }
}

Unfortunately I'm getting this error:

C:\Users\XXXX\Desktop\oracle_test.ps1 : Can’t open connection: User Id=XXXX;Password=XXXX;Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=XXXX)(PORT=XXXX))(CONNECT_DATA = 
(SERVER=dedicated)(SERVICE_NAME=XXXX)))
System.Management.Automation.MethodInvocationException: Exception calling "Open" with "0" argument(s): "The type initializer for 'Oracle.ManagedDataAccess.Types.TimeStamp' threw an exception." ---> 
System.TypeInitializationException: The type initializer for 'Oracle.ManagedDataAccess.Types.TimeStamp' threw an exception. ---> System.Runtime.Serialization.SerializationException: Unable to find assembly 
'Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=XXXX'.
   at OracleInternal.Common.OracleTimeZone.GetInstance()
   at Oracle.ManagedDataAccess.Types.TimeStamp..cctor()
   --- End of inner exception stack trace ---
   at OracleInternal.ConnectionPool.PoolManager`3.CreateNewPR(Int32 reqCount, Boolean bForPoolPopulation, ConnectionString csWithDiffOrNewPwd, String instanceName)
   at OracleInternal.ConnectionPool.PoolManager`3.Get(ConnectionString csWithDiffOrNewPwd, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
   at OracleInternal.ConnectionPool.OraclePoolManager.Get(ConnectionString csWithNewPassword, Boolean bGetForApp, String affinityInstanceName, Boolean bForceMatch)
   at OracleInternal.ConnectionPool.OracleConnectionDispenser`3.Get(ConnectionString cs, PM conPM, ConnectionString pmCS, SecureString securedPassword, SecureString securedProxyPassword)
   at Oracle.ManagedDataAccess.Client.OracleConnection.Open()
   at CallSite.Target(Closure , CallSite , Object )
   --- End of inner exception stack trace ---
   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,oracle_test.ps1
  • I have checked, that the connection string is correct (it works for tnsping)
  • The Username and password are correct as well
  • I replaced anything that shouldn't be disclosed with XXXX
  • The database version is: Oracle Database 12c Release 12.1.0.1.0
  • The error is the same for the 32-Bit and 64-Bit Powershell instances
  • Before the first run the Oracle.ManagedDataAccess.dll isn't loaded, after the run it stays loaded until I close that shell

Unfortunately I'm neither an Oracle nor a Powershell Expert (I prefer MySQL and Python), therefore I would really appreciate any ideas and/or insights you might have.

7
  • Does this stackoverflow answer help? I don't believe it's an error with your code; probably the environment or a pre-requisite. Commented Jun 27, 2017 at 11:37
  • What is the version of your Oracle database? Commented Jun 27, 2017 at 11:47
  • 1
    @WernfriedDomscheit I added it to the list - 12c Release 12.1.0.1.0 @gms0ulman The mentioned gacutil doesn't seem to be installed on my system - I will investigate. Commented Jun 27, 2017 at 11:51
  • Error suggests it is a problem with the assembly. The connection string cannot even be questioned at this point. Are there any versions of this already loaded that might be in conflict? Are you running this from a32bit or 64bit shell? Have you tried the other? Commented Jun 27, 2017 at 12:12
  • @Matt I just tried the 32-Bit and 64-Bit Versions - the error apperas to be the same. How do I determine if other versions are loaded? I closed all powershell instances and reopened them - same behavior. Commented Jun 27, 2017 at 12:30

6 Answers 6

12

Im not sure if this is technically a solution - I'd classify it more as a workaround, but it worked for me.


After doing some more research I found a suitable alternative to the Oracle.ManagedDataAccess.dll. I found the System.Data.OracleClient class of the .Net Framework. (It requires an installed Oracle Client, which the machine fortunately has)

Here's an outline of the solution that worked for me:

add-type -AssemblyName System.Data.OracleClient

$username = "XXXX"
$password = "XXXX"
$data_source = "XXXX"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"

$statement = "select level, level + 1 as Test from dual CONNECT BY LEVEL <= 10"

try{
    $con = New-Object System.Data.OracleClient.OracleConnection($connection_string)

    $con.Open()

    $cmd = $con.CreateCommand()
    $cmd.CommandText = $statement

    $result = $cmd.ExecuteReader()
    # Do something with the results...

} catch {
    Write-Error (“Database Exception: {0}`n{1}” -f `
        $con.ConnectionString, $_.Exception.ToString())
} finally{
    if ($con.State -eq ‘Open’) { $con.close() }
}
Sign up to request clarification or add additional context in comments.

7 Comments

what is data source?
If I remember correctly that's the name you have configured in your TNSNAMES.ORA
I am pretty sure this Microsoft Oracle Client is a dead duck and even if it isn't, I would always favor the native Oracle client dlls for this.
@Allen Please provide a source for this claim and feel free to suggest an edit with a Caveat. If there is a better solution, please let me know - in this case I couldn't find a way solve my problem under the given constraints with the native DLLs. Should you find one, please leave it as an answer :-)
This Microsoft client is clearly no longer supported and should not be used IMHO. A search reveals: ...."This types in System.Data.OracleClient are deprecated and will be removed in a future version of the .NET Framework. For more information, see Oracle and ODP.NET..." Furthermore, the Microsoft ODBC driver is also deprecated, if you have the misfortune to need to use it, and it is my understanding that all the Microsoft drivers for Oracle are somehow joined at the hip to the System.Data.OracleClient - also, these are not managed code, I believe.
|
3

Use the server:port/service syntax.

$dataSource="server.network:1522/service1.x.y.z"

1 Comment

Yup! Oracle server and service has to be listening on 1522 which is a DBA thing.... The service entry here can be just a simple instance name like ORA1.....
1

Here is my (Powershell, but you can adapt to C#) code to do this with ODP.NET managed data access.... which I load directly using the Powershell Add-Type but in C# would be a using/reference...

  1. create a connection, using the connection builder class to ensure the resulting connection string is exactly as desired. Of course you can simplify but this is self-documenting:
function New - OracleConnection { <
  #
  .SYNOPSIS# generate a well - formed connection string with individual properties
  Create and open a new Oracle connection using optional connectionstring argument

    .DESCRIPTION
  Create and open a new Oracle connection using optional connectionstring argument

    .EXAMPLE
  New - OracleConnection
  New - OracleConnect - connectionString "My well-formed Oracle connections string"

    .NOTES
  Connection is opened here by
  default# > #Add - Type - Path ".\Oracle.ManagedDataAccess.dll" [OutputType([Oracle.ManagedDataAccess.Client.OracleConnection])]
  Param(
    [Parameter(Mandatory = $false)]
    [string] $theConnectionString, [Parameter(Mandatory = $false)]
    [string] $openOnCreate = "1"#
    means true - open the connection...
  )[Oracle.ManagedDataAccess.Client.OracleConnection] $con = New - Object - TypeName Oracle.ManagedDataAccess.Client.OracleConnection;
  if ([string]::IsNullOrEmpty($theConnectionString)) {#
    $dataSource = "*********:1521/******;"

    $conStringBuilder = New - Object Oracle.ManagedDataAccess.Client.OracleConnectionStringBuilder;
    $conStringBuilder["Data Source"] = $dataSource;
    $conStringBuilder["User ID"] = "*******";
    $conStringBuilder["Password"] = "*******";
    $conStringBuilder["Persist Security Info"] = $True;
    $conStringBuilder["Connection Lifetime"] = 180;
    $conStringBuilder["Connection Timeout"] = 10;
    $conStringBuilder["Pooling"] = $true;
    $conStringBuilder["Min Pool Size"] = 10;
    $conStringBuilder["Max Pool Size"] = 20;
    $conStringBuilder["Incr Pool Size"] = 5;
    $conStringBuilder["Decr Pool Size"] = 2;
    $conStringBuilder["Statement Cache Size"] = 200;
    $conStringBuilder["Statement Cache Purge"] = $false;#
    default

    $con.ConnectionString = $conStringBuilder.ConnectionString;
  } else {
    $con.ConnectionString = $theConnectionString;
  }

  if (Get - IsTrue - yesNoArg $openOnCreate) {
    if (-not(Get - ConnectionStateIsOpen($con))) {#
      attempt open, ignore error
      if already open.State is normally open after successful create
      try {
        $con.Open();
      } catch {
        $null;
      }
    }
  }

  Write - Output - NoEnumerate $con;

}
  1. get a connection:
$con = New - OracleConnection;
  1. open / close as necessary(it defaults to open...)

... ... if ($con.State - ne[System.Data.ConnectionState]::Open) { $con.Open();# no arguments that I know of ... }

  1. use it and then close/dispose...
    $sql = "SELECT * FROM YOUR_TABLE t WHERE t.SOMETHING = :the_parm";    
        [Oracle.ManagedDataAccess.Client.OracleCommand]$cmd = New-Object -TypeName Oracle.ManagedDataAccess.Client.OracleCommand;    
        $cmd.Connection = Get-OracleConnection;
        $cmd.CommandText = $sql;
        $cmd.BindByName = $true;
        $dbType = ([Oracle.ManagedDataAccess.Client.OracleDbType]::VarChar2);
       
        $cmd.Parameters.Add(( New-Param -name "the_parm" -type $dbType -size 15  )).Value = $the_criteria_value  ;
        Write-Output -NoEnumerate ($cmd.ExecuteScalar());
        $cmd.Connection.Close();
        $cmd.Dispose();
        

Comments

0

It could very well be an issue with oracle 12.2.x
I had to add the following lines to the sqlnet.ora file on the database server to allow connections from older oracle clients: SQLNET.ALLOWED_LOGON_VERSION_CLIENT=8 SQLNET.ALLOWED_LOGON_VERSION_SERVER=8

Once added I could login with oracle 10g and 11g clients

1 Comment

As I mentioned above, older clients have bitten me repeatedly, but I do understand that a corporate entity even of modest size must be somewhat conservative w/ workstation configurations and cannot update nimbly....
0

Probably irrelevant but this parameter: [string] $openOnCreate = "1"#

according to the PS goddesses, the recommended syntax should be: [switch] $OpenOnCreate ...

...where the presence of the switch means $True....

and the check should look like:

if ($OpenOnCreate) ...

so the call should look like this to just create a new connection (to be opened and used later) ... $con = New-OracleConnection

or, if opening the connection as part of the create, just include the [switch]

$con = New-OracleConnection -OpenOnCreate

All of which does not detract from the solution. I would also offer that the code creating the connection string inside this might be moved to a separate dedicated function?

Comments

-1

I had the exact same issue and I switched from ODAC version 12.2.0.1.0 to version 11.2.0.3 and it worked like a charm to Open connection and read data. Hope this helps. Thanks, SK

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.