2013-03-20 61 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(); 

編輯:對不起,我錯過了詢問的實際問題;這個怎麼做? 非常感謝您的幫助。

編輯:表有百萬加上行,而文件有50K行。這是一次性的事情,而不是一個永久的項目。

+6

你的問題是什麼? – 2013-03-20 15:16:45

+0

@BalaR我想問如何做到這一點。抱歉。 – FMFF 2013-03-20 15:19:12

+1

拋開感覺,當你運行該代碼時發生了什麼? – 2013-03-20 15:19:50

回答

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

另一個辦法是檢索數據庫的全部內容複製到內存事先,裝載數據庫ID爲HashSet,然後只檢查HashSet以查看它是否存在 - 開始時間要稍長一些,但每個記錄的速度會更快。

這三種技術中的任何一種都可以工作 - 這一切都取決於數據庫表的大小以及文件的大小。如果它們都相對較小(可能大約爲10,000條記錄),則其中任何一項都應該正常工作。

編輯

而且總是有選擇d:將文件中的所有記錄到一個臨時表(可能是一個真正的表或SQL臨時表,其實並不重要),在數據庫中,然後使用SQL將兩個表連接在一起並檢索差異(使用not existsin或任何您需要的技術),然後以這種方式插入缺失的記錄。

+0

該文件有50,000行,而數據庫表有1 mill + rows – FMFF 2013-03-20 15:25:09

+1

在這種情況下,這取決於您期待的差異。如果很多(或者你不知道),我會用'if not exists'方法 - 即使你要生成一個大的SQL語句,它會全部執行。如果你希望有少數差異,那麼我會用'HashSet'去 - 一百萬英寸內存在內存中查找並不是很糟糕 - 在這裏你會有一個大的查詢加上一個小的小孩的數量。我會避免在這種情況下查找每條記錄 - 這將保證50,000個單獨的查詢,以及插入。 – 2013-03-20 15:33:19

+0

或選項D - 請參閱編輯。在我之前的評論中,我的意思是一個大的SQL腳本,而不是一個大的聲明。這將是很多小的陳述。 – 2013-03-20 15:37:17

2

嘗試比較在註釋中使用.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我們之間的ID列表中,請記住上面的代碼(如任何源代碼,你在interwebs發現)不應該拷貝/粘貼到您的生產代碼中。試試這個重構:

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 2013-03-20 15:24:07

+0

@LukeHennerley該鏈接似乎被打破 – FMFF 2013-03-20 15:26:21

+0

@FMFF不適合我這不是。 Google'linq foreach vs foreach',它應該是來自'blogs.msdn'的第二個鏈接:) – LukeHennerley 2013-03-20 15:28:07

2

我會將所有RecipientsInDB ID添加到HashSet中,然後測試該集是否包含項目ID。

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(); 
相關問題