davin

Just a little thinking and interest!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  53 随笔 :: 8 文章 :: 127 评论 :: 13万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

   一直在想,在EF中,存储过程究竟能为我们在应用中做些什么呢?
  .sp的执行效率
    在之前看到过ado.net team 关于EF的性能分析报告以及linq to entity,esql,sql的性能比较,
     ADO.NET Entity Framework Performance Comparison

    exploring-the-performance-of-the-ado-net-entity-framework-part-1.aspx
    exploring-the-performance-of-the-ado-net-entity-framework-part-2.aspx
    在文章的评论中我看到了许多肯定和宽容.在其中也有关于询问存储过程的性能情况.于是在前些天我对存储过程sp和linq to entity 做了一点比较,具体的做法是利用sp和linq to entity查询OrderID为10248的order对象比较重复执行100次的时间.调用存储过程的测试代码:
            using (NorthwindEFEntities context = new NorthwindEFEntities())
            {
                start = DateTime.Now;
                for (int i = 0; i < 100; i++)
                {
                    Orders order = context.GetOrder(10248);//a single entity order with part property                      }
                end = DateTime.Now;
                usage = end - start;
                Console.WriteLine("sp query with all properties 100 time's usage:{0} Milliseconds", usage.Milliseconds);

            } 
      在第一次测试时使用了187ms,之后的几次测试时间均为171ms.
      linq to entity 的测试代码:
     using (NorthwindEFEntities context = new NorthwindEFEntities())
            {
                start = DateTime.Now;
                for (int i = 0; i < 100; i++)
                {
                    Orders order = context.Orders.Where(q => q.OrderID == 10248).FirstOrDefault<Orders>();
                }
                end = DateTime.Now;
                usage = end - start;
                Console.WriteLine("linq to entity  query 100 time's usage:{0} Milliseconds", usage.Milliseconds);
            }
     在第一次测试时使用的时间是859ms,之后的几次测试时间均为843ms.想比较之下存储过程现在性能还是很明显的,无论是linq to sql,esql还是linq to entity都需要被解释,然后生成相应的sql.在EF中使用存储过程毕竟是直接使用sql.

  .解决大实体(大数据)的问题
    在oo中对于大数据的处理成为一个令人头疼的问题,因为相比较而言,对大数据的操作,更容易成为整个应用程序性能上的瓶颈.一个在业务中表现繁重(访问频率高)的而又极其重要的实体对象   在应用程序的业务处理中并不是在每一次操作时都需要处理每一个属性,而是在不同的应用模块处理某一些属性,因此对于这种场景,我们为了处理某一些属性而将频繁地将整个对象从数据库取出,显然是种浪费的行为,EF也无法避免这种情况.在我参与的项目中就有这种问题,一个业务很重的实体对象有100多个属性+20几个关联对象,好在EF并不允许隐式加载关联对象的行为,否则每次取出一个该实体对象是一个多么庞杂的行为.不过在之前的做关于EF Extension的练习时,我就在考虑使用sp或许能解决这一问题,sp返回需要处理的属性,通过具体化(Materializer)之后的结果就是,取出我们需要关注的属性,不需要关注的属性则为空.为了证实这种想法的可能性我还做了一个测试:取出order的5个属性
private static readonly Materializer<Orders> s_orderMaterializer = new Materializer<Orders>(r =>
            new Orders
            {
                OrderID = r.Field<int>("OrderID"),
                EmployeeID = r.Field<int>("EmployeeID"),
                OrderDate = r.Field<DateTime>("OrderDate"),
                ShipCity = r.Field<string>("ShipCity"),
                ShipRegion = r.Field<string>("ShipRegion"),

            });
       private static readonly Materializer<Orders> _orderMaterializer = new Materializer<Orders>(r =>
          new Orders
          {
              OrderID = r.Field<int>("OrderID"),
              EmployeeID = r.Field<int>("EmployeeID"),
              OrderDate = r.Field<DateTime>("OrderDate"),
              RequiredDate = r.Field<DateTime>("RequiredDate"),
              ShippedDate = r.Field<DateTime>("ShippedDate"),
              Freight = r.Field<decimal>("Freight"),
              ShipName = r.Field<string>("ShipName"),
              ShipAddress = r.Field<string>("ShipAddress"),
              ShipCity = r.Field<string>("ShipCity"),
              ShipRegion = r.Field<string>("ShipRegion"),
              ShipPostalCode = r.Field<string>("ShipPostalCode"),
              ShipCountry = r.Field<string>("ShipCountry")
          });
         下面则是对上面扩展代码的测试代码:       

复制代码
 1 Orders order = context.GetOrder(10248);
 2                 System.Reflection.PropertyInfo[] properties = typeof(Orders).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
 3 
 4                 foreach (var pro in properties)
 5                 {
 6                     object o = pro.GetValue(order, null);
 7                     if (o != null)
 8                         Console.WriteLine("{0}:{1}", pro.Name, o.ToString());
 9                     else
10                         Console.WriteLine("{0}:{1}", pro.Name, null);
11                 }
12                 context.Detach(order);
13                 Console.WriteLine();
14                 Orders order1 = context.GetOrder1(10248);
15                 System.Reflection.PropertyInfo[] properties1 = typeof(Orders).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly);
16 
17                 foreach (var pro in properties1)
18                 {
19                     object o = pro.GetValue(order1, null);
20                     if (o != null)
21                         Console.WriteLine("{0}:{1}", pro.Name, o.ToString());
22                     else
23                         Console.WriteLine("{0}:{1}", pro.Name, null);
24 
25                 }
26 
复制代码

    以上2方式的性能做了对比,同样是重复100次的结果显示用sp取出所有属性,第一次测试时间为187ms,之后的测试为171ms,取出部分属性(5个属性)第一次为173ms,之后测试结果为156ms.效果不是明显,也许是order实体还算不上是大数据,属性不够多优势不能被充分体现.或许在edm中sp给我们带来的远远不止这些。
(以上均为个人的一点猜想)

posted on   davin  阅读(5944)  评论(13编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端
点击右上角即可分享
微信分享提示