請注明轉載地址:http://www.cnblogs.com/arhat
從本章開始,老魏就介紹一下Entity Framework使用Linq來查詢數據,也就是Linq To Entity。其實在Entity Framework中提供了3中查詢方式,除了使用Linq還有Lambda表達式,EQL語句,其中EQL是用於復雜的查詢,當Linq無法勝任的時候就要使用了EQL了,當然也可以使用存儲過程。廢話不多說,開始本章的內容。
在本章中查詢的依然是Student和Clazz兩張表,主要涉及到是單表查詢和一個關聯查詢,對於多對多查詢將在下一章講解。
Demo1:查詢一下全部學生的信息。
原生SQL:
select * from Student
Linq:
DAL.SchoolContext context = new DAL.SchoolContext(); var query = from student in context.Student select student; foreach (var student in query) { Console.WriteLine(student.SId + "----" + student.SName + "----" + student.SAge + "----" + student.SMail); }
翻譯SQL:
SELECT [Extent1].[SId] AS [SId], [Extent1].[SName] AS [SName], [Extent1].[SAge] AS [SAge], [Extent1].[SMail] AS [SMail], [Extent1].[CId] AS [CId] FROM [dbo].[Student] AS [Extent1]
結果:
大家看到這個Linq翻譯的SQL語句還是非常不錯的。並沒有額外的開支。
Demo2:查詢一下全部學生的信息,並顯示學生所在的班級信息。
原生SQL:
select * from Student as a inner join Clazz as b on a.CId= b.CId
Linq:
DAL.SchoolContext context = new DAL.SchoolContext(); var query = from student in context.Student select student; foreach (var student in query) { Console.WriteLine(student.SId + "----" + student.SName + "----" + student.SAge + "----" + student.SMail+"----班級信息:"+student.Clazz.CId+"----"+student.Clazz.CName); }
翻譯SQL:這個老魏就不貼出來了,太長了,大家可以看看
從圖上可以看出,這個Linq執行的時候是先把學生全部查詢出來,然后在根據Student.CId字段分別取得到Clazz信息,如果我們的信息有100000條數據的話,可想而知了。雖然犧牲了性能,但卻換來了編程上的方便。如果大家思考一下老魏的這程序,會發現項目中沒有這么干的,如果數據多的請情況下肯定要使用分頁的,如果使用分頁的話,那么產生的SQL查詢次數肯定要比全部的少很多,的確如此,但是還是多了。其實這也沒有辦法,在所有的ORM框架中使用懶加載的時候都是如此,犧牲效率。
在這里呢,Entity Framework是默認啟用懶加載機制的,所謂的懶加載老魏在NHibernate中已經講解過了,其實就是在使用的時候在向SQL發送查詢指令。這里我們通過Student的Clazz導航屬性來得到班級的信息。當然如果我們不需班級信息的話,那么就不會向SQL發送指令了。
結果:
此時呢,我們在換一種寫法,不使用懶加載,而是通過Linq的join語句來試試看看。
Linq:
DAL.SchoolContext context = new DAL.SchoolContext(); var query = from student in context.Student join clazz in context.Clazz on student.CId equals clazz.CId select new { SName =student.SName, CName = clazz.CName }; foreach (var record in query) { Console.WriteLine(record.SName + "----" + record.CName); }
翻譯SQL:
SELECT [Extent2].[CId] AS [CId], [Extent1].[SName] AS [SName], [Extent2].[CName] AS [CName] FROM [dbo].[Student] AS [Extent1] INNER JOIN [dbo].[Clazz] AS [Extent2] ON [Extent1].[CId] = [Extent2].[CId]
這個時候,我們發現了,這個Linq生成的SQL語句還真是我們想要的語句,直接把我們想要的東西通過inner join來查詢出來了,可是隨之的問題有出現了,為什么呢?如果我們要分層的開發項目,這段代碼應該是在DAL層中的,但是此時我們用了匿名對象來保存我們的查詢結果,而匿名對象是不能跨域訪問的,這該怎么辦呢?這里呢老魏也沒想到好的方法,但是提供兩個參考
1,使用擴展防方法給IEnumable<T>擴展一個方法,優點復雜老魏不喜歡
2,使用.net4.0的dynamic關鍵字,雖然可以實現,但是沒有智能提示,不過勉強接受。
static void Main(string[] args) { var query = Test(); foreach (dynamic d in query) { Console.WriteLine(d.SName + "----" + d.CName); } } public static dynamic Test() { DAL.SchoolContext context = new DAL.SchoolContext(); var query = from student in context.Student join clazz in context.Clazz on student.CId equals clazz.CId select new { SName = student.SName, CName = clazz.CName }; return query as dynamic; }
誰有好的方法可以共享一下,老魏這里實在是想不到一個好的方法了。好了,不在這個問題上過多的糾纏了。
可能看到這里我們有會忽然間想到,如果我們不查詢部分字段那又是什么情況呢?
Linq:
DAL.SchoolContext context = new DAL.SchoolContext(); var query = from student in context.Student join clazz in context.Clazz on student.CId equals clazz.CId into Rows from row in Rows select row; foreach (var row in query) { Console.WriteLine(row.CName); }
當我們寫到row.的時候,會發現row這個對象中只有CId,CName和一個奇怪的Students對象。這是怎么回事啊。我們通過這條Linq語句生成的SQL語句可以看出端倪。
翻譯SQL:
SELECT [Extent2].[CId] AS [CId], [Extent2].[CName] AS [CName] FROM [dbo].[Student] AS [Extent1] INNER JOIN [dbo].[Clazz] AS [Extent2] ON [Extent1].[CId] = [Extent2].[CId]
大家從翻譯的SQL中可以看到最終查詢的結果是是吧Clazz的字段全部查詢出來了,查詢結果如下:
每一個課程都有一個Student對象,那么當然在Clazz中有一個Students對象。只有當我們查詢Student對象的時候,才會向SQL依次的發送指令。其實還是懶加載,。看到這里我們是不是相到既然這樣我們可以關閉懶加載啊,是的,可以的沒有任何的問題,我們在上面的代碼中我們加入一句話。
DAL.SchoolContext context = new DAL.SchoolContext(); //取消懶加載 context.Configuration.LazyLoadingEnabled = false; var query = from student in context.Student join clazz in context.Clazz on student.CId equals clazz.CId into Rows from row in Rows select row; foreach (var row in query) { Console.WriteLine(row.CName+",次班級的人數:"+row.Students.Count); }
運行結果:
發現人數打印出來是0,因為我們取消了懶加載,所以在使用到了Student的時候不會向SQL發送指令,就不會查詢人數了,但是從上圖中其實我們看出來總的記錄加起來還是人數哦!
本章就先到這里吧,雖然本章只涉及到了2個查詢,但還是有收貨的,值得在我們學習Entity Framework的時候多深入的思考一下。






