为什么C#Ado.net比实体框架6.1.3慢?

时间:2016-11-06 19:04:51

标签: c# ado.net entity-framework-6

我写了一些代码来比较C#Ado.Net和Entity Framework 6.1.3的性能。我正在调用一个存储过程,它返回大约20,000个员工记录,然后将这些数据映射到“Person”对象列表中。然后我运行了1000次此代码的迭代并计算了平均时间。

以下是时间:

  • Ado Net:638 ms

  • 实体框架:544 ms

令我惊讶的是,Ado Net比实体框架慢大约100毫秒。

Ado.Net代码:

    //GetAllPersons is a stored proc hosted in Local DB instance
    var adapter = new SqlDataAdapter("GetAllPersons", conn);
    adapter.Fill(dt);
    //Using Fast member library
    var accessor = TypeAccessor.Create(typeof(Person));
    MemberSet members = accessor.GetMembers();
    var list = new List<Person>();
    foreach(DataRow row in dt.Rows)
    {
        var person = new Person();
        foreach (var member in members)
        {
            if (row[member.Name] != DBNull.Value)
            {
                accessor[person, member.Name] = row[member.Name];
            }
        }
        list.Add(person);
    }

实体框架:

        var context = new AdventureWorks2012Entities1();
        List<Person> list = context.GetAllPersons().ToList();

使用SQL Adatper加载Datatable的代码部分是占用大部分时间的代码。我尝试使用SQL Datareader,但情况更糟。我在这里遗漏了什么,因为据说普通的Ado.Net应该比实体框架更快?

2 个答案:

答案 0 :(得分:3)

您写道,您尝试过SqlDataReader,但速度更慢。它应该是最快的,但由于您没有显示您的代码,我们无法提供建议。但这里有一些通用提示:

<强> 1。按序数获取列值,而不是名称。

而不是使用reader["column_name"],而是应该获得列序数,然后使用它。例如:

using (var reader = command.ExecuteReader())
{
  int col1Ordinal = reader.GetOrdinal("Column1");
  int col2Ordinal = reader.GetOrdinal("Column2");
  while (reader.Read())
  {
    int col1 = (int)reader[col1Ordinal];
    string col2 = (string)reader[col2Ordinal];
    // do something with col1 and col2's values
  }
}

<强> 2。避免多次获取

索引运算符是一个方法调用,因此请避免对同一个值执行多次操作。在您编写的SqlDataAdapter代码中

if (row[member.Name] != DBNull.Value)
{
  accessor[person, member.Name] = row[member.Name];
}

如您所见,您正在拨打row[member.Name]两次。相反,你应该得到它一次并重新使用值

object value = row[member.Name];
if (value != DBNull.Value)
{
  accessor[person, member.Name] = value;
}

第3。避免反思

我以前从未听说过TypeAccessorMemberSet。通过快速搜索,它似乎来自名为fast-member的库。即使它比.NET的内置反射更快,我也对它的速度持怀疑态度。我知道它可以显着减少你必须编写的代码量,这很好,特别是如果你的查询有很多列。但是,如果您正在尝试优化性能,特别是如果您对代码的性能与实体框架相比不满意,则应该删除该依赖项并测试性能差异。

答案 1 :(得分:0)

实体框架(EF)基于Ado.Net;请What is Entity Framework?查看Entity Framework Tutorial。因此,EF不能比纯Ado.Net实现更快。

但是,您实现了一个不太理想的解决方案,其中包含循环中的循环和其他开销,例如使用反射。我认为内部EF实现比这更聪明,并且可能使用上下文初始化而不是内部循环。

试试这个:表中只有一名员工并比较结果。 EF可能会变慢。