C# 正在尝试连接到Ms Access数据库,而我没有';我没有管理员权限或ACE.OLEDB.16.0

C# 正在尝试连接到Ms Access数据库,而我没有';我没有管理员权限或ACE.OLEDB.16.0,c#,ms-access,C#,Ms Access,我正试图编写一个C#程序,将大量Ms Access数据库迁移到Ms Sql server。我目前连接到Ms Sql server没有问题,但访问一直是一堵砖墙 我尝试过使用Odbc使用.Net Core,但似乎无法解决“找不到数据源名称且没有默认驱动程序”的错误。无论我输入了什么,因此我已切换到使用.Net Framework的新项目,认为越旧可能意味着我有更好的机会 我的系统似乎有“Microsoft.Jet.OLEDB.4.0”,但这无法识别我的Access Db,它的格式为“*.accdb

我正试图编写一个C#程序,将大量Ms Access数据库迁移到Ms Sql server。我目前连接到Ms Sql server没有问题,但访问一直是一堵砖墙

我尝试过使用Odbc使用.Net Core,但似乎无法解决“找不到数据源名称且没有默认驱动程序”的错误。无论我输入了什么,因此我已切换到使用.Net Framework的新项目,认为越旧可能意味着我有更好的机会

我的系统似乎有“Microsoft.Jet.OLEDB.4.0”,但这无法识别我的Access Db,它的格式为“*.accdb”。通过互联网,我发现我应该尝试切换到“Microsoft.ACE.OLEDB.16.0”,但遗憾的是“该提供商未在本地计算机上注册。”

我没有管理员权限,因此我尝试按照建议安装AccessDatabaseEngine是徒劳的

您有什么建议?我尝试让C#打开与Ms Access数据库的连接

更新:我已经编写了一个脚本,在86x和64x中运行,它应该可以帮助我连接。是否有人可以帮助改进此脚本,以便我可以快速确定如何从任何计算机连接到access数据库(*.accdb)

string[] filePaths = Directory.GetFiles(pathToAccessDbs);
List<string> providers = new List<string>();

var oleEnum = new OleDbEnumerator();
var elems = oleEnum.GetElements();
if (elems != null && elems.Rows != null)
    foreach (System.Data.DataRow row in elems.Rows)
        if (!row.IsNull("SOURCES_NAME") && row["SOURCES_NAME"] is string)
        {
            Console.WriteLine(row["SOURCES_NAME"]);
            providers.Add(row["SOURCES_NAME"].ToString());
            providers.Add("{" + row["SOURCES_NAME"].ToString() + "}");

        }
RegistryKey reg = null;
Console.WriteLine("**********CurrentUser");
try
{
    reg = (Registry.CurrentUser).OpenSubKey("Software");
    reg = reg.OpenSubKey("ODBC");
    reg = reg.OpenSubKey("ODBC.INI");
    reg = reg.OpenSubKey("ODBC Data Sources");
    if (reg != null)
    {

        Console.WriteLine("--Value");
        foreach (string item in reg.GetValueNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item + "}");
            var val = reg.GetValue(item);
            Console.WriteLine(val);
            providers.Add(val.ToString());
            providers.Add("{" + val.ToString() + "}");
        }
        Console.WriteLine("--Subkeys");
        foreach (string item in reg.GetSubKeyNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item.ToString() + "}");
        }
    }
}
catch { }

Console.WriteLine("**********LocalMachine");
try
{
    reg = (Registry.LocalMachine).OpenSubKey("Software");
    reg = reg.OpenSubKey("ODBC");
    reg = reg.OpenSubKey("ODBC.INI");
    reg = reg.OpenSubKey("ODBC Data Sources");
    if (reg != null)
    {

        Console.WriteLine("--Value");
        foreach (string item in reg.GetValueNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item + "}");
            var val = reg.GetValue(item);
            Console.WriteLine(val);
            providers.Add(val.ToString());
            providers.Add("{" + val.ToString() + "}");
        }
        Console.WriteLine("--Subkeys");
        foreach (string item in reg.GetSubKeyNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item.ToString() + "}");
        }
    }
}
catch { }

Console.WriteLine("**********CurrentConfig");
try
{
    reg = (Registry.CurrentConfig).OpenSubKey("Software");
    reg = reg.OpenSubKey("ODBC");
    reg = reg.OpenSubKey("ODBC.INI");
    reg = reg.OpenSubKey("ODBC Data Sources");
    if (reg != null)
    {

        Console.WriteLine("--Value");
        foreach (string item in reg.GetValueNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item + "}");
            var val = reg.GetValue(item);
            Console.WriteLine(val);
            providers.Add(val.ToString());
            providers.Add("{" + val.ToString() + "}");
        }
        Console.WriteLine("--Subkeys");
        foreach (string item in reg.GetSubKeyNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item.ToString() + "}");
        }
    }
}
catch { }

Console.WriteLine("**********Users");
try
{
    reg = (Registry.Users).OpenSubKey("Software");
    reg = reg.OpenSubKey("ODBC");
    reg = reg.OpenSubKey("ODBC.INI");
    reg = reg.OpenSubKey("ODBC Data Sources");
    if (reg != null)
    {

        Console.WriteLine("--Value");
        foreach (string item in reg.GetValueNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item + "}");
            var val = reg.GetValue(item);
            Console.WriteLine(val);
            providers.Add(val.ToString());
            providers.Add("{" + val.ToString() + "}");
        }
        Console.WriteLine("--Subkeys");
        foreach (string item in reg.GetSubKeyNames())
        {
            Console.WriteLine(item);
            providers.Add(item);
            providers.Add("{" + item.ToString() + "}");
        }
    }
}
catch { }

List<string> returnConnectionStrings = new List<string>();
foreach (string filePath in filePaths)
{
    foreach (string pr in providers)
    {

        Console.WriteLine("///////////////////// " + pr);
        string connectiontest = @"Provider=" + pr
            + "; Data Source Name=" + pr
            + "; Driver=" + pr
            + "; Default Driver=" + pr
            + "; Dsn=" + pr 
            + "; Data Source Name=" + pr
            + "; Data Source=" + filePath
            + "; Dbq=" + filePath
            + "; Jet OLEDB:Database Password=" + vbaPass
            + "; Uid=Admin; Pwd=" + vbaPass
            + "; User Id=Admin; Password=" + vbaPass;
        OleDbCommand cmd = null;
        OdbcCommand cmdOdbc = null;
        try
        {

            OleDbConnection connection = new OleDbConnection(connectiontest);
            connection.Open();
            cmd = connection.CreateCommand();

        }
        catch (Exception e)
        {
            Console.WriteLine((e.Message));
        }
        try
        {

            OdbcConnection connectionOdbc = new OdbcConnection(connectiontest);
            connectionOdbc.Open();
            cmdOdbc = connectionOdbc.CreateCommand();

        }
        catch (Exception e)
        {
            Console.WriteLine((e.Message));
        }

        Console.WriteLine("-----------------------------------------");
        if (cmd is null && cmdOdbc is null) continue;
        Console.WriteLine("-----------------------------------------");
        Console.WriteLine("-----------------------------------------");
        Console.WriteLine("-----------------------------------------");
        try
        {
            if(cmd != null)
            {

                cmd.CommandText = "Select * FROM Branches";
                var a = cmd.ExecuteScalar();
                Console.WriteLine(a);
                Console.WriteLine("This works: " + pr);
            } 
        } catch (Exception e)
        {
            Console.WriteLine((e.Message));
        }
        try
        {
            if (cmdOdbc != null)
            {

                cmdOdbc.CommandText = "Select * FROM Branches";
                var a = cmdOdbc.ExecuteScalar();
                Console.WriteLine(a);
                Console.WriteLine("This Works: " + pr);

            }
        }
        catch (Exception e)
        {
            Console.WriteLine((e.Message));
        }
    }
    string connectionString = @"Provider=ADsDSOObject;Data Source=" + filePath;

    returnConnectionStrings.Add(connectionString);
}
请发表评论:


要使用ACE数据引擎吗? 自office/access 2013以来,安装access不会公开ACE的工作副本。(在2013之前,Access的简单安装将安装+显露ACE的工作副本,以与第三方应用程序一起使用。(VB6、FoxPro、C++、.NET) 现在,安装Access不会向第三方公开ACE data engine的工作副本

因此,只需从此处安装ACE数据引擎:

此外,请确保安装了正确的位大小版本(X86代表x32位)。完成后,您可以连接到access(accDB)文件。注意,“mdb”文件无需安装任何内容,因为“JET”引擎作为windows的一部分已默认安装了20多年

一旦安装了ACE(JET的较新版本),那么在net中使用ODBC提供程序或oleDB提供程序应该可以正常工作。但是,您应该强制将.net项目作为x86而不是“任何cpu”

如果您希望将数据从Access数据库迁移到sql server?没有理由使用.net“自己滚”,我强烈建议您使用SSMA(sql server Access迁移助手)。可以在以下位置找到:

上述操作不仅可以迁移数据,还可以设置现有索引,保留现有主键,甚至上传(保留)表关系保持不变。如果您只有几个简单的表,那么您甚至可以使用SQL Manager从Access导入。但是,如果您想节省大量的工作,而不必重新创建PK,不必重新创建索引,也不必重新创建现有的表关系,那么使用SQL migrati可以节省大量的工作在sql server的助手上。SSMAA还将为您自动为每个表添加一个“timestamp”(rowversion)列。因此,我将使用此工具。 (我还建议您将TS列添加到每个表中-.net将使用此列处理并发问题,如果您将Access用作sql server的前端,Access也将使用此列)

你可以在这里找到:

该工具有一个“点”的学习曲线,但它确实是这项工作的最佳工具

同样,请确保您使用x86或x64位版本——有两个下载。而且,除非您安装了ACE的公开副本,否则该实用程序将无法工作

编辑-可能的建议是使用访问代码。 考虑使用Access。“原因”是Access append(sql)查询具有同时在两个不同连接之间工作的“特殊”功能!。大多数.net提供程序都不能这样做。事实上,大多数系统都不能这样做

如果这些“50”数据库中的表名相同,并且50个数据库中的模式相同,则情况尤其如此

那么,从一个空白的新access数据库

我们将一个链接表设置为sql server表。(使用外部数据选项卡–链接到一个sql server表)

您可以将链接表重命名为任何您想要的名称

t百叶窗

现在,再设置一个链接表到第一个Access数据库(50个数据库中的1个)

我们这样做,因为现在我们可以启动access查询生成器。放入源表,然后从功能区中选择附加查询。选择链接的sql server tble

我们这样做的原因是,您可以使用GUI生成器映射列。因此,您有一个from列和一个to列。这是通过从查询生成器中的组合框中选择字段来完成的

到目前为止,我们还没有编写一行代码。您现在可以运行追加查询,我们只是将数据发送到sql server。表1已经完成

现在,如果其他49个数据库是相同的

然后我们只需编写一个小循环来链接到每个数据库,然后执行追加查询

唯一的问题是,50个表中的每个表名是相同的名称,还是不同的名称

假设所有50个表都有相同的表名和相同的结构

那么我们的vba代码如下所示:

Sub Main()

  ' process all mdb or accdb files in a folder
  
  Dim strDir        As String
  Dim strOneFile    As String
  
  strDir = "c:\test2\*.accDB"
  
  strOneFile = Dir(strDir)
  
  Do While strOneFile <> ""
  
     ' link to this database
     
     ' run the append query to send data to sql server
     Debug.Print strOneFile
     
     DoCmd.TransferDatabase acLink, "MS access", strOneFile, acTable, "tblCustomers", "tblSource", False
     
     ' above links table to tblSource
     
     ' now run append query:
     
     CurrentDb.Execute "qryAppend", dbFailOnError
     
     
      strOneFile = dir()
  Loop
  
  
End Sub
Sub-Main()
'处理文件夹中的所有mdb或accdb文件
作为字符串的Dim strDir
作为字符串的Dim strOneFile
strDir=“c:\test2\*.accDB”
strOneFile=Dir(strDir)
在浏览文件“”时执行此操作
'链接到此数据库
'运行追加查询以将数据发送到sql server
打印strOneFile
DoCmd.TransferDatabase acLink,“MS access”,strOneFile,可执行,“tblCustomers”,“tblSource”,False
'以上链接表到tblSource
'现在运行追加查询:
CurrentDb.执行“qryAppend”,dbFailOnError
strOneFile=dir()
环
端接头

您的电脑中是否安装了Office?如果是,则为32位
Sub Main()

  ' process all mdb or accdb files in a folder
  
  Dim strDir        As String
  Dim strOneFile    As String
  
  strDir = "c:\test2\*.accDB"
  
  strOneFile = Dir(strDir)
  
  Do While strOneFile <> ""
  
     ' link to this database
     
     ' run the append query to send data to sql server
     Debug.Print strOneFile
     
     DoCmd.TransferDatabase acLink, "MS access", strOneFile, acTable, "tblCustomers", "tblSource", False
     
     ' above links table to tblSource
     
     ' now run append query:
     
     CurrentDb.Execute "qryAppend", dbFailOnError
     
     
      strOneFile = dir()
  Loop
  
  
End Sub