2013-03-20 5 views
1

У меня есть данные с той же схемой в текстовом файле с разделителями каналов и в таблице базы данных, включая столбец первичного ключа.Итерация через два идентичных источника данных

Я должен проверить, присутствует ли каждая строка в файле в таблице, если не создается оператор INSERT для этой строки.

Таблица содержит 30 столбцов, но здесь я упростил для этого примера:

ID  Name Address1 Address2 City State Zip 

ID является колонна работает идентичность; поэтому, если в таблице найдено определенное значение ID из файла, для него не должно быть insert.

Вот моя попытка, которая не чувствует себя правильно:

foreach (var item in RecipientsInFile) 
     { 
      if (!RecipientsInDB.Any(u => u.ID == item.ID)) 
      { 
       Console.WriteLine(GetInsertSql(item)); 
      } 
     } 
     Console.ReadLine(); 

EDIT: К сожалению, я пропустил запрашиваемая фактический вопрос; как это сделать? Большое спасибо за помощь.

EDIT: таблица содержит миллион строк, а файл имеет 50K строк. Это одно время, а не постоянный проект.

+6

В чем ваш вопрос? –

+0

@BalaR Я хотел спросить, как это сделать. Сожалею. – FMFF

+1

Чувства в стороне, что случилось, когда вы запустили этот код? –

ответ

0

Много способов этого. Твой - это один из способов.

Еще бы всегда генерировать SQL, но создать его следующим образом:

if not exists (select 1 from Recipients where ID == 1234) 
    insert Recipients (...) values (...) 
if not exists (select 1 from Recipients where ID == 1235) 
    insert Recipients (...) values (...) 

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

Любая из этих трех методик будет работать - все зависит от того, насколько велика ваша таблица базы данных и насколько большой ваш файл. Если они оба относительно небольшие (возможно, 10 000 записей или около того), то любой из них должен работать нормально.

EDIT

И всегда есть вариант D: Включить все записи из файла во временную таблицу (может быть реальной таблицы или таблицы SQL темп, действительно не имеет значения) в базе данных, то используйте SQL для объединения двух таблиц и получения различий (используя not exists или in или любой другой метод, который вы хотите) и вставьте отсутствующие записи таким образом.

+0

Файл имеет 50 000 строк, а таблица базы данных имеет 1 стану + строки – FMFF

+1

В этом случае это сводится к тому, сколько различий вы ожидаете. Если много (или вы не знаете), я бы пошел с методом 'if not exist', даже если бы вы создавали большой оператор SQL, все это выполнялось бы одним крупным махом. Если вы ожидаете небольшого количества различий, то я бы пошел с «HashSet» - миллион ints по-прежнему не страшно хранить в памяти и выполнять поиск - здесь у вас будет один большой запрос плюс небольшой количество маленьких. В этом случае я бы не стал искать каждую запись, что гарантировало бы 50 000 индивидуальных запросов плюс вставки. –

+0

Или вариант D - см. Править. И по моему предыдущему комментарию я имел в виду один большой SQL-скрипт, а не один большой оператор. Было бы очень мало заявлений. –

2

Попробуйте сравнивая списки ID с помощью .Except()

List<int> dbIDs = Recipients.Select(x=>x.ID).ToList(); 
List<int> fileIDs = RecipientsFile.Select(x=>x.ID).ToList(); 
List<int> toBeInserted = fileIDs.Except(dbIDs).ToList(); 

toBeInserted.ForEach(x=>GetInsertSqlStatementForID(x)); 

Для педантичного и trollish у нас в комментариях, пожалуйста, помните, приведенный выше код (как и любой исходный код, который вы найдете на межсеть) не должна быть копией/вставлен в ваш производственный код. Попробуйте этот рефакторинг:

foreach (var item in RecipientsFile.Select(x=>x.ID) 
            .Except(DatabaseRecipients.Select(x=>x.ID))) 
{ 
    GetInsertSqlStatementForID(item); 
} 
+0

Рассмотрите эту ссылку в блоге, когда дело доходит до использования' IEnumerable.ForEach() 'вместо простого' foreach' , кроме этого +1. http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx – LukeHennerley

+0

@LukeHennerley Эта ссылка, кажется, сломана – FMFF

+0

@FMFF не для меня это не так. Google 'linq foreach vs foreach', и это должно быть второе звено от' blogs.msdn' :) – LukeHennerley

2

Я бы добавил все идентификаторы RecipientsInDB в HashSet, а затем проверил, содержит ли набор идентификатор элемента.

var recipientsInDBIds = new Hashset(RecipientsInDB.Select(u => u.ID)); 
foreach (var item in RecipientsInFile) 
    { 
     if (!recipientsInDBIds.Contains(item.ID)) 
     { 
      Console.WriteLine(GetInsertSql(item)); 
     } 
    } 
    Console.ReadLine(); 
Смежные вопросы