2010-05-25 95 views
0

我正試圖獲得一個目錄(這是不斷增長)充滿.txt逗號分隔文件導入到我的SQLite數據庫。我現在可以導入所有的文件,但是我需要一些方法來排除之前添加到db的文件。我在名爲FileName的數據庫中有一列,其名稱和擴展名存儲在每個文件的每條記錄旁邊。現在我需要說'如果代碼發現XXX.txt和XXX.txt已經在數據庫中,那麼跳過這個文件'。我可以以某種方式將此邏輯添加到getfiles命令,還是有另一種簡單的方法?C#SQLite文件導入防止重複

using (SQLiteCommand insertCommand = con.CreateCommand()) 
       { 
        SQLiteCommand cmdd = con.CreateCommand(); 
        string[] files = Directory.GetFiles(@"C:\Documents and Settings\js91162\Desktop\", "R303717*.txt*", SearchOption.AllDirectories); 
        foreach (string file in files) 
        { 

         string FileNameExt1 = Path.GetFileName(file); 



         cmdd.CommandText = 
          @" 
        SELECT COUNT(*) FROM Import WHERE FileName = @FileExt;"; 
         cmdd.Parameters.Add(new SQLiteParameter("@FileExt", FileNameExt1)); 

        int count = Convert.ToInt32(cmdd.ExecuteScalar()); 
        //int count = ((IConvertible)insertCommand.ExecuteScalar().ToInt32(null)); 

        if (count == 0) 
        { 

         Console.WriteLine("Parsing CMM data for SQL database... Please wait."); 

         insertCommand.CommandText = 
          @" 
        INSERT INTO Import (FeatType, FeatName, Value, Actual, Nominal, Dev, TolMin, TolPlus, OutOfTol, PartNumber, CMMNumber, Date, FileName) 
        VALUES  (@FeatType, @FeatName, @Value, @Actual, @Nominal, @Dev, @TolMin, @TolPlus, @OutOfTol, @PartNumber, @CMMNumber, @Date, @FileName);"; 

         insertCommand.Parameters.Add(new SQLiteParameter("@FeatType", DbType.String)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@FeatName", DbType.String)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@Value", DbType.String)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@Actual", DbType.Decimal)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@Nominal", DbType.Decimal)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@Dev", DbType.Decimal)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@TolMin", DbType.Decimal)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@TolPlus", DbType.Decimal)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@OutOfTol", DbType.Decimal)); 
         insertCommand.Parameters.Add(new SQLiteParameter("@Comment", DbType.String)); 




         string FileNameExt = Path.GetFileName(file); 
         string RNumber = Path.GetFileNameWithoutExtension(file); 

         string RNumberE = RNumber.Split('_')[0]; 

         string RNumberD = RNumber.Split('_')[1]; 
         string RNumberDate = RNumber.Split('_')[2]; 

         DateTime dateTime = DateTime.ParseExact(RNumberDate, "yyyyMMdd", Thread.CurrentThread.CurrentCulture); 
         string cmmDate = dateTime.ToString("dd-MMM-yyyy"); 
         string[] lines = File.ReadAllLines(file); 
         bool parse = false; 

         foreach (string tmpLine in lines) 
         { 


          string line = tmpLine.Trim(); 
          if (!parse && line.StartsWith("Feat. Type,")) 
          { 
           parse = true; 
           continue; 
          } 
          if (!parse || string.IsNullOrEmpty(line)) 
          { 
           continue; 
          } 

          Console.WriteLine(tmpLine); 
          foreach (SQLiteParameter parameter in insertCommand.Parameters) 
          { 
           parameter.Value = null; 
          } 

          string[] values = line.Split(new[] { ',' }); 

          for (int i = 0; i < values.Length - 1; i++) 
          { 
           SQLiteParameter param = insertCommand.Parameters[i]; 
           if (param.DbType == DbType.Decimal) 
           { 
            decimal value; 
            param.Value = decimal.TryParse(values[i], out value) ? value : 0; 
           } 
           else 
           { 
            param.Value = values[i]; 
           } 
          } 
          insertCommand.Parameters.Add(new SQLiteParameter("@PartNumber", RNumberE)); 
          insertCommand.Parameters.Add(new SQLiteParameter("@CMMNumber", RNumberD)); 
          insertCommand.Parameters.Add(new SQLiteParameter("@Date", cmmDate)); 
          insertCommand.Parameters.Add(new SQLiteParameter("@FileName", FileNameExt)); 
          // 
          insertCommand.ExecuteNonQuery(); 

         } 


        } 
        } 
        Console.WriteLine("CMM data successfully imported to SQL database..."); 
       } 
       con.Close(); 
      } 

編輯。也許如果有方法可以說(如果文件'存在於數據庫中'){} ???

回答

1

您可以將數據庫中的文件名加載到字符串列表中,然後使用Except擴展方法從您的目錄返回的文件名中排除這些文件。

foreach (string file in directoryFilenames.Except(databaseFilenames)) 
{ 
    // do something 
} 

本羅賓遜提供了一個類似的答案,但使用WhereContains是要遍歷在第一列表中每個項目的第二列表。 Except方法將只遍歷第二個列表一次。

+0

這很有趣..你如何查詢sqlite數據庫以返回給定列的所有唯一值(例如,來自列文件名的所有不同文件名)?如果我知道這一點,我會嘗試創建一個列表字符串,並使用Except的想法..在此先感謝。 – 2010-05-26 02:08:27

+0

從表名中選擇不同的字段名 – 2010-05-26 12:50:26

0

爲什麼不在一次處理它們後簡單地將文件移動到其他文件夾。

編輯:您的更新代碼將完成這項工作,但由於您正在查詢目錄中每個文件的數據庫,因此需要更長和更長的時間來運行目錄填充。如果你可以從數據庫retrive導入的文件列表爲List<string>然後你可以執行以下操作使用LINQ:

List<string> ImportedFiles = GetImportedFileList() // Method that gets the list of files from the db 
foreach (string file in files.Where(fl => !ImportedFiles.Contains(fl))) 

這意味着你的foreach循環只能通過那些不已經在數據庫中的文件進行迭代。

我假設你知道如何編寫一個方法GetImportedFileList(),它從db獲取文件列表並將它們返回爲List<string>

+0

這就是踢球者..他們被許多人用於各種原因。位置需要保持不變。我只需要說,「好的,已添加,現在跳過它並繼續到下一個文件」 – 2010-05-25 20:38:08

+0

使用FileSystemWatcher在添加文件以解決「更長和更長」部分時發佈事件。 – 2010-05-25 23:49:59

+0

好吧,我有一個公共靜態void(???)安裝程序的方法,foreach到位,但我得到以下錯誤... 無法找到類型或命名空間名稱'列表'你錯過了一個參考?)。 AND 'string []'沒有包含'Where'的定義,沒有擴展名'Where'接受'string []'類型的第一個參數。 – 2010-05-26 04:37:46

0

使文件名列唯一或爲其添加唯一索引,然後執行INSERT或IGNORE,導致忽略重複項而不拋出異常。