2013-03-20 53 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(); 
相关问题