迭代两个相同的数据源

时间:2013-03-20 15:15:23

标签: c# linq

我在管道分隔的文本文件和数据库表中包含相同模式的数据,包括主键列。

我必须检查文件中的每一行是否存在于表中,如果没有为该行生成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();
编辑:对不起,我错过了询问实际问题;这该怎么做? 非常感谢您的帮助。

编辑:该表有100多万行,而文件有50K行。这是一次性的事情,而不是永久性的项目。

3 个答案:

答案 0 :(得分:2)

尝试使用.Except()

比较ID列表
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));

对于我们在评论中的迂腐和咄咄逼人,请记住上面的代码(就像您在互联网上找到的任何源代码一样)不应该复制/粘贴到您的生产代码中。试试这个重构:

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

答案 1 :(得分:2)

我会在HashSet中添加所有RecipientsInDB ID,然后测试该集是否包含项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();

答案 2 :(得分: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或您想要的任何技术),然后以这种方式插入缺失的记录。