什麼是 Linq to sql
Linq to sql (或者叫 DLINQ )是 LINQ ( .NET 語言集成查詢)的一部分,全稱基於關係數據的 .NET 語言集成查詢,用於以對象形式管理關係數據,並提供了豐富的查詢功能,它和 Linq to xml 、 Linq to objects 、 Linq to dataset 、 Linq to entities 等組成了強大的 LINQ 。
要學好 LINQ 查詢語法,就不得不先理解 C# 3.0 的一些新特性,下面一一簡單介紹。
隱含類型局部變量
var age = 26; var username = "zhuye" ; var userlist = new [] {"a" ,"b" ,"c" }; foreach (var user in userlist) Console .WriteLine(user);
|
純粹給懶人用的 var 關鍵字,告訴編譯器(對於 CLR 來說,它是不會知道你是否使用了 var ,苦力是編譯器出的),你自己推斷它的類型吧,我不管了。但是既然讓編譯器推斷類型就必須聲明的時候賦值,而且不能是 null 值。注意,這隻能用於局部變量,用於字段是不可以的。
匿名類型
var data = new {username = "zhuye" ,age = 26}; Console .WriteLine("username:{0} age:{1}" , data.username, data.age);
|
匿名類型允許開發人員定義行內類型,無須顯式定義類型。常和 var 配合使用, var 用於聲明匿名類型。定義一個臨時的匿名類型在 LINQ 查詢句法中非常常見,我們可以很方便的實現對象的轉換和投影。
擴展方法
public static class helper { public static string MD5Hash(this string s) { return System.Web.Security.FormsAuthentication .HashPasswordForStoringInConfigFile(s,"MD5" ); }
public static bool In(this object o, IEnumerable b) { foreach (object obj in b) { if (obj==o) return true ; } return false ; } }
// 調用擴展方法 Console .WriteLine("123456" .MD5Hash()); Console .WriteLine("1" .In(new []{"1" ,"2" ,"3" }));
|
很多時候我們需要對 CLR 類型進行一些操作,苦於無法擴展 CLR 類型的方法,只能創建一些 helper 方法,或者生成子類。擴展方法使得這些需求得意實現,同時也是實現 LINQ 的基礎。定義擴展方法需要注意,只能在靜態類中定義並且是靜態方法,如果擴展方法名和原有方法名發生衝突,那麼擴展方法將失效。
自動屬性
public class Person { public string username { get ; protected set ; } public int age { get ; set ; }
public Person() { this .username = "zhuye" ; } }
Person p = new Person (); //p.username = "aa"; Console .WriteLine(p.username);
|
意義不是很大,純粹解決機械勞動。編譯器自動爲你生成 get 、 set 操作以及字段,並且你不能使用字段也不能自定義 get 、 set 操作,不過你可以分別定義 get 和 set 的訪問級別。
對象初始化器
public class Person { public string username { get ; set ; } public int age { get ; set ; }
public override string ToString() { return string .Format("username:{0} age:{1}" , this .username, this .age); } }
Person p = new Person () {username = "zhuye" , age=26}; Console .WriteLine(p.ToString());
|
編譯器會自動爲你做 setter 操作,使得原本幾行的屬性賦值操作能在一行中完成。這裏需要注意:
l 允許只給一部分屬性賦值,包括 internal 訪問級別
l 可以結合構造函數一起使用,並且構造函數初始化先於對象初始化器執行
集合初始化器
public class Person { public string username { get ; set ; } public int age { get ; set ; }
public override string ToString() { return string .Format("username:{0} age:{1}" , this .username, this .age); } }
var persons = new List <Person > { new Person {username = "a" , age=1}, new Person {username = "b" , age=2}}; foreach (var p in persons) Console .WriteLine(p.ToString());
|
編譯器會自動爲你做集合插入操作。如果你爲 Hashtable 初始化的話就相當於使用了兩個對象初始化器。
Lambda 表達式
var list = new [] { "aa" , "bb" , "ac" }; var result = Array .FindAll(list, s => (s.IndexOf("a" ) > -1)); foreach (var v in result) Console .WriteLine(v);
|
其實和 2.0 中的匿名方法差不多,都是用於產生內聯方法,只不過 Lambda 表達式的語法更爲簡潔。語法如下:
( 參數列表 ) => 表達式或者語句塊
其中:
參數個數:可以有多個參數,一個參數,或者無參數。
表達式或者語句塊:這部分就是我們平常寫函數的實現部分(函數體)。
前面的示例分別是 1 個參數的例子,下面結合擴展方法來一個複雜的例子:
public delegate int mydg (int a, int b);
public static class LambdaTest {
public static int oper(this int a, int b, mydg dg) { return dg(a, b); } }
Console .WriteLine(1.oper(2, (a, b) => a + b)); Console .WriteLine(2.oper(1, (a, b) => a - b));
|
查詢句法
var persons = new List <Person > { new Person {username = "a" , age=19}, new Person {username = "b" , age=20}, new Person {username = "a" , age=21}, }; var selectperson = from p in persons where p.age >= 20 select p.username.ToUpper(); foreach (var p in selectperson) Console .WriteLine(p);
|
查詢句法是使用標準的 LINQ 查詢運算符來表達查詢時一個方便的聲明式簡化寫法。該句法能在代碼裏表達查詢時增進可讀性和簡潔性,讀起來容易,也容易讓人寫對。 Visual Studio 對查詢句法提供了完整的智能感應和編譯時檢查支持。編譯器在底層把查詢句法的表達式翻譯成明確的方法調用代碼,代碼通過新的擴展方法和 Lambda 表達式語言特性來實現。上面的查詢句法等價於下面的代碼:
var selectperson = persons.Where(p=>p.age>=20).Select(p=>p.username.ToUpper()); |
LINQ 查詢句法可以實現 90 %以上 T-SQL 的功能(由於 T-SQL 是基於二維表的,所以 LINQ 的查詢語法會比 T-SQL 更簡單和靈活),但是由於智能感應的原因, select 不能放在一開始就輸入。