我正在尝试使用Powershell和Oracle.ManagedDatabaseAccess.dll连接到现有的oracle数据库。我使用相同的库在C#中运行代码。 该程序集已加载,但我无法使用。
我正在使用Win10和Powershell ISE。 我也使用VS2017 / 15.3.2和.Net 4.7.02046。
我尝试使用根本不起作用的“ Add-Type -AssemblyName”和“ Add-Type -Path”。这两个选项都立即显示错误。
我可以打电话
[Reflection.Assembly]::LoadFile("myrootpath\.nuget\packages\oracle.manageddataaccess.core\2.18.5\lib\netstandard2.0\Oracle.ManagedDataAccess.dll")
但是我得到了
GAC Version Location
--- ------- --------
False v4.0.30319 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Oracle.ManagedDataAccess\v4.0_2.0.18.3__89b483f429c47342\Oracle.ManagedDataAccess.dll
我使用gcautil将程序集手动添加到了GAC。 现在我得到了
GAC Version Location
--- ------- --------
True v4.0.30319 C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Oracle.ManagedDataAccess\v4.0_2.0.18.3__89b483f429c47342\Oracle.ManagedDataAccess.dll
现在我打电话给
$command = New-Object Oracle.DataAccess.Client.OracleCommand($sql,$conn)
我收到以下错误:
New-Object : The Type [Oracle.ManagedDataAccess.Client.OracleConnection] cannot be found. Make sure that you load the Assembly that contains this Type.
In Line:2 Character:8
+ $conn= New-Object Oracle.ManagedDataAccess.Client.OracleConnection($c ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
我了解了有关编译小型C#控制台应用程序(自可行)并从powershell调用该解决方案的解决方案。这可能是可行的,但是我真的很想了解这里的问题。 任何帮助将不胜感激。
PS H:\> Add-Type -Path "C:\mypath\Oracle.ManagedDataAccess.dll"
Add-Type : At least one type in the assembly could not be loaded.
+ CategoryInfo : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException
+ FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeCommand
PS H:\> $error[0].Exception.LoaderExceptions[0]
The type "System.IO.Stream" in the assembly "netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" could not be loaded.
Netstandard2.0.0.0是Oracle.ManagedDataAccess.dll的要求,该文件也必须安装在我的VS项目中。
System.IO.Stream应该在PS中可用而无需加载。可能是版本冲突,因为我的主要开发环境是.Net 4.7.02046?
答案 0 :(得分:1)
首先,您需要确保所使用的NuGet程序集版本与所使用的PowerShell版本兼容。您提到您是在Windows 10上的PowerShell ISE中编写代码。由于PowerShell ISE不支持PowerShell Core,并且Windows 10 Anniversary包含5.1 out of the box,因此我假设您在Windows PowerShell中编写代码,而不是较新的PowerShell Core。
这很重要,因为在Windows PowerShell 5.1之前,PowerShell基于.NET Framework,而在使用PowerShell Core的情况下,Microsoft切换到了多平台.NET Core。而且, Oracle为每个发布了不同版本的Oracle数据提供程序。
在使用.NET Framework(Windows PowerShell 5.1及更低版本)时,请使用Oracle.ManagedDataAccess
使用.NET Core(PowerShell Core 6及更高版本)时,请使用Oracle.ManagedDataAccess.Core
第二,您需要将程序集导入到当前会话中。尽管这听起来很容易,但是Oracle有一个绝妙的主意,即对于托管和非托管版本的Core版本和非Core版本都使用相同的程序集名称,因此您将希望使用完整的程序集路径来实现。否则,您可能会不可靠地导入不兼容的版本。
幸运的是,您可以结合使用找到程序集和下载程序集(如果缺少该程序集)到快速操作中,而仅使用在用户空间中运行的本机PowerShell命令进行操作。
Get-Package
检查ODP.NET是否已安装并获取其位置。ObjectNotFound
异常,请使用Install-Package
从NuGet.org下载ODP.NET。ObjectNotFound
异常,则将NuGet.org安装为不受信任的PackageProvider。Add-Type
和程序集路径显式导入新安装的程序集。然后可以按预期在PowerShell中使用ODP.NET。
#Requires -PSEdition Desktop
try { $nugetPkg = (Get-Package Oracle.ManagedDataAccess.Core -ProviderName NuGet -MinimumVersion "2.18.3" -ErrorAction Stop -Debug:$false).Source }
catch [System.Exception] {
if($_.CategoryInfo.Category -eq "ObjectNotFound") {
# Register NuGet.org as a package source if it is missing.
try { Get-PackageSource -Name "nuget.org" -ProviderName NuGet -Debug:$false -ErrorAction Stop }
catch [System.Exception] {
if($_.CategoryInfo.Category -eq "ObjectNotFound") {
Register-PackageSource -Name "nuget.org" -Location "https://www.nuget.org/api/v2/" -ProviderName NuGet -Debug:$false
}
else { throw $_ }
}
# Install Oracle drivers.
$pkg = (Install-Package Oracle.ManagedDataAccess.Core -ProviderName NuGet -MinimumVersion "2.18.3" -Verbose -Scope CurrentUser -Force -Debug:$false).Payload.Directories[0]
$nugetPkg = Join-Path -Path $pkg.Location -ChildPath $pkg.Name
Remove-Variable pkg
}
else { throw $_ }
}
# Add ODP.NET to the assemblies available in-session. Using the path instead of AssemblyName avoids conflicts with ODP.NET (Core).
# See https://docs.oracle.com/en/database/oracle/oracle-data-access-components/18.3/odpnt/index.html for documentation.
Add-Type -Path (Get-ChildItem (Split-Path ($nugetPkg) -Parent) -Filter "Oracle.ManagedDataAccess.dll" -Recurse -File)[0].FullName
# Begin Query Operations
try {
# TESTB connection string. You can replace the Data Source value with a tnsnames alias.
$con = New-Object Oracle.ManagedDataAccess.Client.OracleConnection(
"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=testb)(PORT=1521)) (CONNECT_DATA=(SERVICE_NAME=testb))); User Id=test;Password=user;"
)
$con.Open()
Write-Host ("Connected to database: {0} – running on host: {1} – Servicename: {2} – Serverversion: {3}" -f $con.DatabaseName, $con.HostName, $con.ServiceName, $con.ServerVersion) -ForegroundColor Cyan -BackgroundColor Black
# Get a single value
Write-Host "Returning a Scalar Value from Oracle" -ForegroundColor Cyan -BackgroundColor Black
$cmd = $con.CreateCommand()
$cmd.CommandText = "SELECT 'Hello World!' FROM DUAL"
$cmd.ExecuteScalar()
# Get several defined values
Write-Host "Retrieving manually typed ordinals from v`$version via OracleDataReader" -ForegroundColor Cyan -BackgroundColor Black
$cmd.CommandText = 'SELECT BANNER FROM v$version'
$rdr = $cmd.ExecuteReader()
while ($rdr.Read()) {
$rdr.GetString(0)
}
$rdr.Dispose()
# Use a DataAdapter to get defined Data objects.
Write-Host "Using a DataAdapter to return NLS_SESSION_PARAMETERS from Oracle" -ForegroundColor Cyan -BackgroundColor Black
$adap = New-Object Oracle.ManagedDataAccess.Client.OracleDataAdapter("SELECT * FROM NLS_SESSION_PARAMETERS",$con)
# Create the builder for the adapter to automatically generate the Command when needed.
$oraCmdBldr = New-Object Oracle.ManagedDataAccess.Client.OracleCommandBuilder($adap)
[System.Data.DataSet]$dataset = New-Object System.Data.DataSet
$adap.Fill($dataset,"NLSSesParams")
$dataset.Tables["NLSSesParams"]
Remove-Variable dataset
}
catch {
Write-Error ("Can't open connection: {0}n{1}" -f $con.ConnectionString, $_.Exception.ToString())
}
finally {
if ($con.State -eq 'Open') { $con.close() }
$con.Dispose()
Write-Host "Disconnected from database" -ForegroundColor Cyan -BackgroundColor Black
}
Connected to database: testb – running on host: bat – Servicename: testb – Serverversion: 11.2.0.4.0
Returning a Scalar Value from Oracle
Hello World!
Retrieving manually typed ordinals from v$version via OracleDataReader
Oracle Database 11g Release 11.2.0.4.0 - 64bit Production
PL/SQL Release 11.2.0.4.0 - Production
CORE 11.2.0.4.0 Production
TNS for Linux: Version 11.2.0.4.0 - Production
NLSRTL Version 11.2.0.4.0 - Production
Using a DataAdapter to return NLS_SESSION_PARAMETERS from Oracle
17
Disconnected from database
PARAMETER VALUE
--------- -----
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
可以通过以下方式轻松修改此代码以在PowerShell Core中运行:
#Requires -PSEdition Desktop
代替#Requires -PSEdition Core
Oracle.ManagedDataAccess
更改为Oracle.ManagedDataAccess.Core
-MinimumVersion
和Get-Package
的{{1}}参数值从Install-Package
更改为"19.3.1"
。