当前手头的项目又是LINQ、又是EF、又是MVC的,把我这样的菜鸟搞的晕头转向。前两天终于有了点空闲时间,便花了点解决了一个存在心中许久的疑问:EF到底在什么时候向数据库递交了查询?现在来分享一下我的小收获。
我为什么会产生的这样的疑问:
以SQL自带的数据库NorthWind和简单的ASP.NET网站程序为例,先新建一个默认的ASP.NET网站,然后在项目中添加 ADO.NET Entity Data Model,并且在向导中选择orders和order_details两张表。完成后在默认的页面Default.aspx添加一个gridview并敲入如下代码。
protected void Page_Load(object sender, EventArgs e)
{
NorthwindModel.NorthwindEntities ne = new NorthwindModel.NorthwindEntities();
GridView1.DataSource = ne.Orders;
GridView1.DataBind();
}
运行程序,简单的3句话,完成了数据库的连接、查询、绑定。就这样的3句代码“EF到底在什么时候向数据库递交了查询?”这个问题似乎没有去追寻的必要。然而在具体的系统中,因为在系统架构下代码的层层封装,对我这样的新手来说事情就不是那么简单了。另外,我们强大的VS这个IDE也增加了我的疑惑。
比如关闭程序,然后在第一句代码前面打上断点,程序运行,程序停下后按F10,此时只执行了第1句代码,然后把鼠标移到ne这个变量上,此时应该出现那个“树形菜单”(不知道叫什么名字。。。囧),然后我惊奇的发现,此时在ne的两个属性orders和order_details中已经可以看到他们的所有在数据库中的数据。我不禁疑惑?难道EF此时就取到数据了,并且还是所有的表的所有行!我想肯定不是这样的,如果是的话,EF是没人会去用了。
SQl中的事件探查器
带着这个疑问,我在CSDN上发了一个帖子“如何监视或者得到程序与SQL数据库的通讯信息”,然后有人推荐了 sql server profiler。在SQL2000中,叫事件探查器,就在查询分析器的下面(这么显眼的位置,我居然从没去关注它,哎)。
打开时间探查器,新建“跟踪”,连接数据库实例(刚才的NorthWind所属数据库)。然后当我们的程序访问数据库的时候,事件探查器中就会记录下访问的具体信息,比如访问时间,执行的查询语句,进程ID等等。
接下来关闭正在运行的网站程序,更改为如下代码,并且在第一句打上断点。
NorthwindModel.NorthwindEntities ne = new NorthwindModel.NorthwindEntities();
var result = from p in ne.Orders where p.EmployeeID == 1 select p;
GridView1.DataSource = result ;
GridView1.DataBind();
运行程序,在程序停止执行后,我们一直按F10运行,
第一句代码执行后,我们发现程序并没有向数据库递交查询,那么更没有去取所有的表数据。
第二句代码执行后,程序依然没有向数据库递交查询,这里就有点意思了,这说明我们只写了一个查询语句,而没有向数据库提交,那么我们也就可以在下面的语句更改这个查询语句。
第三句代码执行后,我原本猜想到这里应该提交了吧,没想到,在这里还是没有提交。
最后一句代码执行,这下终于提交了。
这样看来:EF只有在数据真正需要取出,赋给其他对象的时候,才会去数据库提交查询。
强大的VS
那么:对另一个疑问,在第一句代码执行后ne变量中能取到所有表的数据,就很容易理解了,那都是VS的功劳,是VS在我们展开ne变量属性值的时候向数据库递交了查询,而非我们自己写的程序。
因为一个疑问,我了解了事件探查器,了解了不少东西。从事件探查器的功能来看,用它来优化网站程序会是不错的工具。