zoukankan      html  css  js  c++  java
  • 测试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。

  • 相关阅读:
    C#学习记录(一)
    C#学习记录(五)第一次上机实验
    C#学习记录(四)
    C#学习记录(三)
    统计代码行数
    夜深了
    写在岁末的烟花易冷
    c语言|博客作业02
    c语言I博客作业03
    设计模式之模板方法模式
  • 原文地址:https://www.cnblogs.com/bwangel/p/3793237.html
Copyright © 2011-2022 走看看