none
关于Entity Framework的性能疑问 RRS feed

  • 问题

  • 之前看到网上有赞EF4的性能在大量查询时性能优于ADO.NET

    然后今天做了一个简单的测试,测试结果如下:

    重复50次操作:

    使用EF操作:(单位:ms,循环3次)

    Add:795 Query:519 update:600 delete:230

    Add:225 Query 350  update:575 delete:225

    Add:225 Query:250 update 760 delete:250

    使用ADO.NET:

    Add:165 Query:155 update:160 delete:155

    Add:165 Query:160 update:155 delete:160

    Add:165 Query:165 update:155 delete:155

    然后执行5000次

    EF:

    Add:23524 Query:35611 update:58852 delete:23100

    Add:23882 Query:35690 update:57898 delete:23065

    Add:23827 Query:35845 update:59306 delete:23217

    ADO.Net:

    Add:17045 Query:15937 update:16207 delete:16197

    Add:17460 Query:15952 update:15665 delete:15955

    Add:17277 Query:18183 update:15935 delete:16890

    通过以上测试。似乎EF的性能并没有所介绍的那么好。而且其性能和Linq-To-Sql相似。这是为什么呢?

    附上测试代码(本代码测试3种方式。而且循环更多次):

     int exenum = 50;
    
       for (var y = 0; y < 3; y++)
    
       {
    
        Console.WriteLine("执行" + exenum + "次");
    
        Console.WriteLine("Opertion by EF4");
    
        for (var x = 0; x < 5; x++)
    
        {
    
         DateTime query, add, delete, update;
    
         
    
         add = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var ctx = new Test.EF.sq_sinospacedbEntities())
    
          {
    
           var item = new Test.EF.testtable()
    
           {
    
            content = "啊啊啊啊啊啊啊啊啊啊啊",
    
            summary = "啊飒飒飒飒",
    
            m_id = 1,
    
            title = "啊飒飒飒",
    
            id = i
    
           };
    
           ctx.testtable.AddObject(item);
    
           ctx.SaveChanges();
    
          }
    
         }
    
         var _add = DateTime.Now;
    
         Console.Write(String.Format(" Add:{0}", _add.Subtract(add).Minutes * 60 * 1000 + _add.Subtract(add).Seconds * 1000 + _add.Subtract(add).Milliseconds));
    
         /*------------------------------------------*/
    
         query = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var ctx = new Test.EF.sq_sinospacedbEntities())
    
          {
    
           var items = ctx.testtable
    
            .FirstOrDefault(c => c.id == i);
    
          }
    
         }
    
         var _query = DateTime.Now;
    
         Console.Write(String.Format(" Query:{0}", _query.Subtract(query).Minutes * 60 * 1000 + _query.Subtract(query).Seconds * 1000 + _query.Subtract(query).Milliseconds));
    
         
    
         /*--------------------------------------------*/
    
         update = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var ctx = new Test.EF.sq_sinospacedbEntities())
    
          {
    
           ctx.testtable.Single(c => c.id == i).title = "巴巴变版本";
    
           ctx.SaveChanges();
    
          }
    
         }
    
         var _update = DateTime.Now;
    
         Console.Write(String.Format(" update:{0}", _update.Subtract(update).Minutes * 60 * 1000 + _update.Subtract(update).Seconds * 1000 + _update.Subtract(update).Milliseconds));
    
         /*--------------------------------------------*/
    
         delete = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          var deleteitem = new Test.EF.testtable()
    
          {
    
           id = i
    
          };
    
          using (var ctx = new Test.EF.sq_sinospacedbEntities())
    
          {
    
           ctx.testtable.Attach(deleteitem);
    
           ctx.ObjectStateManager.ChangeObjectState(deleteitem,
    
             System.Data.EntityState.Deleted);
    
           ctx.SaveChanges();
    
          }
    
         }
    
         var _delete = DateTime.Now;
    
         Console.Write(String.Format(" delete:{0}", _delete.Subtract(delete).Minutes * 60 * 1000 + _delete.Subtract(delete).Seconds * 1000 + _delete.Subtract(delete).Milliseconds));
    
    
    
         Console.WriteLine();
    
        }
    
        /*---------------LinqToSql--------------------*/
    
        Console.WriteLine("Opertion by LinqToSql");
    
        for (var x = 0; x < 5; x++)
    
        {
    
         DateTime query, add, delete, update;
    
         add = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var ctx = new Test.LinqToSql.LinqTestContextDataContext())
    
          {
    
           var item = new Test.LinqToSql.testtable()
    
           {
    
            content = "啊啊啊啊啊啊啊啊啊啊啊",
    
            summary = "啊飒飒飒飒",
    
            m_id = 1,
    
            title = "啊飒飒飒",
    
            id = i
    
           };
    
           ctx.testtable.InsertOnSubmit(item);
    
           ctx.SubmitChanges();
    
          }
    
         }
    
         var _add = DateTime.Now;
    
         Console.Write(String.Format(" Add:{0}", _add.Subtract(add).Minutes * 60 * 1000 + _add.Subtract(add).Seconds * 1000 + _add.Subtract(add).Milliseconds));
    
         /*--------------------------------------------*/
    
         query = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var ctx = new Test.LinqToSql.LinqTestContextDataContext())
    
          {
    
           var items = ctx.testtable
    
            .FirstOrDefault(c => c.id == i);
    
          }
    
         }
    
         var _query = DateTime.Now;
    
         Console.Write(String.Format(" Query:{0}", _query.Subtract(query).Minutes * 60 * 1000 + _query.Subtract(query).Seconds * 1000 + _query.Subtract(query).Milliseconds));
    
         /*------------------------------------------*/
    
         update = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var ctx = new Test.EF.sq_sinospacedbEntities())
    
          {
    
           ctx.testtable.Single(c => c.id == i).title = "巴巴变版本";
    
           ctx.SaveChanges();
    
          }
    
         }
    
         var _update = DateTime.Now;
    
         Console.Write(String.Format(" update:{0}", _update.Subtract(update).Minutes * 60 * 1000 + _update.Subtract(update).Seconds * 1000 + _update.Subtract(update).Milliseconds));
    
         /*--------------------------------------------*/
    
         delete = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          //var deleteitem = new Test.LinqToSql.LinqTestContextDataContext()
    
          //{
    
          // id = i
    
          //};
    
          using (var ctx = new Test.LinqToSql.LinqTestContextDataContext())
    
          {
    
           ctx.testtable.DeleteOnSubmit(
    
            ctx.testtable.Single(c => c.id == i));
    
           ctx.SubmitChanges();
    
          }
    
         }
    
         var _delete = DateTime.Now;
    
         Console.Write(String.Format(" delete:{0}", _delete.Subtract(delete).Minutes * 60 * 1000 + _delete.Subtract(delete).Seconds * 1000 + _delete.Subtract(delete).Milliseconds));
    
         Console.WriteLine();
    
        }
    
        /*---------------SQLClient--------------------*/
    
        Console.WriteLine("Option by ADO.NET");
    
        for (int x = 0; x < 5; x++)
    
        {
    
         DateTime query, add, delete, update;
    
         add = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var con = new SqlConnection("Data Source=.;Initial Catalog=sq_sinospacedb;Persist Security Info=True;User ID=hugo;Password=MYvalentinE;"))
    
          {
    
           SqlCommand com = new System.Data.SqlClient.SqlCommand(
    
            "insert into testtable values('" + i + "','啊飒飒飒','啊飒飒飒飒','啊啊啊啊啊啊啊啊啊啊啊',1)", con);
    
           con.Open();
    
           com.ExecuteNonQuery();
    
           con.Close();
    
          }
    
         }
    
         var _add = DateTime.Now;
    
         Console.Write(String.Format(" Add:{0}", _add.Subtract(add).Minutes * 60 * 1000 + _add.Subtract(add).Seconds * 1000 + _add.Subtract(add).Milliseconds));
    
         query = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var con = new SqlConnection("Data Source=.;Initial Catalog=sq_sinospacedb;Persist Security Info=True;User ID=hugo;Password=MYvalentinE;"))
    
          {
    
           SqlDataAdapter da = new System.Data.SqlClient.SqlDataAdapter(
    
            "select * from testtable where id=" + i, con);
    
           DataSet ds = new DataSet();
    
           con.Open();
    
           da.Fill(ds);
    
          }
    
         }
    
         var _query = DateTime.Now;
    
         Console.Write(String.Format(" Query:{0}", _query.Subtract(query).Minutes * 60 * 1000 + _query.Subtract(query).Seconds * 1000 + _query.Subtract(query).Milliseconds));
    
    
    
         update = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var con = new SqlConnection("Data Source=.;Initial Catalog=sq_sinospacedb;Persist Security Info=True;User ID=hugo;Password=MYvalentinE;"))
    
          {
    
           SqlCommand com = new System.Data.SqlClient.SqlCommand(
    
            "update testtable set title='巴巴变版本' where id=" + i, con);
    
           con.Open();
    
           com.ExecuteNonQuery();
    
           con.Close();
    
          }
    
         }
    
         var _update = DateTime.Now;
    
         Console.Write(String.Format(" update:{0}", _update.Subtract(update).Minutes * 60 * 1000 + _update.Subtract(update).Seconds * 1000 + _update.Subtract(update).Milliseconds));
    
    
    
         delete = DateTime.Now;
    
         for (var i = 0; i < exenum; i++)
    
         {
    
          using (var con = new SqlConnection("Data Source=.;Initial Catalog=sq_sinospacedb;Persist Security Info=True;User ID=hugo;Password=MYvalentinE;"))
    
          {
    
           SqlCommand com = new System.Data.SqlClient.SqlCommand(
    
            "delete testtable where id=" + i, con);
    
           con.Open();
    
           com.ExecuteNonQuery();
    
           con.Close();
    
          }
    
         }
    
         var _delete = DateTime.Now;
    
         Console.Write(String.Format(" delete:{0}", _delete.Subtract(delete).Minutes * 60 * 1000 + _delete.Subtract(delete).Seconds * 1000 + _delete.Subtract(delete).Milliseconds));
    
         Console.WriteLine();
    
        }
    
    
    
        exenum = exenum * 10;
    
    
    
       }
    
       Console.ReadKey();
    
      }
    
    

    郭鹏
    2010年8月28日 9:51

答案

  • Entity Framework是ADO.Net的一部分,不知道你这里怎么把Entity Framework和ADO.Net比较的。



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    • 已标记为答案 Hugo12345 2010年9月9日 2:32
    2010年8月31日 1:12
    版主

全部回复

  • 你先了解.net整个历史来源 linq to sql是3.5加入的 entity是3.5 sp1加入的 linq to sql 已经被微软抛弃了 又名叫entity 重新设计一个服务框架 ado.net linq是个组件 算不上框架
    77138191qq群 .net与asp.net
    2010年8月30日 10:35
  • Entity Framework是ADO.Net的一部分,不知道你这里怎么把Entity Framework和ADO.Net比较的。



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    • 已标记为答案 Hugo12345 2010年9月9日 2:32
    2010年8月31日 1:12
    版主
  • 不用说“Entity Framework是ADO.Net的一部分”,也不说“怎么把Entity Framework和ADO.Net比较”,这回答有意义吗,就谈这两者最终的目的的“增删改”操作,为什么相差这么多!
    2011年1月12日 16:01
  • 不用说“Entity Framework是ADO.Net的一部分”,也不说“怎么把Entity Framework和ADO.Net比较”,这回答有意义吗,就谈这两者最终的目的的“增删改”操作,为什么相差这么多!

    因为LZ的这个测试本身就写得不怎么样。
    2011年1月12日 16:44
  • 不用说“Entity Framework是ADO.Net的一部分”,也不说“怎么把Entity Framework和ADO.Net比较”,这回答有意义吗,就谈这两者最终的目的的“增删改”操作,为什么相差这么多!

    因为LZ的这个测试本身就写得不怎么样。
    好吧,你的意思是测试代码的原因!那么假设它测试代码写的“挺像样的”,针对“增删改”操作,会不会出现性能问题?为什么存在性能上的些许差异(大或小)? 怎么改善?这些是大家关心的好吧,别总跑踢为了回复而回复!
    2011年1月13日 15:44
  • Entity Framework功能不同,比如跟踪对象的变化以生成优化的SQL这功能简单说就是用应用服务器的性能换数据库服务器的性能,是不是造成问题得看具体数据。

    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2011年1月13日 16:50
    版主
  • 用ENTITY FRAMEWORK有几个问题

    1、如果你的表很多,那么entities会很大。new一次要好几秒(150张表大概8秒左右)。如果你把他拆分成几个ENTITES那么在使用时会出来类型匹配问题。比如在A程序集的YH做为参数给B程序集中的YH时会出问题。

    2、复杂查询非常糟糕。比如ANY

    3、第一次SAVE会有明显等待。(可能是因我表多了?)

    3、如果你的SELECT 比较简单可以考虑用。否则会无法忍受

    优点也很明显:关联数据的修改很简单,数据状态是系统维护的。比如常见的主从表新建保存,假如你原来从表中有的PARENTID关联主表的ID(标识列),那用传统方法必须要先保存主表,取得ID再把ID给从表所有行的PARENTID列,然后保存从表。而用ENTITY  FRAMEWORK就不用了

    2011年2月13日 4:36
  • 您好,我对您的“

    优点也很明显:关联数据的修改很简单,数据状态是系统维护的。比如常见的主从表新建保存,假如你原来从表中有的PARENTID关联主表的ID(标识列),那用传统方法必须要先保存主表,取得ID再把ID给从表所有行的PARENTID列,然后保存从表。而用ENTITY  FRAMEWORK就不用了

    ”这一段很感兴趣。最近项目中用到了EF的相关知识,并且也应用到了主从表新建保存,我用的是您所说的传统方法,可是当数据量比较的多的时候,在调用SaveChanges()方法时总是会报异常,想请教您,若不用传统的方法,EF中有更好的处理方式吗?等待您的解答

    2011年12月19日 8:08
  • 用ENTITY FRAMEWORK有几个问题

    1、如果你的表很多,那么entities会很大。new一次要好几秒(150张表大概8秒左右)。如果你把他拆分成几个ENTITES那么在使用时会出来类型匹配问题。比如在A程序集的YH做为参数给B程序集中的YH时会出问题。

    2、复杂查询非常糟糕。比如ANY

    3、第一次SAVE会有明显等待。(可能是因我表多了?)

    3、如果你的SELECT 比较简单可以考虑用。否则会无法忍受

    优点也很明显:关联数据的修改很简单,数据状态是系统维护的。比如常见的主从表新建保存,假如你原来从表中有的PARENTID关联主表的ID(标识列),那用传统方法必须要先保存主表,取得ID再把ID给从表所有行的PARENTID列,然后保存从表。而用ENTITY  FRAMEWORK就不用了

    您好,我对您的“

    优点也很明显:关联数据的修改很简单,数据状态是系统维护的。比如常见的主从表新建保存,假如你原来从表中有的PARENTID关联主表的ID(标识列),那用传统方法必须要先保存主表,取得ID再把ID给从表所有行的PARENTID列,然后保存从表。而用ENTITY  FRAMEWORK就不用了

    ”这一段很感兴趣。最近项目中用到了EF的相关知识,并且也应用到了主从表新建保存,我用的是您所说的传统方法,可是当数据量比较的多的时候,在调用SaveChanges()方法时总是会报异常,想请教您,若不用传统的方法,EF中有更好的处理方式吗?等待您的解答


    2011年12月19日 8:09