关于大循环中的LINQ用法

时间:2013-08-15 14:52:36

标签: c# performance linq

我想知道在以下场景中推荐什么:

我有一个大循环,我遍历以获取一个ID,然后我将其存储在数据库中,如下所示:

foreach (var rate in rates)
{
    // get ID from rate name
    Guid Id = dbContext.DifferentEntity
        .Where(x => x.Name == rate.Name).FirstOrDefault();

    // create new object with the newly discovered 
    // ID to insert into the database
    dbContext.YetAnotherEntity.Add(new YetAnotherEntity
    {
        Id = Guid.NewGuid(),
        DiffId = Id,
    }
}

这样做会更好/更快(首先获取所有DifferentEntity ID,而不是单独查询它们吗?

List<DifferentEntity> differentEntities = dbContext.DifferentEntity;

foreach (var rate in rates)
{
    // get ID from rate name
    Guid Id = differentEntities
        .Where(x => x.Name == rate.Name).FirstOrDefault();

    // create new object with the newly discovered 
    // ID to insert into the database
    dbContext.YetAnotherEntity.Add(new YetAnotherEntity
    {
        Id = Guid.NewGuid(),
        DiffId = Id,
    }
}

差异是可以忽略的还是我应该考虑的事情?谢谢你的建议。

3 个答案:

答案 0 :(得分:2)

将您的费率名称存储在已排序的字符串数组(string[])中,而不是ListCollection。然后使用Array.BinarySearch()使搜索速度更快。我要编写的其他内容已由@Felipe编写。

答案 1 :(得分:1)

跑马吧!我们真的知道很多。是否可以将所有实体保留在内存中?其中有多少与Name相比重复?

一个简单的解决方案,从数据库中获取一次并使用并行性:

// Fetch entities
var entitiesDict = dbContext.DifferentEntity
     .Distinct(EqualityComparerForNameProperty).ToDictionary(e => e.Name); 

// Create the new ones real quick and divide into groups of 500 
// (cause that horse wins in my environment with complex entities, 
// maybe 5 000 or 50 000 fits your scenario better since they are not that complex?)
var newEnts = rates.AsParallel().Select((rate, index) => {
  new {
        Value = new YetAnotherEntity
           { Id = Guid.NewGuid(), DiffId = entitiesDict[rate.Name],},
        Index = index
     }
  })
.GroupAdjacent(anon => anon.Index / 500) // integer division, and note GroupAdjacent! (not GroupBy)
.Select(group => group.Select(anon => anon.Value)); // do the select so we get the ienumerables

// Now we have to add them to the database
Parallel.ForEach(groupedEnts, ents => {
   using (var db = new DBCONTEXT()) // your dbcontext
   {
     foreach(var ent in ents)       
       db.YetAnotherEntity.Add(ent);

     db.SaveChanges();
   }
});

通常在数据库场景中,昂贵的东西是获取和提交,所以尽量将它们保持在最低限度。

答案 2 :(得分:0)

您可以减少在数据库中执行的查询次数。例如,获取所有名称并查询名称包含的findind Ids。

尝试这样的事情。

// get all names you have in rates list...
var rateNames = rates.Select(x => x.Name).ToList();

// query all Ids you need where contains on the namesList... 1 query, 1 column (Id, I imagine)
var Ids = dbContext.DifferentEntity.Where(x => rateNames.Contains(x.Name).Select(x => x.Id).ToList();

// loop in Ids result, and add one by one
foreach(var id in Ids)
    dbContext.YetAnotherEntity.Add(new YetAnotherEntity
    {
        Id = Guid.NewGuid(),
        DiffId = id,
    }