一、Crud复习
// 首先创建一个上下文: BlogDBEntities blog = new BlogDBEntities(); //增加 UserState user = new UserState();
user.name = "失效"; blog.UserState.Add(user); //修改 UserState state = (from s in blog.UserState where s.id == 1 select s).FirstOrDefault(); state.name = "修改"; //当然也可以这样写 blog.UserState.Attach(state); blog.Entry(state).State = System.Data.EntityState.Modified; //删除 blog.UserState.Remove(state); //查询 //使用lambda表达式查询单个对象 UserState u = blog.UserState.Where(s => s.id == 1).FirstOrDefault(); //查询全部对象 IQueryable<UserState> userStates = blog.UserState; //使用Linq查询单个对象 var states = from state in blog.UserState where state.id == 2 select state; //查询全部 IQueryable<UserState> userState=from state in blog.UserState select state;
二、EF延迟加载
延迟加载:只在需要的时候加载数据,不需要预先计划,避免了各种复杂的外连接、索引、视图操作带来的低效率问题
延迟加载原因:IQueryable这个接口是造成延迟加载的原因。接口里面的三个属性:
Type ElementType { get; } 、Expression Expression { get; }、IQueryProvider Provider { get; }
Expression:一个表达式,会存储拼接表达式树,直到在运行期最终执行。那么在EF中我们根据条件查询数据时,不应该把数据一次性加载到本地内存中,然后再本地内存中进行筛选,如果数据量大了,就崩溃了。我们需要将表达式组合好,然后再一起提交到数据库执行,返回查询结果。
(每次在执行where查询操作符的时候IQueryProvider会为我们创建一个新的IQueryable<T>,调用AsEnumerable()方法的时候并不会去实际取值,只是
得到了一个IEnumerable,所以EF在查询数据时候不要先取IEnumerable再去筛选数据。执行ToList方法时才会去真正调用迭代器GetEnumerator()
取值。真正取值时候,会去执行IQueryProvider中的Excute方法.(解析表达式,然后执行取得结果))
第一种延迟加载:
IQueryable < UserState > userStates = blog.UserState;//因为使用IQueryable接口的缘故,所以此处延迟加载,执行完这行代码后userStates里面并没有返回的结果集 foreach (var item in userStates)//编译器执行到in这个地方的时候才将结果集赋值给userStates { Console.WriteLine(item.id + "状态:" + item.name + " 有" + item.UserInfo.Count + "人"); //item.UserInfo.Count:为什么会得到UserInfo的数据呢?这就是第二种延迟加载情况了 }
第二种延迟加载:
就像上面的item.UserInfo.Count能获取到UserInfo中的信息,虽然说我们Linq表达式中并未查询Order表中的数据,但是当执行到这个地方的时候,EF会自动为我们去查询。
延迟加载的优点与缺点:
优点:只在需要的时候加载数据,不需要预先计划,避免了各种复杂的外连接、索引、视图操作带来的低效率问题。
缺点:多次与数据库进行交互,性能降低,无法实现Web中的缓存。
三、EF贪婪加载
贪婪加载:就是把所有的数据直接加载出来
List<UserState> userState=(from s in UserStateselect s).ToList();
优点以及缺点:
优点:减少数据访问的延迟,在一次数据库的访问中返回所有的数据。
缺点:一次性读取所有相关的数据,可能导致部分数据实际无需用到,从而导致读取数据的速度变慢,效率变低
注:以上代码使用的是EF5.0