测试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 = p.Birthdate;
                    cmd.Parameters["RegTime"].Value = p.RegTime;
                    cmd.Parameters["UserName"].Value = p.UserName;
                    cmd.Parameters["Mark"].Value = 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):

 条数  100 1000 3000 10000 100000
EF  31  196  649  2955 22714
Ado  12  128  245  1044 11051

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

 条数  100 1000 3000 10000 100000
EF  4  11  24  50 522
Ado  3  6  13  30 169

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

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

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

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

原文地址:https://www.cnblogs.com/bwangel/p/3793237.html