有没有人知道最有效的方法是检查大型数据库表中是否存在多个项目(最多1000个)(1,000,000行+)以查看是否需要添加它们,使用EF / Linq / a Sql Server db(托管在Azure上)?
目前我的性能速度非常慢(尽管我最初使用以下两种方法在本地Sql db上进行开发时效果要好得多)。
我是否需要考虑将EF留给此任务,并直接针对db运行一些SQL?
//loop to check all imported items against db
private void ImportNewSerialsWorkerUsingLoopCheck(List<foo> importedFoos)
{
List<foos> foosToAddToDb = new List<foo>();
foreach (var foo in importedFoos)
{
fooCheck = context.Foos.FirstOrDefault(f => f.Serial == foo.Serial);
if (fooCheck == null)
{
foosToAddToDb.Add(foo);
}
}
context.foos.AddRange(foosToAddToDb);
}
//use Any() to check all imported items against db
private void ImportNewSerialsWorkerUsingAnyCheck(List<foo> importedFoos)
{
var foosToAddToDb = importedFoos.Where(i => !context.foos.Any(f => f.Serial == i.Serial)).ToList();
context.foos.AddRange(foosToAddToDb);
}
更新
我在.Any()
命令中使用var foosToAddToDb = importedFoos.Where(i => !context.foos.Any(f => f.Serial == i.Serial)).ToList();
LINQ命令时,只针对本地sql db运行sql profiler跟踪,并发现EF将其作为每个项目的单独sql查询运行在importedFoos
中,所以使用该方法似乎没有任何优势。
答案 0 :(得分:4)
您的第二个代码段是作为Linq to objects查询的一部分执行EF查询,因此它为每个项目执行查询的原因。您只需要执行一次EF查询就可以进行一次往返数据库。
var serials = importedFoos. Select(foo => too.Serial);
var existing = context.Foos.Where(foo => serials.Contains(foo.Serial));
var toAdd = importedFoos.Except(existing);