Entity Framework學習筆記(四)----Linq查詢(1)


請注明轉載地址: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]

結果:

wps_clip_image-12154

大家看到這個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:這個老魏就不貼出來了,太長了,大家可以看看

wps_clip_image-5241

從圖上可以看出,這個Linq執行的時候是先把學生全部查詢出來,然后在根據Student.CId字段分別取得到Clazz信息,如果我們的信息有100000條數據的話,可想而知了。雖然犧牲了性能,但卻換來了編程上的方便。如果大家思考一下老魏的這程序,會發現項目中沒有這么干的,如果數據多的請情況下肯定要使用分頁的,如果使用分頁的話,那么產生的SQL查詢次數肯定要比全部的少很多,的確如此,但是還是多了。其實這也沒有辦法,在所有的ORM框架中使用懶加載的時候都是如此,犧牲效率。

在這里呢,Entity Framework是默認啟用懶加載機制的,所謂的懶加載老魏在NHibernate中已經講解過了,其實就是在使用的時候在向SQL發送查詢指令。這里我們通過Student的Clazz導航屬性來得到班級的信息。當然如果我們不需班級信息的話,那么就不會向SQL發送指令了。

結果:

wps_clip_image-25654

此時呢,我們在換一種寫法,不使用懶加載,而是通過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]

wps_clip_image-30143

大家從翻譯的SQL中可以看到最終查詢的結果是是吧Clazz的字段全部查詢出來了,查詢結果如下:

wps_clip_image-2067

每一個課程都有一個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);

 }

運行結果:

wps_clip_image-24764

發現人數打印出來是0,因為我們取消了懶加載,所以在使用到了Student的時候不會向SQL發送指令,就不會查詢人數了,但是從上圖中其實我們看出來總的記錄加起來還是人數哦!

本章就先到這里吧,雖然本章只涉及到了2個查詢,但還是有收貨的,值得在我們學習Entity Framework的時候多深入的思考一下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM