C# 使用 SSIS 检查文件夹中的几个特定文件
C# Using SSIS to check for several specific files in a folder
我有一个包含 10 个左右文本文件的列表,我需要确保它们在特定时间在 SSIS 中存在于特定文件夹中。如果这些文件存在,我将启动一个包,如果不存在,我将通过电子邮件发送给客户。我在检查单个文件时没有问题,但我无法遍历所有文件以找到我需要的特定文件。
一个例子是我需要文件 A.txt b.txt e.txt 和 z.txt 并且在目录中你有 a.txt 到 y.txt但没有 z.txt。我希望这是有道理的。如果有人可以帮助我,我将不胜感激! SQL 2008 R2 顺便说一句和 VS 2008。
从数据库的角度来看,这将是从应该存在的 table 个文件到实际存在的 table 个文件的左连接(显示不匹配)。问题是这不是数据库上下文。
您可以将 10 个文件的名称存储在一个 table 中,然后将存在的所有文件的名称导入到一个 "temporary" table 中,从而将其合并。这将使比较变得容易。
遍历文件夹中的所有文件永远不会成为一个优雅的解决方案,因为你必须检查 10 个文件,在 AND 的基础上(它们必须都存在,否则你做其他事情)。你必须在你的 C# 代码中有 10 个标志,当相应的文件出现在循环中时设置每个标志,并在最后检查它们是否全部为 TRUE。这不好玩。
最好只遍历 10 个文件名(这意味着您必须将它们放入某种可循环结构中,例如 table)。然后 C# 代码可以对每个文件执行 System.IO.File.Exists,如果找不到任何文件,请重置您在开始时设置的 AllFilesAreThere 标志。
有很多方法可以解决这个问题,但如果您对 C# 感兴趣,我会看一下类似 Enumerable.Intersect 的方法。
Intersection,正如我们都从集合论中回忆的那样,是同时存在于 A 和 B 中的组。在您的情况下,您的第一个集合将是 "expected" 集合(a.txt、b.txt、e.txt 和 z.txt)。根据需要定义该列表。您可以从 table 中提取它,对列表进行硬编码,随便什么。
var expected = new List<string>() {
@"C:\ssisdata\so\input\so_36362799_a.txt",
@"C:\ssisdata\so\input\so_36362799_b.txt" };
第二组将是"actual"。由于我们在 .NET 领域,我会查看 System.IO.Directory.GetFiles
方法从我们的文件夹中提取所有 .txt 文件。
var actual = System.IO.Directory.GetFiles(@"C:\ssisdata\so\input", "so*.txt");
此时我们有两个集合,物理上实现为 List<string>
但任何实现 IEnumerable 的东西都应该足够了。如果我生成两个列表的交集,我会受到挫折。如果您需要知道哪些文件不在交叉点中,那么您应该捕获结果集。不过我们不在乎,我们只想知道 "do we have all the files we need"
expected.Intersect(actual)
由于我们不关心可能丢失了哪些文件,我们可以简单地计算我们预期的元素数量并将其与交集进行比较。如果计数相同,那么我们应该拥有所需的所有文件。
expected.Count() == expected.Intersect(actual).Count()
因为这是 Windows,我们需要担心区分大小写的问题。在 Unix 世界中,一个目录可以有 foo.txt、Foo.txt、foo.TXT 等,只要区分大小写的文件名是唯一的。 Windows 没有那种担心。 But,确定交集 的字符串比较将 区分大小写,因此如果可能的话,一个人而不是一个程序将生成这些文件,您可能希望强制文件名 upper/lower 大小写与您的预期设置一致。
综合起来,您会得到这样的脚本任务。很多改进的机会。我们可以传入源文件夹、我们的文件列表、文件掩码,然后如果我们没有找到我们期望找到的所有文件应该发生什么——现在它使脚本任务失败。
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using Microsoft.SqlServer.Dts.Runtime;
namespace ST_6fabd2d80a6340399c540f8fdeaebf97
{
/// <summary>
/// Whosebug 36362799
/// </summary>
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
/// <summary>
/// Determine if all the files in our expected set match the actual set
/// </summary>
public void Main()
{
var expected = new List<string>() { @"C:\ssisdata\so\input\so_36362799_a.txt", @"C:\ssisdata\so\input\so_36362799_b.txt" };
var actual = System.IO.Directory.GetFiles(@"C:\ssisdata\so\input", "so*.txt");
bool pokemon = expected.Count() == expected.Intersect(actual).Count();
if (pokemon)
{
Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
由于这是用 SQL Server 2008 标记的,因此默认脚本任务将针对 .NET 框架 2.0。上面的代码将不起作用,因为 intersect 调用将需要 System.Linq 命名空间。这是一个简单的补救措施,在脚本任务中,右键单击项目 (ST_#########) 并转到属性菜单。
我有一个包含 10 个左右文本文件的列表,我需要确保它们在特定时间在 SSIS 中存在于特定文件夹中。如果这些文件存在,我将启动一个包,如果不存在,我将通过电子邮件发送给客户。我在检查单个文件时没有问题,但我无法遍历所有文件以找到我需要的特定文件。
一个例子是我需要文件 A.txt b.txt e.txt 和 z.txt 并且在目录中你有 a.txt 到 y.txt但没有 z.txt。我希望这是有道理的。如果有人可以帮助我,我将不胜感激! SQL 2008 R2 顺便说一句和 VS 2008。
从数据库的角度来看,这将是从应该存在的 table 个文件到实际存在的 table 个文件的左连接(显示不匹配)。问题是这不是数据库上下文。
您可以将 10 个文件的名称存储在一个 table 中,然后将存在的所有文件的名称导入到一个 "temporary" table 中,从而将其合并。这将使比较变得容易。
遍历文件夹中的所有文件永远不会成为一个优雅的解决方案,因为你必须检查 10 个文件,在 AND 的基础上(它们必须都存在,否则你做其他事情)。你必须在你的 C# 代码中有 10 个标志,当相应的文件出现在循环中时设置每个标志,并在最后检查它们是否全部为 TRUE。这不好玩。
最好只遍历 10 个文件名(这意味着您必须将它们放入某种可循环结构中,例如 table)。然后 C# 代码可以对每个文件执行 System.IO.File.Exists,如果找不到任何文件,请重置您在开始时设置的 AllFilesAreThere 标志。
有很多方法可以解决这个问题,但如果您对 C# 感兴趣,我会看一下类似 Enumerable.Intersect 的方法。
Intersection,正如我们都从集合论中回忆的那样,是同时存在于 A 和 B 中的组。在您的情况下,您的第一个集合将是 "expected" 集合(a.txt、b.txt、e.txt 和 z.txt)。根据需要定义该列表。您可以从 table 中提取它,对列表进行硬编码,随便什么。
var expected = new List<string>() {
@"C:\ssisdata\so\input\so_36362799_a.txt",
@"C:\ssisdata\so\input\so_36362799_b.txt" };
第二组将是"actual"。由于我们在 .NET 领域,我会查看 System.IO.Directory.GetFiles
方法从我们的文件夹中提取所有 .txt 文件。
var actual = System.IO.Directory.GetFiles(@"C:\ssisdata\so\input", "so*.txt");
此时我们有两个集合,物理上实现为 List<string>
但任何实现 IEnumerable 的东西都应该足够了。如果我生成两个列表的交集,我会受到挫折。如果您需要知道哪些文件不在交叉点中,那么您应该捕获结果集。不过我们不在乎,我们只想知道 "do we have all the files we need"
expected.Intersect(actual)
由于我们不关心可能丢失了哪些文件,我们可以简单地计算我们预期的元素数量并将其与交集进行比较。如果计数相同,那么我们应该拥有所需的所有文件。
expected.Count() == expected.Intersect(actual).Count()
因为这是 Windows,我们需要担心区分大小写的问题。在 Unix 世界中,一个目录可以有 foo.txt、Foo.txt、foo.TXT 等,只要区分大小写的文件名是唯一的。 Windows 没有那种担心。 But,确定交集 的字符串比较将 区分大小写,因此如果可能的话,一个人而不是一个程序将生成这些文件,您可能希望强制文件名 upper/lower 大小写与您的预期设置一致。
综合起来,您会得到这样的脚本任务。很多改进的机会。我们可以传入源文件夹、我们的文件列表、文件掩码,然后如果我们没有找到我们期望找到的所有文件应该发生什么——现在它使脚本任务失败。
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows.Forms;
using Microsoft.SqlServer.Dts.Runtime;
namespace ST_6fabd2d80a6340399c540f8fdeaebf97
{
/// <summary>
/// Whosebug 36362799
/// </summary>
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
/// <summary>
/// Determine if all the files in our expected set match the actual set
/// </summary>
public void Main()
{
var expected = new List<string>() { @"C:\ssisdata\so\input\so_36362799_a.txt", @"C:\ssisdata\so\input\so_36362799_b.txt" };
var actual = System.IO.Directory.GetFiles(@"C:\ssisdata\so\input", "so*.txt");
bool pokemon = expected.Count() == expected.Intersect(actual).Count();
if (pokemon)
{
Dts.TaskResult = (int)ScriptResults.Success;
}
else
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
由于这是用 SQL Server 2008 标记的,因此默认脚本任务将针对 .NET 框架 2.0。上面的代码将不起作用,因为 intersect 调用将需要 System.Linq 命名空间。这是一个简单的补救措施,在脚本任务中,右键单击项目 (ST_#########) 并转到属性菜单。