我在两个数据库中有记录。这是第一个数据库中的实体:
public class PersonInDatabaseOne
{
public string Name { get; set; }
public string Surname { get; set; }
}
这是第二个数据库中的实体:
public class PersonInDatabaseTwo
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
如何从第二个数据库中获取第一个数据库中不存在的记录(第一个名称和姓氏必须与第一个数据库中的不同)。现在我有类似的东西,但这很慢,太慢了:
List<PersonInDatabaseOne> peopleInDatabaseOne = new List<PersonInDatabaseOne>();
// Hear I generate objects but in real I take it from database:
for (int i = 0; i < 100000; i++)
{
peopleInDatabaseOne.Add(new PersonInDatabaseOne { Name = "aaa" + i, Surname = "aaa" + i });
}
List<PersonInDatabaseTwo> peopleInDatabaseTwo = new List<PersonInDatabaseTwo>();
// Hear I generate objects but in real I take it from database:
for (int i = 0; i < 10000; i++)
{
peopleInDatabaseTwo.Add(new PersonInDatabaseTwo { FirstName = "aaa" + i, LastName = "aaa" + i });
}
for (int i = 0; i < 10000; i++)
{
peopleInDatabaseTwo.Add(new PersonInDatabaseTwo { FirstName = "bbb" + i, LastName = "bbb" + i });
}
List<PersonInDatabaseTwo> peopleInDatabaseTwoWhichNotExistInDatabaseOne = new List<PersonInDatabaseTwo>();
// BELOW CODE IS VERY SLOW:
foreach (PersonInDatabaseTwo personInDatabaseTwo in peopleInDatabaseTwo)
{
if (!peopleInDatabaseOne.Any(x => x.Name == personInDatabaseTwo.FirstName && x.Surname == personInDatabaseTwo.LastName))
{
peopleInDatabaseTwoWhichNotExistInDatabaseOne.Add(personInDatabaseTwo);
}
};
答案 0 :(得分:4)
最快的方法取决于实体的数量,以及您已经拥有的索引。
如果有一些实体,那么您已经拥有的功能会更好,因为对一小组的多次扫描所花费的时间少于创建HashSet
个对象。
如果您的所有实体都适合内存,最好的方法是从中构建HashSet
,并使用Except
,其中详细说明了@ alex.feigin。
如果您无法负担加载内存中的所有实体,则需要根据比较密钥将它们分成块并将其加载到内存中并应用{{ 1}}方法反复。请注意,批量不能基于记录数,而是基于比较键。例如,加载名称以HashSet
开头的所有实体,然后加载'A'
,依此类推。
如果您已在其中一个数据库中的比较键(例如,在您的情况下,'B'
和FirstName
)上有数据库的索引,则可以检索已排序的列表来自数据库。这将帮助您在排序列表上进行二进制搜索(http://en.wikipedia.org/wiki/Binary_search_algorithm)以进行比较。请参阅https://msdn.microsoft.com/en-us/library/w4e7fxsh(v=vs.110).aspx
如果您已在两个数据库上的比较键上有数据库索引,则可以在O(n)中以可扩展的方式(任何数字)执行此操作记录)。您需要遍历两个列表并仅查找一次差异。有关详细信息,请参阅https://stackoverflow.com/a/161535/187996。
答案 1 :(得分:1)
编辑:关于评论 - 使用真实模型和字典而不是简单集:
尝试将您的列表哈希到一个词典中以保存您的人物对象,作为键 - 尝试一个元组而不是一个名字1 == name2&amp;&amp; lname1 == lname2。
这可能看起来像这样:
// Some people1 and people2 lists of models already exist:
var sw = Stopwatch.StartNew();
var removeThese = people1.Select(x=>Tuple.Create(x.FirstName,x.LastName));
var dic2 = people2.ToDictionary(x=>Tuple.Create(x.Name,x.Surname),x=>x);
var result = dic2.Keys.Except(removeThese).Select(x=>dic2[x]).ToList();
Console.WriteLine(sw.Elapsed);
我希望这会有所帮助。