【问题标题】:SSIS Ado.NET Source With Expression Fails Validation带有表达式的 SSIS Ado.NET 源验证失败
【发布时间】:2023-02-23 03:40:51
【问题描述】:

我有一个奇怪的问题,我有这样的控制流程:

最后是这样的数据流:

我正在尝试从 QuickBooks 桌面文件读取数据,但为了确保我不会不必要地运行数据流任务,我首先比较了 SQL Server 和 Quickbooks 的修改时间。然后,如果返回的记录计数大于零,则执行数据流任务。 数据流任务中的表达式如下:

"SELECT ListID, [Name], CompanyName, TermsRefFullName, IsActive, Notes, TimeModified, TimeCreated FROM Customer WHERE TimeModified > {ts '" + @[User::CustomerMaxTimeMod] + "'} ORDER BY TimeModified DESC"

CustomerMaxTimeMod 是一个字符串变量,它存储我在控制流的第 1 步中获得的最大修改时间。

我知道此表达式有效,因为当数据流首先进入控制流或单独进入时,数据流执行得很好。然而,问题是当这个数据流是一个更大的控制流的一部分并且不是首先执行时,它就会中断说:

[ADO NET Source [2]] Error: An error occurred executing the provided SQL command: <my expression here> ERROR [42000] [QODBC] [sql syntax error] Expected lexical element not found: = <identifier>

[SSIS.Pipeline] Error: "ADO NET Source" failed validation and returned validation status "VS_ISBROKEN".

我对此进行了研究,并且看到有人建议在数据流上将 delay validation 属性设置为 true。我试过了,同时尝试将 validate external metadata 设置为 false。它无论如何都会中断,但会显示一条错误消息:

[ADO NET Source [2]] Error: System.Data.Odbc.OdbcException (0x80131937): ERROR [42000] [QODBC] [sql syntax error] Expected lexical element not found: = <identifier> at System.Data.Odbc.OdbcConnection.HandleError(OdbcHandle hrHandle, RetCode retcode) at System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, String method, Boolean needReader, Object[] methodArguments, SQL_API odbcApiMethod) at System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, String method, Boolean needReader) at System.Data.Odbc.OdbcCommand.ExecuteReader(CommandBehavior behavior) at Microsoft.SqlServer.Dts.Pipeline.DataReaderSourceAdapter.PreExecute() at Microsoft.SqlServer.Dts.Pipeline.ManagedComponentHost.HostPreExecute(IDTSManagedComponentWrapper100 wrapper)

此时我几乎只是在将不同的属性设置为 true 或 false 之间徘徊,不知道该怎么做。任何帮助表示赞赏!

【问题讨论】:

  • @[User::CustomerMaxTimeMod] 的默认/设计时间值是多少
  • @billinkc 字符串的默认值只是我选择并放入值字段中的一些随机日期时间值,这样 ADO 源就不会在设计时抱怨与空字符串进行比较。因为无论如何我都在控制流的第 1 步中获得了该值并替换了它,所以它是什么重要吗?

标签: ssis ado.net visual-studio-2022 dataflowtask qodbc


【解决方案1】:

你正在做的是完全有效的,应该根据我的心理分析工作。需要注意的几点

变量表达式,而不是对象表达式

获取数据流的 Odbc 源上的现有表达式并创建一个变量 @[User::QuerySource] 并使用其中的表达式。

"SELECT ListID, [Name], CompanyName, TermsRefFullName, IsActive, Notes, TimeModified, TimeCreated FROM Customer WHERE TimeModified  > {ts '" + @[User::CustomerMaxTimeMod]  + "'} ORDER BY TimeModified DESC"

现在在 [ADO NET Source] 的表达式中使用 @[User::QuerySource]。

看起来像是什么都没有的东西,它会全部洗净,但现在,您可以在先行步骤中检查生成的查询。当表达式直接应用于对象时,您无法放置断点并查看呈现的值是什么。

我大量使用 tiny script task 引发信息事件,然后流入包执行日志(假设默认日志记录级别)

bool fireAgain = false;
string message = "{0}::{1} : {2}";
foreach (var item in Dts.Variables)
{
    Dts.Events.FireInformation(0, "SCR Echo Back", string.Format(message, item.Namespace, item.Name, item.Value), string.Empty, 0, ref fireAgain);
}

旋钮设置

是的,正如您所猜测的那样,您需要将包上的 DelayValidation 设置为 True,因为表达式的设计时值可能无效。

我认为“验证外部元数据”仅适用于减少设计时模式检查的频率。运行时始终必须验证元数据 - 在包的开始或在 DelayValidation 的情况下紧接执行之前。

猜测根本原因

由于您报告的错误是语法错误而不是更常见的 VS_NEEDSNEWMETADATA,我认为您将要使用脚本任务来弹出 @[User::CustomerMaxTimeMod] 的值和您的查询,因为它不需要任何额外费用并注意最大时间值的格式。它确实闻起来像一个意想不到的或可能是空的值正在进入那里,这就是为什么你会收到语法错误而不是无效的元数据。

您还可以通过在其中添加执行 SQL 任务来对此进行测试。不要将结果推入任何东西,而只是验证是的,您获得/没有获得与数据流相同的体验(这再次变得更容易,因为它现在由变量而不是对象上的表达式驱动)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2020-03-17
    • 2020-11-21
    • 1970-01-01
    相关资源
    最近更新 更多