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