LINQ学习之旅——第二站LTQ之标准数据库操作(增查删改)
今天要講解主要內容是關于LINQ TO SQL中的標準數據庫操作:插入(Insert)、查詢(Select)、更新(Update)以及刪除(Delete),凡是涉及到數據庫方面的都會使用這些操作。而這些操作對大家來說是再熟悉不過了,所以這節內容在理解上沒有任何困難。下面就來講解一下這四個操作在LINQ TO SQL中的應用。
在介紹四個操作內容之前,先來簡單說一下泛型接口IQueryable<T>。LINQ TO SQL的大部分從操作符都是作為該接口的擴展方法。因為LINQ TO SQL中使用了大量表達式樹,為了實現表達式樹的運行時編譯優化功能,被操作對象必須暴露更多額外的信息,而繼承泛型接口IEnumerable<T>的IQUeryable<T>泛型接口提供了足夠的信息使能夠滿足LINQ TO SQL的即時優化編譯要求。下面介紹四個標準數據庫操作:
1.插入操作:
在LINQ TO SQL中的插入操作其實非常簡單,在上一節DataContext對象詳解的示例代碼中就提到過,新建一個實體類對象,然后把實體類對象添加入DataContext類的成員方法GetTable返回的一個Table<T>的集合中,或添加到類型為EntitySet<T>的集合中,其中的T代表實體類,最后調用DataContext對象的SubmitChanges方法,提交新增結果給數據庫。下面是兩個關于插入操作的示例(注:本文中所涉及到的Student、Course以及Student_Course實體類請參考對象——關心映射的內容 ):
i.普通插入:
普通插入 1 string str_sql ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc =new DataContext(str_sql);
3
4 //實例化實體類對象
5 Student newstudent =new Student()
6 {
7 No ="20030012",
8 Name ="古箏",
9 Dept ="表演系",
10 Age =23,
11 Sex ="女"
12 };
13
14 //將對象添加到Table<T>
15 dc.GetTable<Student>().InsertOnSubmit(newstudent);
16
17 //提交
18 dc.SubmitChanges();
ii.結果(物理表student):
i.一對多關系插入:
一對多關系插入 1 string str_sql ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc =new DataContext(str_sql);
3
4 //實例化實體類對象
5 Course newcourse =new Course()
6 {
7 No ="ky030011",
8 Name ="聲樂與語言發音",
9 Credit=5,
10 };
11
12 var student=dc.GetTable<Student>().Where(s=>s.No=="20030012").Single();
13 //實例化實體類對象
14 Student_Course sc =new Student_Course()
15 {
16 Cno = newcourse.No,
17 Sno = student.No,
18 Grade =95,
19 };
20
21 newcourse.Students.Add(sc);
22
23 //將對象添加到Table<T>
24 dc.GetTable<Course>().InsertOnSubmit(newcourse);
25
26 //提交
27 dc.SubmitChanges();
ii.結果:
①物理表course:
②物理表sc:
2.查詢操作:
LINQ TO SQL中的標準查詢語句和LINQ TO OBJECT中的非常類似,但是它們在底層實現上有很大區別:1.LINQ TO?SQL查詢語句返回的結果類型為IQueryable<T>,而非IEnumerable<T>;2.LINQ TO SQL的大部分標準查詢操作符都是定義在IQueryable<T>類型中的擴展方法,而不像LINQ TO OBJECT中是定義在類型IEnumerable<T>上的,另外IQueryable<T>其實繼承了IEnumerable<T>類的,所以LINQ TO SQL上的查詢操作符比LINQ TO OBJECT更多,要想在LINQ TO SQL上使用LINQ TO OBJECT的查詢符,那么就需要使用AsEnumerable操作符進行轉換,這個在之前的延時標準查詢符(下)一節中有詳細介紹;3.LINQ TO SQL的查詢語句被轉換成標準的SQL語句,而LINQ TO OBJECT中的查詢語句是被轉換成IL代碼,LINQ TO SQL使用表達式樹來實現編譯時動態轉換成SQL語句發送給數據庫;4.LINQ TO SQL查詢被轉換成SQL語言后在數據庫被執行,而不像LINQ TO OBJECT中的查詢是在客戶端被執行的。雖然LINQ TO SQL和LINQ TO OBJECT在查詢上有很多的差別,但它們也有相同之處,就是LINQ TO SQL和LINQ TO OBJECT一樣都有延時查詢的特性,也就是說對數據庫的查詢是在必要時候才執行查詢,比如訪問一個實體類對象的屬性時,而不是在定義的時候就立即進行查詢。下面通過實例來說明LINQ TO SQL中延時查詢的特性:
i.延時查詢:
延時查詢 1 string conn ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc =new DataContext(conn);
3
4 //將SQL語句顯示在控制臺
5 dc.Log = Console.Out;
6
7 Table<Student> Tb_Students = dc.GetTable<Student>();
8
9 Console.WriteLine("LINQ TO SQL查詢符轉化的SQL語句:");
10
11 //查詢
12 var students = from s in Tb_Students where s.Age >2 select s;
13
14 //列舉
15 //foreach (var stu in students.Take(3))
16 //{
17 // Console.WriteLine(stu.ToString());
18 //}
19
20 Console.Read();
ii.結果:
從運行結果中可以看到盡管示例代碼中使用了查詢語句,但沒有任何向數據庫發送的SQL語句,現在把列舉部分的注釋去掉,再來看看結果如何:
這時候出現了相應的SQL語句,也就是說在真正用到查詢結果時(比如圖中通過foreach來列舉查詢結果),才會去發送并執行SQL語句。當實體類之間存在一對多的關系時,可以用屬性(attribute)Association來進行關聯,一旦實現了關聯操作,那么在向數據庫中查詢一個物理表記錄生成實體類對象時,也會附帶著相關聯物理表生成的實體類對象。這樣就方便了關聯數據的訪問,但也許有讀者會問,那如果要查詢的實體類對象,比如Course類,它有關聯的實體類Student_Course,那么每次查詢類Course對象,都會連帶去查詢相對應的實體類Student_Course對象,而不管在這之后的操作中用不用到實體類Student_Course對象。這樣不就在性能上有損失了。其實并非如此,LINQ TO SQL中有一個稱為延時載入的特性,也就是說只有用到與Course實體類相關聯的實體類Student_Course對象時,才會發去SQL語句去查詢相關聯的物理表的記錄生成實體類對象。以下是關于延時載入特性的說明示例:
i.延時載入:
2 DataContext dc =new DataContext(conn);
3
4 //將SQL語句顯示在控制臺
5 dc.Log = Console.Out;
6
7 Console.WriteLine("LINQ TO SQL查詢符轉化的SQL語句:");
8
9 Table<Course> Tb_Courses = dc.GetTable<Course>();
10
11 //查詢
12 var course = Tb_Courses.Where(c => c.No =="ky030002").Single();
13
14 //foreach (var sc in course.Students)
15 //{
16 // Console.WriteLine(sc.ToString());
17 //}
18
19 Console.Read();
ii.結果:
從結果中可以看到向數據庫發送SQL語句只是查詢物理表course里的記錄,而并沒有把相關的物理表sc中對應記錄也查詢出來。現在把上述的列舉代碼的注釋去掉,再來看看運行結果:
默認條件下,延時載入是自動支持的,但有時候在實際的運用中需要明確地要求在生成實體類對象的同時一并生成該對象的關聯成員,而不是等到使用該關聯成員時,才載入,這就需要立即載入的功能,而LINQ TO SQL中就提供了DataLoadOptions類的操作符LoadWith<T>來通知DataContext對象進行立即載入。下面是關于立即載入功能的說明示例:
i.立即載入:
立即載入 1 string conn ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc1 =new DataContext(conn);
3
4 Table<Course> Tb_Courses1 = dc1.GetTable<Course>();
5
6 //將SQL語句顯示在控制臺
7 dc1.Log = Console.Out;
8
9 //實例化類DataLoadOptions
10 DataLoadOptions dlo =new DataLoadOptions();
11
12 //指定在載入Course對象時一并載入關聯成員Students(來自Student_Course類的對象集合)
13 dlo.LoadWith<Course>(c => c.Students);
14
15 //將類DataLoadOptions的對象dlo賦值給DataContext對象
16 dc1.LoadOptions = dlo;
17
18 Console.WriteLine("LINQ TO SQL查詢符轉化的SQL語句:");
19 //查詢
20 var courses = Tb_Courses1.Where(c => c.No =="ky030002").Single();
21
22 Console.Read();
ii.結果:
使用Association屬性僅限于只有在數據庫中明確為需要關聯的物理表建立外鍵的情況,而在有些實際應用中,并沒有對數據庫中的物理表建立明確的主外鍵關系,但仍然需要對關聯的多個表進行查詢,那么這時候就要用到LINQ TO SQL中的標準操作符Join了,它和SQL中的Join一樣,有兩種表示內連接(inner join)的語法,還有它和SQL SERVER中的SQL一樣也可以定義外連接(outer join),下面是LINQ TO SQL中Join操作符使用的說明示例:
i.Join操作符實現內連接和外連接:
Join操作符 1 string conn ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc =new DataContext(conn);
3
4 var students2 = dc.GetTable<Student>();
5 var courses2 = dc.GetTable<Course>();
6 var scs2 = dc.GetTable<Student_Course>();
7
8 Console.WriteLine("內連接:");
9 var scs_1 = from s in students2
10 join sc in scs2
11 on s.No equals sc.Sno into sscs //放入臨時對象sscs
12 from ssc in sscs
13 join c in courses2
14 on ssc.Cno equals c.No
15 select new { Sname = s.Name, Cname = c.Name, Grade = ssc.Grade };
16 //或
17 //var scs_2 = from s in students2
18 // from c in courses2
19 // from sc in scs2
20 // where s.No == sc.Sno && c.No == sc.Cno
21 // select new { Sname = s.Name, Cname = c.Name, Grade = sc.Grade };
22
23 Console.WriteLine("學生選課情況:");
24 foreach (var scg in scs_1.AsEnumerable().Reverse().Take(5))
25 {
26 Console.WriteLine(scg.ToString());
27 }
28
29 Console.WriteLine();
30
31 Console.WriteLine("外連接:");
32 var scs_3 = from s in students2
33 join sc in scs2
34 on s.No equals sc.Sno into sscs //放入臨時對象sscs
35 from ssc in sscs.DefaultIfEmpty()//DefaultIfEmpty實現外連接
36 join c in courses2
37 on ssc.Cno equals c.No into sccs //放入臨時對象sccs
38 from scc in sccs.DefaultIfEmpty()//DefaultIfEmpty實現外連接
39 select new { Sname = s.Name, Cname =scc.Name, Grade = ssc.Grade };
40
41 Console.WriteLine("學生選課情況:");
42 foreach (var scg in scs_3.AsEnumerable().Reverse().Take(5))
43 {
44 Console.WriteLine(scg);
45 }
46
47 Console.Read();
ii.結果:
3.更新操作:
同樣的更新操作也十分簡單,修改實體類對象的屬性,然后調用SubmitChanges方法,提交更改。但要注意的是在LINQ TO SQL中對主鍵的修改是不允許的,下面是關于更新操作的示例:
i.更新操作:
更新操作 1 string str_sql ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc =new DataContext(str_sql);
3
4 var students = dc.GetTable<Student>();
5
6 Console.WriteLine("修改前:");
7 foreach (var stu in students.Take(3))
8 {
9 Console.WriteLine(stu.ToString());
10 }
11
12 foreach(var stu in students)
13 {
14 stu.Age +=1;
15 }
16
17 dc.SubmitChanges();
18
19 dc.Refresh(RefreshMode.OverwriteCurrentValues, students);
20
21 Console.WriteLine("修改后:");
22 foreach (var stu in students.Take(3))
23 {
24 Console.WriteLine(stu.ToString());
25 }
26
27 Console.WriteLine("\n");
28
29 Console.Read();
ii.結果:
4.刪除操作:
LINQ TO SQL中的刪除操作和插入操作類似,可以在DataContext對象的方法GetTable的返回值Table<T>,基礎上調用DeleteOnSumbit方法,它允許將一個或多個實體類對象從Table<T>集合中被刪除。下面是刪除操作的示例:
i.刪除操作:
刪除操作 1 string str_sql ="Data Source=localhost;Initial Catalog=DB_Student;User ID=sa;Password=king";2 DataContext dc =new DataContext(str_sql);
3
4 Console.WriteLine("學生:");
5 var student2 = dc.GetTable<Student>().Where(s => s.No =="20030012").Single();
6 Console.WriteLine(student2.ToString());
7
8 Console.WriteLine("選課:");
9 var courses = dc.GetTable<Student_Course>().Where(s => s.Sno =="20030012");
10 foreach (var c in courses)
11 {
12 Console.WriteLine(c.Course.ToString());
13 }
14
15 dc.GetTable<Student_Course>().DeleteAllOnSubmit(courses);
16 dc.GetTable<Student>().DeleteOnSubmit(student2);
17
18 dc.SubmitChanges();
19
20 dc.Refresh(RefreshMode.OverwriteCurrentValues,courses);
21 Console.WriteLine("刪除操作后,學號為20030012的學生選課情況:");
22 foreach (var c in courses)
23 {
24 Console.WriteLine(c.Course.ToString());
25 }
26
27 Console.Read();
ii.結果:
轉載于:https://www.cnblogs.com/CaiNiaoZJ/archive/2011/09/14/2174468.html
總結
以上是生活随笔為你收集整理的LINQ学习之旅——第二站LTQ之标准数据库操作(增查删改)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# App.config 自定义 配置
- 下一篇: Owasp live CD 2011下载