SQL 访问数据库的 SSIS 包代理作业失败

SQL Agent job failure with SSIS package to Access DB

我有一个 SSIS 包,它 运行 是一个脚本任务(主要是,还有一些其他事情)。脚本任务使用 OleDB 连接连接到 Access 数据库。这是 Microsoft Jet 4.0 连接。我安装了驱动程序。但它不会 运行 in SQL 通过代理帐户代理。它将 运行 直接从 Visual Studio 和包商店中获得。事实上,当我以代理绑定的特殊帐户登录时,这两个地方都 运行 没问题。但是当我通过 SQL 服务器代理 运行 时,我得到了可怕的 "Unspecifed Error" OleDbException。

来自脚本任务的相关代码:

// class field
private string accessConnectionStringTemplate = "Data Source=\"{0}\";Provider=Microsoft.Jet.OLEDB.4.0;";

// in method that connects to database
Print(file, "Connection string: " + string.Format(accessConnectionStringTemplate, file.FileName));
// outputs: Data Source = "\Path\To\File";Provider=Microsoft.Jet.OLEDB.4.0"
using(access = new OleDbConnection(string.Format(accessConnectionStringTemplate, file.FileName))) {
     access.Open();
     // other code
}

通过 SQL 代理作业历史记录的错误消息:

Started:  12:35:10 PM
Error: 2016-11-03 12:35:33.51
   Code: 0x00000000
   Source: Import Files Main
   Description: Exception: Unspecified error
End Error
Error: 2016-11-03 12:35:33.51
   Code: 0x00000000
   Source: Import Files Main
   Description:    at System.Data.OleDb.OleDbConnectionInternal..ctor(OleDbConnectionString constr, OleDbConnection connection)
   at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(DbConnection owningConnection, DbConnectionPoolGroup poolGroup, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
   at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
   at System.Data.ProviderBase.DbConnectionInternal.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.OleDb.OleDbConnection.Open()
   at ST_cc0028a4b56242909c2eae546a807995.csproj.ScriptMain.ImportFile(AccessFile file, DateTime startRecordDate, DateTime endRecordDate, List`1 accessTables, Boolean includeTransactionTables, List`1 specifiedTableList)
   at ST_cc0028a4b56242909c2eae546a807995.csproj.ScriptMain.Main()
End Error
Error: 2016-11-03 12:35:33.51
   Code: 0x00000006
   Source: Import Files 
   Description: The script returned a failure result.
End Error

我确定的一些事情:

在我在互联网上看到的其他问题中,这通常是驱动程序的问题。在这种情况下,我不确定它会怎样。

我很乐意提供更多信息来帮助其他人进行诊断。我自己完全不确定为什么这不起作用。

我建议尝试一些事情:

  1. 尝试使用 cmd 模式执行您的程序包,即使用 SQL Agent 中的 dtexce.exe 语法(同时使用 32 位和 64 位选项)。

  2. 将服务帐户(帐户 SQL 代理 运行 通过)添加到 DCOM component for Integration Service。如果允许,请将 SQL 代理服务帐户更改为代理帐户(用于测试)。

  3. 使用代理帐户执行所有操作,即使用代理帐户部署包并将作业所有者设为代理帐户(在 SQL 代理中)。使用代理帐户创建作业。

  4. 如果您有任何与您的代理帐户或SQL代理服务帐户相关的错误,请检查Windowevent viewer

  5. 如果您使用 SQL Server 2012 或更高版本部署包,请尝试使用 Integration Services Catalog。

事实证明,问题在于 Jet 提供程序正试图写入 SQL 代理用户的临时目录,即使该任务是 运行 并且冒充为不同的用户。这似乎是 Windows 模拟系统的一个功能,它不会更改用户配置文件,只会更改用户令牌。我最终得到了这段代码:

var tempPath = Path.GetTempPath().Replace("\SQLSERVERAGENT\", "\" + Environment.UserName + "\");
Environment.SetEnvironmentVariable("TEMP", tempPath);
Environment.SetEnvironmentVariable("TMP", tempPath);

这并不理想,但它确实有效。这意味着我不必为 SQL 代理的临时目录授予权限。只有这段代码需要更改。

遗憾的是,似乎无法更改 ODBC 驱动程序放置其临时文件的位置。

编辑:我也遇到了带有 Excel 源的基于常规数据流的包的问题。在这种情况下,我别无选择,只能为我的代理用户帐户授予对 SQL 代理临时目录的访问权限。如果我也能想出一个解决方法,我会 post 它。