C# - XLSX 到 SQL 服务器 - OpenRecordSet 在 C# 中不工作但在 MS SQL Server Management Studio 中工作

C# - XLSX to SQL Server - OpenRecordSet not working in C# but works in MS SQL Server Management Studio

以下脚本在存储过程中的 SQL Server 2014 Management Studio 中运行,但当我通过 C# 应用程序 .NET Framework 4.8 调用存储过程时不起作用。 SQL代码:

create proc getData
as
Insert INTO tmpLeaveImport ([CarName], Year, Make , Model) 
    SELECT *  FROM OPENROWSET('Microsoft.ACE.OLEDB.15.0',
    'Excel 12.0;Database=E:\Cars\Cars.xlsx',
    'SELECT * FROM [Car Report$]')

我从 C# 得到以下错误:

System.Data.SqlClient.SqlException: 'Cannot initialize the data source object of OLE DB provider "Microsoft.ACE.OLEDB.15.0" for linked server "(null)". OLE DB provider "Microsoft.ACE.OLEDB.15.0" for linked server "(null)" returned message "Unspecified error".'

当此代码在 C# 中执行时:

  //Tried the conn strign with Integrated Security=yes and SSPI
  string ConnString = @"Data Sournce=MySQLServerDB;Initial Catalog=DBName;Integrated Security=true;";
  using (SqlConnection conn = new SqlConnection(ConnString))
        {
            using (SqlCommand cmd = conn.CreateCommand())
            {
                conn.Open();
                cmd.CommandText = "getData";
                cmd.CommandType = CommandType.StoredProcedure;
                cmd.ExecuteNonQuery();
            }
            conn.Open();
        }

精简版

根据 this possibly duplicate question,Excel 文件可能已打开。或者这可能是一个更严重的错误。

不要使用 OPENROWSET 将 Excel 数据导入 SQL 服务器。使用像 ExcelDataReader to read it without using the Access Engine and insert it to the target table with SqlBulkCopy 这样的库。你会避免很多痛苦。

using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
    using (var reader = ExcelReaderFactory.CreateReader(stream))
    {
        using (var bcp = new SqlBulkCopy(connString))
        {
            bcp.DestinationTableName ="SomeTable";
            bcp.WriteToServer(reader);
        }
    }
}

长版

在这两种情况下,存储过程都在 SQL 服务器上运行,而不是在客户端上运行。就 SQL 服务器而言,SSMS 只是另一个客户端。假设两种情况都使用相同的服务器,不同的是每种情况下执行存储过程的账户不同[=15] =]

对于 SSMS,通常是开发人员的帐户在服务器上拥有 sysadmin 权限。对于 C#,该帐户可能是最终用户的帐户,也可能是运行网站的应用程序池帐户,具有 非常 受限的权限。 SQL服务器的默认服务账号也是受限账号。

这很重要,因为访问引擎是一个 COM 组件。要使用它,应用程序需要在注册表中查找它,这需要它自己的权限。如果您在 SO 中搜索您遇到的错误,您会看到 questions where the choice of service account 影响是否可以使用 Access Engine。在其他情况下,文件已打开。

另一个潜在的问题是 ACE 必须针对与计算机上安装的任何以前的 Office 组件相同的体系结构。如果您有 x86 Office 应用程序,则只能安装 x86 版本的 ACE。那是因为您不能使用针对另一种体系结构的进程为一种体系结构创建的 COM 组件。

这也意味着您不能在 SQL 服务器的 x64 安装中使用 x86 ACE,这是过去 10 多年中最常见的安装选项。