为什么这种EF数据导入方法的性能如此糟糕?

时间:2012-05-26 10:03:29

标签: performance entity-framework

我有一个循环,在这里删节,执行员工记录的导入,如下所示:

var cts2005 = new Cts2005Entities();
IEmployeeRepository repository = new EmployeeRepository();

foreach (var c in cts2005.Candidates)
{
    var e = new Employee();

    e.RefNum = c.CA_EMP_ID;
    e.TitleId = GetTitleId(c.TITLE);
    e.Initials = c.CA_INITIALS;
    e.Surname = c.CA_SURNAME;

    repository.Insert(e);
}

实际上还有几个字段,总共有9个查找,例如GetTitleId(c.TITLE) 以上。这些代码完全是这样的:

private List<Title> _titles;
private Guid GetTitleId(string titleName)
{
    ITitleRepository repository = new TitleRepository();
    if (_titles == null)
    {
        _titles = repository.ListAll().ToList();
    }
    var title = _titles.FirstOrDefault(t => String.Compare(t.Name, titleName, StringComparison.OrdinalIgnoreCase) == 0);
    if (title == null)
    {
        title = new Title { Name = titleName };
        repository.Insert(title);
        _titles.Add(title);
    }
    return title.Id;
}

所有repository.Insert()次调用都是这样的,但实体类型不同:

public void Insert(Employee entity)
{
    CurrentDbContext.Employees.Add(entity);
    CurrentDbContext.SaveChanges();
}

所有PK都是Guid。我知道这可能是一个小问题,但我没想到它会像这样的小卷那么大。

我还没有对这个例程进行调整或优化,因为它只适用于我的小测试数据库,但昨天我被迫做了6000条记录的意外导入。最后,这个处理速度已经放慢到每条记录大约1秒,这非常令人沮丧。没有一些调整,我不会期望高速,但没有那么低。

我的方法在这里有什么明显的错误吗?

2 个答案:

答案 0 :(得分:1)

你的GetTitleId将数据库中的所有标题一次性下载到应用程序中,但它正在为每个“候选人”对所有标题进行线性搜索。这可能非常昂贵。使用带有StringComparer.OrdinalIgnoreCase的客户端哈希表。

另外,为什么不描述您的申请?加载它并在调试器中点击10次。它大部分时间停在哪里?这是热点。

答案 1 :(得分:1)

感谢上面marc_s的评论,我将例程更改为每500次插入只调用SaveChanges,速度提高了约500%。