2009-10-23 3 views
1

Récemment, j'ai été chargé de créer un processus ETL automatisé qui pompe les données dans des tables en fonction du nom de fichier plat en lisant un fichier de mappage maître. J'ai décidé d'aller avec SqlBulkCopy et tout semblait aller bien. L'interface IDataReader a été implémentée pour lire les fichiers plats, les méta-données de SQL Server fournies avec le nombre de colonnes pour un mappage de données un-à-un, tout fonctionnait jusqu'à ce que je traverse le fichier contenant des chaînes vides. SqlBulkCopy lève une exception disant que "La valeur donnée de type String de la source de données ne peut pas être convertie en type int de la colonne cible spécifiée.". Fin de l'histoire, il ne se soucie même pas que le type de DB pour cette colonne soit INT NULL. Je sais que je peux interpréter davantage les méta-données, extraire des types de données pour des colonnes données, construire un DataSet basé sur des informations extraites, redéfinir les données depuis des fichiers plats et obtenir une bonne solution fortement typée qui fonctionnera, mais je suis un gars paresseux qui se sent comme son bonheur a été vicieusement lacéré par Microsoft, ou ma propre incompétence si quelqu'un connaît une solution à mon problème soudain. Merci pour votre temps.SqlBulkCopy refuse de convertir String.Empty en INT NULL

List<String> fileNames; 

DateTime startJobTime = DateTime.Now; 

Console.WriteLine("---------------------------------------------"); 
Console.WriteLine("Start Time: " + startJobTime); 
Console.WriteLine("---------------------------------------------"); 

using (SqlConnection sqlCon = new SqlConnection(sqlConnection)) 
{ 
    try 
    { 
     sqlCon.Open(); 
     sqlCon.ChangeDatabase(edwDBName); 

     // Get service information for staging job 
     UnivStage us = GetStagingJobInfo(jobName, sqlCon); 
     us.StartJobTime = startJobTime; 

     // Get a list of file names 
     fileNames = GetFileList(us, args); 

     if (fileNames.Count > 0) 
     { 
       // Truncate Staging Table 
       TruncateStagingTable(us, sqlCon); 
       // Close and dispose of sqlCon2 connection 
       sqlCon.Close(); 

       Console.WriteLine("Processing files: "); 
       foreach (String fileName in fileNames) 
        Console.WriteLine(fileName); 
       Console.WriteLine(); 
      } 
      else 
      { 
       Console.WriteLine("No files to process."); 
       Environment.Exit(0); 
      } 

      // Re-open Sql Connection 
      sqlCon.Open(); 

      sqlCon.ChangeDatabase(stagingDBName); 


      foreach (String filePath in fileNames) 
      { 
       using (SqlTransaction sqlTran = sqlCon.BeginTransaction()) 
       { 
        using (FlatFileReader ffReader = new FlatFileReader(filePath, us.Delimiter)) 
        { 
         using (SqlBulkCopy sqlBulkCopy = 
           new SqlBulkCopy(sqlCon, SqlBulkCopyOptions.Default, sqlTran)) 
         { 
          SqlConnection sqlCon2 = new SqlConnection(sqlConnection); 

          SetColumnList(sqlCon2, us, sqlBulkCopy); 

          sqlBulkCopy.BatchSize = 1000; 
          sqlBulkCopy.DestinationTableName = 
           us.StagingSchemaName + "." + us.StagingTableName; 

          sqlBulkCopy.WriteToServer(ffReader); 

          sqlTran.Commit(); 

          sqlCon2.Close(); 
         } 
        } 
       } 
      } 

      sqlCon.ChangeDatabase(edwDBName); 
      sqlCon.Close(); 

      sqlCon.Open(); 
      SetRowCount(us, sqlCon); 
      sqlCon.Close(); 

      us.EndJobTime = DateTime.Now; 
      sqlCon.Open(); 
      LogStagingProcess(us, sqlCon); 
      sqlCon.Close(); 

      Console.WriteLine(us.ProcessedRowCount + " rows inserted."); 

      Console.WriteLine("---------------------------------------------"); 
      Console.WriteLine("Success! End Time: " + us.EndJobTime); 
      Console.WriteLine("---------------------------------------------"); 

      Console.ReadLine(); 
     } 
     catch (SqlException e) 
     { 
      RenderExceptionMessagesAndExit(e, 
       "Exception have occured during an attempt to utilize SqlBulkCopy\n"); 
     } 
    } 

Répondre

4

Convertissez vos chaînes vides en DBNull.

+1

Nous vous remercions de votre réponse. Je crains de ne pouvoir le faire à cause des contraintes que je me suis imposées. L'interface IDataReader utilisée par SqlBulkCopy ne peut transmettre que des tableaux de chaînes. –