UCanAccess、IKVM 和 C#

Posted

技术标签:

【中文标题】UCanAccess、IKVM 和 C#【英文标题】:UCanAccess, IKVM and C# 【发布时间】:2016-02-24 12:45:05 【问题描述】:

我正在尝试使 UCanAccess 在 C# 中工作。我正在使用 Linux 上的 Mono 开发 MonoDevelop。我已经使用IKVM 将所需的 .jar 文件转换为 .dll .NET 文件,这样:

ikvmc -target:library file.jar

然后我在我的 C# 项目中引用了转换后的 .dll 文件。所以,这里是我引用的所有 DLL:

ucanaccess-3.0.3.1.dll hsqldb.dll jackcess-2.1.3.dll commons-logging-1.1.1.dll commons-lang-2.6.dll IKVM.OpenJDK.Core.dll IKVM.OpenJDK.Jdbc.dll IKVM.Runtime

我还将 ucanaccess-3.0.3.1.jar、hsqldb.jar、jackcess-2.1.3.jar、commons-logging-1.1.1.jar 和 commons-lang-2.6.jar 放入我的 bin/Debug 文件夹。

这是我在 Main 中编写的 C# 代码:

//ikvm.runtime.Startup.addBootClassPathAssemby(System.Reflection.Assembly.Load("commons-lang-2.6"));
//ikvm.runtime.Startup.addBootClassPathAssemby(System.Reflection.Assembly.Load("commons-logging-1.1.1"));
//ikvm.runtime.Startup.addBootClassPathAssemby(System.Reflection.Assembly.Load("jackcess-2.1.3"));
//ikvm.runtime.Startup.addBootClassPathAssemby(System.Reflection.Assembly.Load("hsqldb"));
ikvm.runtime.Startup.addBootClassPathAssemby(System.Reflection.Assembly.Load("ucanaccess-3.0.3.1"));

java.sql.Driver v_driver = (java.sql.Driver) java.lang.Class.forName("net.ucanaccess.jdbc.UcanaccessDriver, ucanaccess-3.0.3.1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").newInstance();
java.sql.Connection v_con = v_driver.connect("northwind.mdb", null);

//java.lang.Class.forName("org.hsqldb.jdbcDriver, hsqldb, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
//java.lang.Class.forName("net.ucanaccess.jdbc.UcanaccessDriver, ucanaccess-3.0.3.1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
//java.sql.Connection v_con = java.sql.DriverManager.getConnection("jdbc:ucanaccess://northwind.mdb");

java.sql.Statement v_st = v_con.createStatement();

java.sql.ResultSet v_res = v_st.executeQuery("select * from Categories");
java.sql.ResultSetMetaData v_resmd = v_res.getMetaData();

for (int i = 0; i < v_resmd.getColumnCount(); i++)
    Console.Write(v_resmd.getColumnLabel(i) + "|");
Console.WriteLine();

while (v_res.next())

    for (int i = 0; i < v_resmd.getColumnCount(); i++)
        Console.Write(v_res.getString(i) + "|");
    Console.WriteLine();

代码编译,当我尝试执行时,出现以下错误:

Unhandled Exception:
System.TypeInitializationException: An exception was thrown by the type initializer for net.ucanaccess.jdbc.UcanaccessDriver ---> java.lang.RuntimeException: org.hsqldb.jdbc.JDBCDriver
--- End of inner exception stack trace ---
at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00000] in <filename unknown>:0 
at IKVM.Internal.TypeWrapper.RunClassInit () [0x00000] in <filename unknown>:0 
at IKVM.NativeCode.java.lang.Class.forName0 (System.String name, Boolean initialize, java.lang.ClassLoader loader) [0x00000] in <filename unknown>:0 
at java.lang.Class.forName0 (System.String , Boolean , java.lang.ClassLoader ) [0x00000] in <filename unknown>:0 
at java.lang.Class.forName (System.String className, ikvm.internal.CallerID ) [0x00000] in <filename unknown>:0 
at java.lang.Class.forName (System.String className) [0x00000] in <filename unknown>:0 
at Test.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.TypeInitializationException: An exception was thrown by the type initializer for net.ucanaccess.jdbc.UcanaccessDriver ---> java.lang.RuntimeException: org.hsqldb.jdbc.JDBCDriver
--- End of inner exception stack trace ---
at (wrapper managed-to-native) System.Runtime.CompilerServices.RuntimeHelpers:RunClassConstructor (intptr)
at System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor (RuntimeTypeHandle type) [0x00000] in <filename unknown>:0 
at IKVM.Internal.TypeWrapper.RunClassInit () [0x00000] in <filename unknown>:0 
at IKVM.NativeCode.java.lang.Class.forName0 (System.String name, Boolean initialize, java.lang.ClassLoader loader) [0x00000] in <filename unknown>:0 
at java.lang.Class.forName0 (System.String , Boolean , java.lang.ClassLoader ) [0x00000] in <filename unknown>:0 
at java.lang.Class.forName (System.String className, ikvm.internal.CallerID ) [0x00000] in <filename unknown>:0 
at java.lang.Class.forName (System.String className) [0x00000] in <filename unknown>:0 
at Test.MainClass.Main (System.String[] args) [0x00000] in <filename unknown>:0

我已经尝试过的注释行,没有成功。

我错过了什么吗?提前致谢!

编辑:

@jamadei 是对的,我将所有 jar 合并到一个 jar 中,并且成功了! 这是工作代码(请注意,列索引从 1 开始,而不是从 0 开始):

ikvm.runtime.Startup.addBootClassPathAssemby(System.Reflection.Assembly.Load("ucanaccess-3.0.3.1"));
java.sql.Driver v_driver = (java.sql.Driver) java.lang.Class.forName("net.ucanaccess.jdbc.UcanaccessDriver, ucanaccess-3.0.3.1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null").newInstance();

java.sql.Connection v_con = v_driver.connect("northwind.mdb", null);
java.sql.Statement v_st = v_con.createStatement();

java.sql.ResultSet v_res = v_st.executeQuery("select categoryid, categoryname, description from Categories");
java.sql.ResultSetMetaData v_resmd = v_res.getMetaData();

for (int i = 1; i <= v_resmd.getColumnCount(); i++)
    Console.Write(v_resmd.getColumnLabel(i) + "|");
Console.WriteLine();

while (v_res.next())

    for (int i = 1; i <= v_resmd.getColumnCount(); i++)
        Console.Write(v_res.getString(i) + "|");
    Console.WriteLine();

【问题讨论】:

如果先将 hsqdb 和 ucanaccess jar 合并到一个 jar 中,然后创建 ddl 会怎样? @jamadei,成功了!但我需要将所有罐子合并成一个罐子。谢谢!您会发布并回答,以便我可以选择您的答案吗?我这里已经有一个工作代码,我想分享一下。 我是ucanaccess作者,我在下面回答只是为了分享,但感谢您的探索! 【参考方案1】:

您需要将所有 jar 合并到一个 jar 中,然后将其转换为 dll。

【讨论】:

再次感谢,我用工作代码编辑了问题。

以上是关于UCanAccess、IKVM 和 C#的主要内容,如果未能解决你的问题,请参考以下文章

找不到适合 jdbc:ucanaccess://C:\Users\Asim Iqbal\Documents\PersonInfo.accdb 的驱动程序

java.lang.ClassNotFoundException:net.ucanaccess.jdbc.ucanaccessDriver

IKVM.NET 作为 OpenOffice 的 JRE

有没有办法加快IKVM中的垃圾收集?

带有 IKVM 的 C# 中 Weka 的 LIbSVM

使用 UCanAccess 创建表后,ms 访问未强制执行非空约束