某個項目遇到個ora的問題,打算先在開發環境中把託管odp組件更新爲新的版本試一試。於是直接下載了新版本dll替換,但運行報錯 System.MissingMethodException: 找不到方法:“xxxxx”。
甚是詭異,當下百思不得姐 (-_-!!! ...
靜心打坐後試之,解開~~
【問題原因】
1. 基類使用的odp組件 和 派生類使用的組件版本不一致(基類項目引用改成了高版本odp後編譯,但派生類的項目沒有調整編譯);
2. 派生類中操作基類中的 odp 對象(高版本),例如:
//基類定義了方法
protected Oracle.ManagedDataAccess.Client.OracleConnection GetConnection()
在基類裏是 protected OracleConnectionV2 GetConnection()
在派生類裏 OracleConnectionV1 = base.GetConnection(); //返回值類型是OracleConnectionV2
單獨寫了個驗證程序:
1) 基類項目 ClassLibrary.dll
public class DbAccessBase
{
public string DBConnString { get; set; }
public DateTime GetDbTime()
{
object val;
using (OracleConnection conn = new OracleConnection(DBConnString))
{
conn.Open();
using (OracleCommand cmd = new OracleCommand("select sysdate from dual", conn))
{
val = cmd.ExecuteScalar();
}
}
return (DateTime)val;
}
protected OracleConnection GetConnection()
{
return new OracleConnection(DBConnString);
}
public string GetInfo()
{
return GetType().FullName + ", " + typeof(OracleConnection).Assembly.FullName;
}
}
2) 派生類項目ClassLibrary2.dll
public class DbAccess : ClassLibrary.DbAccessBase
{
public DateTime GetDbTime2()
{
object val;
using (OracleConnection conn = new OracleConnection(DBConnString))
{
conn.Open();
using (OracleCommand cmd = new OracleCommand("select sysdate from dual", conn))
{
val = cmd.ExecuteScalar();
}
}
return (DateTime)val;
}
public DateTime GetDbTime3()
{
object val;
using (OracleConnection conn = GetConnection())
{
conn.Open();
using (OracleCommand cmd = new OracleCommand("select sysdate from dual", conn))
{
val = cmd.ExecuteScalar();
}
}
return (DateTime)val;
}
public string GetInfo2()
{
return GetType().FullName + ", " + typeof(OracleConnection).Assembly.FullName;
}
}
3) 調用
private string Call(Func<DateTime> getDbTime)
{
try
{
return getDbTime().ToString();
}
catch (Exception ex)
{
return ex.ToString();
}
}
private void button1_Click(object sender, EventArgs e)
{
ClassLibrary2.DbAccess dbAccess = new ClassLibrary2.DbAccess();
dbAccess.DBConnString = txtDbConnString.Text;
txtOutput.Text = $"{dbAccess.GetInfo()}\r\n{dbAccess.GetInfo2()}\r\n------------\r\n";
//調用基類,高版本odp
txtOutput.Text += Call(dbAccess.GetDbTime) + "\r\n------------\r\n";
//調用派生類,低版本odp
txtOutput.Text += Call(dbAccess.GetDbTime2) + "\r\n------------\r\n";
//調用派生類,混用不同版本odp
txtOutput.Text += Call(dbAccess.GetDbTime3) + "\r\n------------\r\n";
}
private void btnPrintAssemblies_Click(object sender, EventArgs e)
{
Assembly[] array = AppDomain.CurrentDomain.GetAssemblies();
StringBuilder str = new StringBuilder();
foreach (Assembly item in array)
{
str.AppendLine($"{item.FullName}, {item.Location}");
}
txtOutput.Text += str.ToString() + "\r\n------------\r\n";
}
4) 重現方式:
a.先編譯程序集 ClassLibrary.dll 和 ClassLibrary2.dll(都是引用低版本odp組件)
>>此時執行3)的代碼是不報錯的;
b.更改 ClassLibrary.dll 的引用,引用高版本的odp組件,重新編譯生成 ClassLibrary.dll;
>>此時執行3)的代碼就會報錯
ClassLibrary2.DbAccess, Oracle.ManagedDataAccess, Version=4.122.19.1, Culture=neutral, PublicKeyToken=89b483f429c47342
ClassLibrary2.DbAccess, Oracle.ManagedDataAccess, Version=4.121.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342
------------
2020/1/13 11:38:56
------------
2020/1/13 11:38:56
------------
System.MissingMethodException: 找不到方法:“Oracle.ManagedDataAccess.Client.OracleConnection ClassLibrary.DbAccessBase.GetConnection()”。
在 ClassLibrary2.DbAccess.GetDbTime3()
在 WinFormsApp.Form1.Call(Func`1 getDbTime) 位置 E:\Users\fj\source\repos\OdpTest\RefTest\WinFormsApp\Form1.cs:行號 21
------------
其實這時打開 ClassLibrary2.dll 的項目,已經能查看到編譯錯誤,如圖: