Reputation: 413
I wrote some code to compare performance of C# Ado.Net and Entity Framework 6.1.3. I am calling a stored procedure which returns around 20,000 employee records and then map this data into List of "Person" objects. Then I ran 1000 iterations of this code and calculated the average time.
Here are the timings:
Ado Net: 638 ms
Entity Framework: 544 ms
To my surprise, Ado Net is around 100 ms slower than Entity Framework.
Ado.Net code:
//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);
}
Entity Framework:
var context = new AdventureWorks2012Entities1();
List<Person> list = context.GetAllPersons().ToList();
The part of the code which uses SQL Adatper to load Datatable is the one taking most of the time. I tried using SQL Datareader instead but it was even worse. Am I missing something here because supposedly plain Ado.Net should be faster than Entity Framework?
Upvotes: 2
Views: 816
Reputation: 6795
The Entity Framework (EF) is based on Ado.Net; see What is Entity Framework? by the Entity Framework Tutorial. Consequently, EF cannot be faster than a pure Ado.Net implementation.
However, you implemented a less ideal solution with a loop in a loop and other overhead such as using reflection. I suppose the internal EF implementation is smarter than that and possibly makes use of the context initialization instead of having an inner loop.
Try this: Have only one single employee in your table and compare the results. EF is likely to be slower.
Upvotes: 0
Reputation: 15011
You wrote that you tried SqlDataReader, but it was even slower. It should be the fastest, but since you didn't show your code, we can't offer suggestions. But here are some generic tips:
1. Get column values by ordinal, not name.
Rather than using reader["column_name"]
, instead you should get the column ordinal, then use that. For example:
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. Avoid multiple gets
The index operator is a method call, so avoid doing it multiple times for the same value. In your SqlDataAdapter code you wrote
if (row[member.Name] != DBNull.Value)
{
accessor[person, member.Name] = row[member.Name];
}
As you can see, you're calling row[member.Name]
twice. Instead, you should get it once and re-use the value
object value = row[member.Name];
if (value != DBNull.Value)
{
accessor[person, member.Name] = value;
}
3. Avoid reflection
I've never heard of TypeAccessor
or MemberSet
before. From a quick search, it seems to be from a library called fast-member
. Even if it's faster than .NET's built-in reflection, I'm sceptical about how fast it is. I know it's nice that it can significantly reduce the amount of code you have to write, particularly if your query has many columns. But, if you're trying to optimise for performance, particularly if you're unhappy with your code's performance compared to Entity Framework, you should remove that dependency and test what the performance difference is.
Upvotes: 3