Comment puis-je définir une expression à la spécification de fichier de propriété sur Foreach énumérateur de Fichier?
Je suis en train de créer un package SSIS pour traiter les fichiers dans un répertoire qui contient de nombreuses années la valeur de fichiers. Les fichiers sont tous nommé numériquement, afin de sauver le traitement de tout, je veux passer SSIS un nombre minimum, et seulement énumérer les fichiers dont le nom (converti en un nombre) est plus élevé que mon minimum.
J'ai essayé de laisser le ForEach Fichier boucle d'énumérer tout et puis exclure des fichiers dans une Tâche de Script, mais lorsque vous traitez avec des centaines de milliers de fichiers, c'est beaucoup trop lent pour être adapté.
La FileSpec propriété permet de spécifier un masque de fichier pour déterminer les fichiers que vous voulez dans la collection, mais je n'arrive pas à voir comment spécifier une expression pour faire ce travail, car il s'agit essentiellement d'une chaîne de match.
Si il y a une expression au sein de la composante quelque part qui dit en substance Should I Enumerate? - Yes /No
, ce serait parfait. J'ai fait des expériences avec l'au-dessous de l'expression, mais ne peut pas trouver une propriété à laquelle elle s'applique.
(DT_I4)REMPLACER( SUBSTRING(@[Utilisateur::ActiveFilePath],FINDSTRING( @[Utilisateur::ActiveFilePath], "\", 7 ) + 1 ,100),".txt","") > @[Utilisateur::MinIndexId] ? "Vrai" : "False"
Vous devez vous connecter pour publier un commentaire.
Ici est une façon vous pouvez obtenir cette. Vous pouvez utiliser
Expression Task
combiné avecForeach Loop Container
de faire correspondre les valeurs numériques des noms de fichier. Voici un exemple qui montre comment faire cela. L'exemple utiliseSSIS 2012
.Cela peut ne pas être très efficace, mais c'est une façon de le faire.
Nous allons supposer qu'il y a un dossier avec des tas de fichiers nommé au format AAAAMMJJ. Le dossier contient des fichiers pour le premier jour de chaque mois depuis 1921, comme 19210101, 19210201, 19210301 .... tous le mois en cours jusqu'à 20121101. Qui ajoute jusqu'à
1,103
fichiers.Disons que l'exigence est seulement à une boucle sur les fichiers qui ont été créés depuis le mois de juin 1948. Que signifierait le package SSIS a parcourir uniquement les fichiers de plus de
19480601
.Sur le package SSIS, créer des trois paramètres suivants. Il est préférable de configurer des paramètres pour ces parce que ces valeurs sont configurables à travers l'environnement.
ExtensionToMatch
- Ce paramètre deString
type de données contiendra l'extension que le paquet a boucle à travers. Cela permettra de compléter la valeur deFileSpec
variable qui sera utilisée sur la Boucle Foreach conteneur.FolderToEnumerate
- Ce paramètre deString
type de données stocke le chemin d'accès au dossier qui contient les fichiers à boucle à travers.MinIndexId
- ce paramètre deInt32
type de données contiendra au minimum valeur numérique au-dessus de laquelle les fichiers doivent correspondre à la forme.Créer les quatre paramètres qui vont nous aider à boucler sur les fichiers.
ActiveFilePath
- Cette variable deString
type de données contiendra le nom de fichier que le conteneur de Boucle Foreach parcourt chaque fichier dans le dossier. Cette variable est utilisée dans l'expression d'une autre variable. Afin d'éviter toute erreur, le régler à une valeur non vide, dire 1.FileCount
- C'est une variable indicatrice deInt32
type de données sera utilisée pour cet exemple pour illustrer le nombre de fichiers que la Boucle Foreach conteneur boucle à travers.FileSpec
- Cette variable deString
type de données contiendra le fichier de modèle à boucle à travers. Définir l'expression de cette variable mentionnées ci-dessous de la valeur. Cette expression va utiliser l'extension spécifiée sur les paramètres. Si il n'y a pas d'extensions, il*.*
d'une boucle sur tous les fichiers.ProcessThisFile
- Cette variable deBoolean
type de données permettra d'évaluer si un fichier ne correspond aux critères ou non.Configurer l'emballage comme indiqué ci-dessous. Boucle Foreach contenant une boucle sur tous les fichiers correspondant au modèle spécifié sur la
FileSpec
variable. Une expression spécifiée sur l'Expression de la Tâche d'évaluer au cours de l'exécution et remplir la variable ProcessThisFile. La variable sera ensuite utilisé sur la contrainte de Précédence pour déterminer si le fichier ou non.La tâche de script dans la boucle Foreach conteneur d'incrémenter le compteur de variable
FileCount
par 1 pour chaque fichier avec succès correspond à l'expression.La tâche de script à l'extérieur de la boucle Foreach va simplement afficher combien de fichiers ont été bouclé par la boucle Foreach conteneur.
Configurer le conteneur de boucle Foreach pour parcourir le dossier à l'aide du paramètre et les fichiers à l'aide de la variable.
Stocker le nom du fichier dans la variable
ActiveFilePath
que la boucle passe à travers chaque fichier.Sur l'Expression de la tâche, définissez l'expression à la valeur suivante. L'expression de convertir le nom du fichier sans l'extension à un nombre, puis va vérifier si on les évalue à plus grand que le nombre donné dans le paramètre
MinIndexId
Cliquez-droit sur la contrainte de Précédence et de le configurer pour utiliser la variable
ProcessThisFile
sur l'expression. Cela dit, le paquet de traiter le fichier seulement si elle correspond à la condition définie sur l'expression de la tâche.Sur la première tâche de script, j'ai la variable
User::FileCount
ensemble de la ReadWriteVariables et le code C# suivant dans la tâche de script. Cette incrémente le compteur de fichier avec succès correspond à la condition.Sur la deuxième tâche de script, j'ai la variable
User::FileCount
ensemble de la ReadOnlyVariables et le code C# suivant dans la tâche de script. Il suffit de sorties le nombre total de dossiers traités.Lorsque le programme est exécuté avec MinIndexId ensemble de
1948061
(hors ce), il affiche la valeur773
.Lorsque le programme est exécuté avec MinIndexId ensemble de
20111201
(hors ce), il affiche la valeur11
.Espère que ça aide.
D'enquêter sur la façon dont la boucle ForEach fonctionne dans SSIS (en vue de la création de mon propre à résoudre le problème), il semble que la façon dont il fonctionne (aussi loin que je pouvais voir de toute façon) consiste à énumérer l'ensemble de fichiers en premier, avant toute masque est spécifié. Il est difficile de dire exactement ce qui se passe, sans voir le code sous-jacent pour la boucle ForEach, mais il semble être le faisant de cette manière, résultant en un ralentissement des performances lorsque vous traitez avec plus de 100k fichiers.
Tandis que @Shiva solution est incroyablement détaillé et certainement une amélioration par rapport à mon approche initiale, il est essentiellement le même processus, sauf à l'aide d'une Expression de la Tâche de tester le nom de fichier, plutôt que d'une Tâche de Script (ce qui ne semble offrir une certaine amélioration).
Donc, j'ai décidé de prendre une approche totalement différente et plutôt que d'utiliser un fichier de base de boucle ForEach, énumérer la collecte de moi-même dans une Tâche de Script, ma logique de filtrage, puis itérer sur les autres résultats. C'est ce que j'ai fait:
Dans ma Tâche de Script, j'utilise le asynchrones
DirectoryInfo.EnumerateFiles
méthode, qui est l'approche recommandée pour les grandes collections de fichiers, car il permet le streaming, plutôt que d'avoir à attendre pour l'ensemble de la collection à être créé avant l'application de toute logique.Voici le code:
Donc, je énumérer la collecte, l'application de ma logique, car les fichiers sont découverts et ajouter immédiatement le chemin du fichier à ma liste pour la sortie. Une fois terminé, je puis assigner à un Objet SSIS variable nommée ActiveFilenames que je vais utiliser comme collection pour ma boucle ForEach.
J'ai configuré la boucle ForEach comme un ForEach Partir d'une Variable permet, qui maintenant itère sur une beaucoup plus petite collection (Post-filtrées
List<string>
par rapport à ce que je peux seulement supposer a pas filtréList<FileInfo>
ou quelque chose de semblable dans SSIS intégré ForEach Énumérateur de Fichier.Donc les tâches à l'intérieur de ma boucle peut juste être consacré au traitement des données, car il a déjà été filtrée avant de frapper la boucle. Bien qu'il ne semble pas bien différent de mon forfait initial ou Siva exemple, dans la production (pour ce cas particulier, de toute façon) il me semble que le filtrage de la collecte et de l'énumération de manière asynchrone offre un énorme coup de pouce sur l'utilisation de la construction dans le ForEach Énumérateur de Fichier.
Je vais continuer à enquêter sur la boucle ForEach conteneur et voir si je peux reproduire cette logique dans un composant personnalisé. Si je reçois ce travail, je vais poster un lien dans les commentaires.
Le meilleur que vous pouvez faire est d'utiliser FileSpec pour spécifier un masque, comme vous l'avez dit. Vous pourriez inclure au moins certaines caractéristiques, comme les fichiers commençant par "201" pour 2010, 2011 et 2012. Puis, dans une autre tâche, vous pouvez filtrer ceux que vous ne voulez pas de processus (par exemple, 2010).