2010-05-25 3 views
0

Я пытаюсь получить каталог (который постоянно растет), полный файлов с разделителями-запятыми .txt для импорта в мой SQLite-db. Теперь у меня есть все файлы, импортирующие ok, однако мне нужно иметь какой-то способ исключить файлы, которые ранее были добавлены в db. У меня есть столбец в db с именем FileName, где имя и расширение хранятся рядом с каждой записью из каждого файла. Теперь мне нужно сказать: «Если код находит XXX.txt, а XXX.txt уже находится в db, то пропустите этот файл». Могу ли я каким-то образом добавить эту логику в команду getfiles или есть еще один простой способ?C# SQLite file import предотвращает дублирование

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(); 
      } 

EDIT. Возможно, если есть способ сказать, что (файл «присутствует в db») {} ???

ответ

1

Вы можете загрузить имена файлов из базы данных в список строк, а затем использовать метод расширения Except, чтобы исключить эти файлы из имен файлов, возвращаемых из вашего каталога.

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

Бен Робинсон предлагает подобный ответ, но с использованием Where и Contains собирается перебрать второй список для каждого элемента в первом списке. Метод Except будет перебирать только один раз по второму списку.

+0

Это интересно .. Как вы запрашиваете sqlite db для возврата всех уникальных значений данного столбца (например, всех разных имен файлов из имени файла столбца)? если я это знаю, я попытаюсь создать строку списка и использовать идею Except. Спасибо заранее. –

+0

выберите отдельное имя поля из tablename –

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))) 

Это означает, что ваш цикл Еогеаспа бы итерацию только через файлы, которые не были в базе данных уже.

Я предположил, что вы знаете, как написать метод GetImportedFileList(), который получает список файлов из db и возвращает их как List<string>.

+0

Thats the kicker .. Они используются многими людьми по разным причинам. Место должно оставаться неизменным. Мне просто нужно сказать: «ОК, это было добавлено, теперь пропустите его и перейдите к следующему файлу» –

+0

Используйте FileSystemWatcher для публикации событий всякий раз, когда файл добавляется, чтобы обойти «более длинную и длинную» часть. –

+0

Хорошо, у меня есть метод как общедоступный статический void (???) setup, foreach на месте, но я получаю следующую ошибку ... Тип или имя пространства имен «Список» не найдено (есть вам не хватает ссылки?). AND «string []» не содержит определения для «Где» и не имеет расширения menthod «Где» принятие первого аргумента типа «string []» не удалось найти. –

0

Сделайте столбец имени файла уникальным или добавьте для него уникальный индекс, а затем выполните INSERT ИЛИ IGNORE, в результате чего дубликаты будут проигнорированы без исключения исключений.