首页 > 代码库 > 测试Entity Framework 6比传统Ado.net性能差多少

测试Entity Framework 6比传统Ado.net性能差多少

测试环境:

硬件: Intel I5 4核 +8G内存。

软件: Windows 7 + vs2013 SP2 + EF6.1 + MVC5.1

数据库: vs2013自带的sql express 2012.

测试过程:

1. 新建一默认模板的MVC项目,在Models中添加如下代码并建立对应的库表:

    [Table("Person")]    public class Person    {        public int Id { get; set; }        public string UserName { get; set; }        public DateTime RegTime { get; set; }        public DateTime Birthdate { get; set; }        public string Mark { get; set; }    }

这里有一个有趣的插曲,开始报错找不到“ado.people",纳闷呢,怎么EF这么”聪明“,自动地认为表名是和Person对应的People?
不管了,用[Table]的属性强制固定住。

2. 在HomeController里新建两个Action,一个是管插入Person的,一个是查询Person的:

using EFXpoAdoCompare.Models;using System;using System.Collections.Generic;using System.Data.Common;using System.Data.SqlClient;using System.Diagnostics;using System.Linq;using System.Web;using System.Web.Mvc;namespace EFXpoAdoCompare.Controllers{    public class HomeController : Controller    {        public ActionResult Index()        {            return View();        }        public ActionResult About()        {            ViewBag.Message = "Your application description page.";            return View();        }        public ActionResult Contact()        {            ViewBag.Message = "Your contact page.";            return View();        }        /// <summary>        /// 使用EF保存数据        /// </summary>        /// <param name="persons"></param>        void EFSave(Person[] persons)        {            ApplicationDbContext db = new ApplicationDbContext();            db.Persons.AddRange(persons);            db.SaveChanges();        }        /// <summary>        /// 保用ado保存数据        /// </summary>        /// <param name="persons"></param>        void AdoSave(Person[] persons)        {            SqlConnection conn = new ApplicationDbContext().Database.Connection as SqlConnection;            conn.Open();            using (SqlTransaction trans = conn.BeginTransaction())            {                SqlCommand cmd = new SqlCommand(@"INSERT INTO Person (Birthdate,RegTime,UserName,Mark)VALUES(@Birthdate,@RegTime,@UserName,@Mark)", conn, trans);                cmd.Parameters.Add("Birthdate", System.Data.SqlDbType.Date);                cmd.Parameters.Add("RegTime", System.Data.SqlDbType.DateTime);                cmd.Parameters.Add("UserName", System.Data.SqlDbType.NVarChar);                cmd.Parameters.Add("Mark", System.Data.SqlDbType.NVarChar);                foreach (var p in persons)                {                    cmd.Parameters["Birthdate"].Value =http://www.mamicode.com/ p.Birthdate;                    cmd.Parameters["RegTime"].Value =http://www.mamicode.com/ p.RegTime;                    cmd.Parameters["UserName"].Value =http://www.mamicode.com/ p.UserName;                    cmd.Parameters["Mark"].Value =http://www.mamicode.com/ p.Mark;                    cmd.ExecuteNonQuery();                }                trans.Commit();            }            conn.Close();        }        /// <summary>        /// EF查询数据        /// </summary>        /// <param name="persons"></param>        void EFSearch(Person[] persons)        {            ApplicationDbContext db = new ApplicationDbContext();            var list = db.Persons.Where(p => p.UserName.CompareTo("d") >= 1).Take(_num).ToList();            ViewBag.List = list;        }        /// <summary>        /// Ado查询数据        /// </summary>        /// <param name="persons"></param>        void AdoSearch(Person[] persons)        {            SqlConnection conn = new ApplicationDbContext().Database.Connection as SqlConnection;            conn.Open();            string sql = "SELECT TOP " + _num + " * FROM Person WHERE UserName >= ‘d‘";            SqlCommand comm = new SqlCommand(sql, conn);            List<Person> ps = new List<Person>();            using (SqlDataReader reader = comm.ExecuteReader())            {                while (reader.Read())                {                    ps.Add(new Person()                    {                        Birthdate = (DateTime)reader["Birthdate"],                        Id = (int)reader["Id"],                        UserName = (string)reader["UserName"],                        Mark = (string)reader["Mark"],                        RegTime = (DateTime)reader["RegTime"],                    });                }            }            ViewBag.List = ps;            conn.Close();        }        public ActionResult SearchPerson(int? num)        {            if (num == null) num = 1000;            _num = num.Value;            PersonsCreater pc = new PersonsCreater(_num);            pc.OnPersonsSaving = AdoSearch;            ViewBag.AdoMS = pc.SavePersons();            pc.OnPersonsSaving = EFSearch;            ViewBag.EFMS = pc.SavePersons();            return View();        }        int _num;        public ActionResult CreatePerson(int? num)        {            if (num == null) num = 1000;            _num = num.Value;            PersonsCreater pc = new PersonsCreater(_num);            pc.OnPersonsSaving = AdoSave;            ViewBag.AdoMS = pc.SavePersons();            pc.OnPersonsSaving = EFSave;            ViewBag.EFMS = pc.SavePersons();            return View();        }    }    class PersonsCreater    {        int _num;        public PersonsCreater(int num) { _num = num; }        public Action<Person[]> OnPersonsSaving;        Person[] CreatePersons()        {            Person[] persons = new Person[_num];            Random rand = new Random();            for (int i = 0; i < _num; i++)            {                persons[i] = new Person()                {                    Birthdate = DateTime.Today.AddDays(-rand.Next(365 * 20, 365 * 50)),                    RegTime = DateTime.Now.AddSeconds(-rand.Next(0, 86400 * 365)),                    UserName = Guid.NewGuid().ToString(),                    Mark = "My Mark:" + Guid.NewGuid().ToString(),                };            }            return persons;        }        Stopwatch sw = new Stopwatch();        public long SavePersons()        {            var persons = CreatePersons();            sw.Restart();            OnPersonsSaving(persons);            sw.Stop();            return sw.ElapsedMilliseconds;        }    }}

3.添加视图,配置路由(此处暂且不表,重点不在这儿)试运行通过。

4.开始测试:

测试结果(插入数据, 单位:ms):

 条数 1001000300010000100000
EF 31 196 649 295522714
Ado 12 128 245 104411051

 

测试结果(查询数据, 单位 ms):

 条数 1001000300010000100000
EF 4 11 24 50522
Ado 3 6 13 30169

我先用debug版本,在vs环境下调试,结果比Release版本不调试,速度至少慢了10倍。所以大家在生产环境部署时,一定要用Relase编译你的程序,切记切记。

以上数据都是Release下的运行结果。

 在以上查询数据的结果中, 数据量越小,测试结果越不规则,有时甚至出现ef比ado还快的情况。

 测试结论: 在通常的小数据量应用中,EF和Ado的差别可以忽略不计。只有在大规模插入数据时,EF性能才会明显落后于传统ado。