2010-05-25 92 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,导致忽略重复项而不抛出异常。