久久精品国产精品国产精品污,男人扒开添女人下部免费视频,一级国产69式性姿势免费视频,夜鲁夜鲁很鲁在线视频 视频,欧美丰满少妇一区二区三区,国产偷国产偷亚洲高清人乐享,中文 在线 日韩 亚洲 欧美,熟妇人妻无乱码中文字幕真矢织江,一区二区三区人妻制服国产

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

LINQ to SQL语句(1)之Where(抄的好)

發布時間:2025/3/15 数据库 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LINQ to SQL语句(1)之Where(抄的好) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Where操作適用場景:實現過濾,查詢等功能。說明:與SQL命令中的Where作用相似,都是起到范圍限定也就是過濾作用的,而判斷條件就是它后面所接的子句。Where操作包括3種形式,分別為簡單形式、關系條件形式、First()形式。下面分別用實例舉例下:1.簡單形式:例如:使用where篩選在倫敦的客戶var q =from c in db.Customerswhere c.City == "London"select c;再如:篩選1994 年或之后雇用的雇員:var q =from e in db.Employeeswhere e.HireDate >= new DateTime(1994, 1, 1)select e;2.關系條件形式:篩選庫存量在訂貨點水平之下但未斷貨的產品:var q =from p in db.Productswhere p.UnitsInStock <= p.ReorderLevel && !p.Discontinuedselect p;篩選出UnitPrice 大于10 或已停產的產品:var q =from p in db.Productswhere p.UnitPrice > 10m || p.Discontinuedselect p;下面這個例子是調用兩次where以篩選出UnitPrice大于10且已停產的產品。var q =db.Products.Where(p=>p.UnitPrice > 10m).Where(p=>p.Discontinued);3.First()形式:返回集合中的一個元素,其實質就是在SQL語句中加TOP (1)。簡單用法:選擇表中的第一個發貨方。Shipper shipper = db.Shippers.First();元素:選擇CustomerID 為“BONAP”的單個客戶Customer cust = db.Customers.First(c =>c.CustomerID == "BONAP");條件:選擇運費大于 10.00 的訂單:Order ord = db.Orders.First(o =>o.Freight > 10.00M);LINQ to SQL語句(2)之Select/Distinct[1] Select介紹1[2] Select介紹2[3] Select介紹3和 Distinct介紹Select/Distinct操作符適用場景:o(∩_∩) o…查詢唄。說明:和SQL命令中的select作用相似但位置不同,查詢表達式中的select及所接子句是放在表達式最后并把子句中的變量也就是結果返回回來;延遲。Select/Distinct操作包括9種形式,分別為簡單用 法、匿名類型形式、條件形式、指定類型形式、篩選形式、整形類型形式、嵌套類型形式、本地方法調用形式、Distinct形式。1.簡單用法:這個示例返回僅含客戶聯系人姓名的序列。var q =from c in db.Customersselect c.ContactName;注意:這個語句只是一個聲明或者一個描述,并沒有真正把數據取出來,只有當你需要該數據的時候,它才會執行這個語句,這就是延遲加載(deferred loading)。如果,在聲明的時候就返回的結果集是對象的集合。你可以使用ToList() 或ToArray()方法把查詢結果先進行保存,然后再對這個集合進行查詢。當然延遲加載(deferred loading)可以像拼接SQL語句那樣拼接查詢語法,再執行它。2.匿名類型形式:說明:匿名類型是C#3.0中新特性。其實質是編譯器根據我們自定義自動產生一個匿名的類來幫助我們實現臨時變量的儲存。匿名類型還依賴于另外一個特性:支持根據property來創建對象。比如,var d = new { Name = "s" };編譯器自動產生一個有property叫做Name的匿名類,然后按這 個類型分配內存,并初始化對象。但是var d = new {"s"};是編譯不 通過的。因為,編譯器不知道匿名類中的property的名字。例如stringc = "d";var d = new { c}; 則是可以通過編譯的。編譯器會創建一個叫 做匿名類帶有叫c的property。例如下例:new {c,ContactName,c.Phone};ContactName和Phone都是在映射文件中定義與表中字 段相對應的property。編譯器讀取數據并創建對象時,會創建一個匿名類,這個 類有兩個屬性,為ContactName和Phone,然后根據數據初始化對象。另外編譯器 還可以重命名property的名字。var q =from c in db.Customersselect new {c.ContactName, c.Phone};上面語句描述:使用 SELECT 和匿名類型返回僅含客戶聯系人姓名和電話號碼的序列var q =from e in db.Employeesselect new{Name = e.FirstName + " " + e.LastName,Phone = e.HomePhone};上面語句描述:使用SELECT和匿名類型返回僅含雇員姓名和電話號碼的序列,并將 FirstName和LastName字段合并為一個字段“Name”,此外在所得的序列中將HomePhone字段重命名為Phone。var q =from p in db.Productsselect new{p.ProductID,HalfPrice = p.UnitPrice / 2};上面語句描述:使用SELECT和匿名類型返回所有產品的ID以及 HalfPrice(設置為產品單價除以2所得的值)的序列。3.條件形式:說明:生成SQL語句為:case when condition then else。var q =from p in db.Productsselect new{p.ProductName,Availability =p.UnitsInStock - p.UnitsOnOrder < 0 ?"Out Of Stock" : "In Stock"};上面語句描述:使用SELECT和條件語句返回產品名稱和產品供貨狀態的序列。4.指定類型形式:說明:該形式返回你自定義類型的對象集。var q =from e in db.Employeesselect new Name{FirstName = e.FirstName,LastName = e.LastName};上面語句描述:使用SELECT和已知類型返回雇員姓名的序列。5.篩選形式:說明:結合where使用,起到過濾作用。var q =from c in db.Customerswhere c.City == "London"select c.ContactName;上面語句描述:使用SELECT和WHERE返回僅含倫敦客戶聯系人姓名的序列。6.shaped形式(整形類型):說明:其select操作使用了匿名對象,而這個匿名對象中,其屬性也是個匿名對象。var q =from c in db.Customersselect new {c.CustomerID,CompanyInfo = new {c.CompanyName, c.City, c.Country},ContactInfo = new {c.ContactName, c.ContactTitle}};語句描述:使用 SELECT 和匿名類型返回有關客戶的數據的整形子集。查詢顧客的ID和公司信息(公司名稱,城市,國家)以及聯系信息(聯系人和職位)。7.嵌套類型形式:說明:返回的對象集中的每個對象DiscountedProducts屬性中,又包含一個集合。也就是每個對象也是一個集合類。var q =from o in db.Ordersselect new {o.OrderID,DiscountedProducts =from od in o.OrderDetailswhere od.Discount > 0.0select od,FreeShippingDiscount = o.Freight};語句描述:使用嵌套查詢返回所有訂單及其OrderID 的序列、打折訂單中項目的子序列以及免送貨所省下的金額。8.本地方法調用形式(LocalMethodCall):這個例子在查詢中調用本地方法 PhoneNumberConverter將電話號碼轉換為國際格式。var q = from c in db.Customerswhere c.Country == "UK" || c.Country == "USA"select new{c.CustomerID,c.CompanyName,Phone = c.Phone,InternationalPhone =PhoneNumberConverter(c.Country, c.Phone)};PhoneNumberConverter方法如下:public string PhoneNumberConverter(stringCountry, string Phone){Phone = Phone.Replace(" ", "").Replace(")", ")-");switch (Country){case "USA":return "1- " + Phone;case "UK":return "44-" + Phone;default:return Phone;}}下面也是使用了這個方法將電話號碼轉換為國際格式并創建XDocumentXDocument doc = new XDocument(new XElement("Customers", from c in db.Customerswhere c.Country == "UK" || c.Country == "USA"select (new XElement ("Customer",new XAttribute ("CustomerID", c.CustomerID),new XAttribute("CompanyName", c.CompanyName),new XAttribute("InterationalPhone",PhoneNumberConverter(c.Country, c.Phone))))));9.Distinct形式:說明:篩選字段中不相同的值。用于查詢不重復的結果集。生成SQL語句為:SELECT DISTINCT [City] FROM [Customers]var q = (from c in db.Customersselect c.City ).Distinct();語句描述:查詢顧客覆蓋的國家。LINQ to SQL語句(3)之Count/Sum/Min/Max/Avg [1] Count/Sum講解[2] Min講解[3] Max講解[4] Average和Aggregate講解Count/Sum/Min/Max/Avg操作符適用場景:統計數據吧,比如統計一些數據的個數,求和,最小值,最大值,平均數。Count說明:返回集合中的元素個數,返回INT類型;不延遲。生成 SQL語句為:SELECT COUNT(*) FROM1.簡單形式:得到數據庫中客戶的數量:var q = db.Customers.Count();2.帶條件形式:得到數據庫中未斷貨產品的數量:var q = db.Products.Count(p =>!p.Discontinued);LongCount說明:返回集合中的元素個數,返回LONG類型;不延遲。對于元素個數較多的集合可視情況可以選用LongCount來統計元素個數,它返回long類型,比較精確。生成 SQL語句為:SELECT COUNT_BIG(*) FROMvar q = db.Customers.LongCount();Sum說明:返回集合中數值類型元素之和,集合應為INT類型集合;不延遲。生成SQL語句為:SELECT SUM(…) FROM1.簡單形式:得到所有訂單的總運費:var q = db.Orders.Select(o =>o.Freight).Sum();2.映射形式:得到所有產品的訂貨總數:var q = db.Products.Sum(p =>p.UnitsOnOrder);Min說明:返回集合中元素的最小值;不延遲。生成SQL語句為:SELECT MIN(…) FROM1.簡單形式:查找任意產品的最低單價:var q = db.Products.Select(p => p.UnitPrice).Min();2.映射形式:查找任意訂單的最低運費:var q = db.Orders.Min(o => o.Freight);3.元素:查找每個類別中單價最低的產品:var categories =from p in db.Productsgroup p by p.CategoryID into gselect new {CategoryID = g.Key,CheapestProducts =from p2 in gwhere p2.UnitPrice == g.Min(p3 => p3.UnitPrice)select p2};Max說明:返回集合中元素的最大值;不延遲。生成SQL語句為:SELECT MAX(…) FROM1.簡單形式: 查找任意雇員的最近雇用日期:var q = db.Employees.Select(e => e.HireDate).Max();2.映射形式:查找任意產品的最大庫存量:var q = db.Products.Max(p =>p.UnitsInStock);3.元素:查找每個類別中單價最高的產品:var categories =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,MostExpensiveProducts =from p2 in gwhere p2.UnitPrice == g.Max(p3 => p3.UnitPrice)select p2};Average說明:返回集合中的數值類型元素的平均值。集合應為數字類型集合,其返回值類型為double;不延遲。生成SQL語句為:SELECT AVG(…) FROM1.簡單形式: 得到所有訂單的平均運費:var q = db.Orders.Select(o =>o.Freight).Average();2.映射形式:得到所有產品的平均單價:var q = db.Products.Average(p => p.UnitPrice);3.元素:查找每個類別中單價高于該類別平均單價的產品:var categories =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,ExpensiveProducts =from p2 in gwhere p2.UnitPrice > g.Average (p3 => p3.UnitPrice)select p2};Aggregate說明:根據輸入的表達式獲取聚合值;不延遲。即是說:用一個種子值與當前元素通過指定的函數來進行對比來遍歷集合中的元素,符合條件的元素保留下來。如果沒有指定種子值的話,種子值默認為集合的第一個元素。LINQ to SQL語句(4)之Join Join操作符適用場景:在我們表關系中有一對一關系,一對多關系,多對多關系等。對各個表之間的關系,就用這些實現對多個表的操作。說明:在Join操作中,分別為Join(Join查詢), SelectMany(Select一對多選擇) 和GroupJoin(分組Join查詢)。該擴展方法對兩個序列中鍵匹配的元素進行inner join操作SelectMany說明:我們在寫查詢語句時,如果被翻譯成SelectMany需要滿足2個條件。1:查詢語句中沒有join和into,2:必須出現EntitySet。在我們表關系中有一對一關系,一對多關系,多對多關系等,下面分別介紹一下。1.一對多關系(1 to Many):var q =from c in db.Customersfrom o in c.Orderswhere c.City == "London"select o;語句描述:Customers與Orders是一對多關系。即Orders在Customers類中以 EntitySet形式出現。所以第二個from是從c.Orders而不是db.Orders里進行篩選。這個例子在From子句中使用外鍵導航選擇倫敦客戶的所有訂單。var q =from p in db.Productswhere p.Supplier.Country == "USA" &&p.UnitsInStock == 0select p;語句描述:這一句使用了 p.Supplier.Country條件,間接關聯了Supplier表。這個例子在Where子句中使用外鍵導航篩選其供應商在美國且缺貨的產品。生成SQL語句為:SELECT [t0].[ProductID],[t0].[ProductName], [t0]. [SupplierID],[t0].[CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],[t0].[UnitsInStock],[t0].[UnitsOnOrder],[t0]. [ReorderLevel],[t0].[Discontinued] FROM [dbo].[Products]AS [t0]LEFT OUTER JOIN [dbo].[Suppliers] AS [t1]ON[t1]. [SupplierID] = [t0].[SupplierID]WHERE ([t1].[Country] = @p0) AND([t0].[UnitsInStock] = @p1)-- @p0: Input NVarChar (Size = 3; Prec = 0;Scale = 0) [USA]-- @p1: Input Int (Size = 0; Prec = 0;Scale = 0) [0]2.多對多關系(Many to Many):var q =from e in db.Employeesfrom et in e.EmployeeTerritorieswhere e.City == "Seattle"select new{e.FirstName,e.LastName,et.Territory.TerritoryDescription};說明:多對多關系一般會涉及三個表(如果有一個表是自關聯的,那有可能只有2個表)。這一句語句涉及Employees, EmployeeTerritories, Territories三個表。它們的關系是1:M:1。Employees 和Territories沒有很明確的關系。語句描述:這個例子在From子句中使用外鍵導航篩選在西雅圖的雇員,同時列出其所在地區。這條生成SQL語句為:SELECT [t0].[FirstName], [t0].[LastName],[t2]. [TerritoryDescription]FROM [dbo].[Employees] AS [t0] CROSS JOIN[dbo].[EmployeeTerritories]AS [t1] INNER JOIN [dbo]. [Territories] AS[t2] ON[t2].[TerritoryID] = [t1].[TerritoryID]WHERE ([t0].[City] = @p0) AND([t1].[EmployeeID] = [t0]. [EmployeeID])-- @p0: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Seattle]3.自聯接關系:var q =from e1 in db.Employeesfrom e2 in e1.Employeeswhere e1.City == e2.Cityselect new {FirstName1 = e1.FirstName, LastName1 = e1.LastName,FirstName2 = e2.FirstName, LastName2 = e2.LastName,e1.City};語句描述:這個例子在select 子句中使用外鍵導航篩選成對的雇員,每對中一個雇員隸屬于另一個雇員,且兩個雇員都來自相同城市。生成SQL語句為:SELECT [t0].[FirstName] AS [FirstName1],[t0].[LastName] AS[LastName1],[t1].[FirstName] AS[FirstName2], [t1].[LastName] AS[LastName2],[t0].[City] FROM[dbo].[Employees] AS [t0],[dbo].[Employees] AS [t1] WHERE([t0].[City] = [t1]. [City]) AND([t1].[ReportsTo] = [t0].[EmployeeID])GroupJoin像上面所說的,沒有join和into,被翻譯成 SelectMany,同時有join和into時,那么就被翻譯為GroupJoin。在這里into的概念是對其結果進行重新命名。1.雙向聯接(Two way join):此示例顯式聯接兩個表并從這兩個表投影出結果:var q =from c in db.Customersjoin o in db.Orders on c.CustomerIDequals o.CustomerID into ordersselect new{c.ContactName,OrderCount = orders.Count ()};說明:在一對多關系中,左邊是1,它每條記錄為c(from c in db.Customers),右邊是Many,其每條記錄叫做o ( join o in db.Orders ),每對應左邊的一個c,就會有一組o,那這一組o,就叫做orders, 也就是說,我們把一組o命名為orders,這就是into用途。這也就是為什么在select語句中,orders可以調用聚合函數Count。在T-SQL中,使用其內嵌的T- SQL返回值作為字段值。如圖所示:生成SQL語句為:SELECT [t0].[ContactName], (SELECT COUNT(*)FROM [dbo].[Orders] AS [t1]WHERE [t0].[CustomerID] = [t1].[CustomerID]) AS [OrderCount]FROM [dbo].[Customers] AS [t0]2.三向聯接(There way join):此示例顯式聯接三個表并分別從每個表投影出結果:var q =from c in db.Customersjoin o in db.Orders on c.CustomerIDequals o.CustomerID into ordsjoin e in db.Employees on c.Cityequals e.City into empsselect new{c.ContactName,ords = ords.Count(),emps = emps.Count()};生成SQL語句為:SELECT [t0]. [ContactName], (SELECT COUNT(*)FROM [dbo].[Orders] AS [t1]WHERE [t0].[CustomerID] = [t1].[CustomerID]) AS [ords], (SELECT COUNT(*)FROM [dbo].[Employees] AS [t2]WHERE [t0].[City] = [t2].[City]) AS [emps]FROM [dbo].[Customers] AS [t0]3.左外部聯接(Left Outer Join):此示例說明如何通過使用此示例說明如何通過使用 DefaultIfEmpty() 獲取左外部聯接。在雇員沒有訂單時,DefaultIfEmpty()方法返回null:var q =from e in db.Employeesjoin o in db.Orders on e equals o.Employee into ordsfrom o in ords.DefaultIfEmpty()select new{e.FirstName,e.LastName,Order = o};說明:以Employees左表,Orders右表,Orders 表中為空時,用null值填充。Join的結果重命名ords,使用DefaultIfEmpty()函數對其再次查詢。其最后的結果中有個Order,因為from o in ords.DefaultIfEmpty() 是對 ords組再一次遍歷,所以,最后結果中的Order并不是一個集合。但是,如果沒有from o in ords.DefaultIfEmpty() 這句,最后的select語句寫成selectnew { e.FirstName, e.LastName, Order = ords }的話,那么Order就是一個集合。4.投影的Let賦值(Projectedlet assignment):說明:let語句是重命名。let位于第一個from和select語句之間。這個例子從聯接投影出最終“Let”表達式:var q =from c in db.Customersjoin o in db.Orders on c.CustomerIDequals o.CustomerID into ordslet z = c.City + c.Countryfrom o in ordsselect new{c.ContactName,o.OrderID,z};5.組合鍵(Composite Key):這個例子顯示帶有組合鍵的聯接:var q =from o in db.Ordersfrom p in db.Productsjoin d in db.OrderDetailson new{o.OrderID,p.ProductID} equalsnew{d.OrderID,d.ProductID}into detailsfrom d in detailsselect new{o.OrderID,p.ProductID,d.UnitPrice};說明:使用三個表,并且用匿名類來說明:使用三個表,并且用匿名類來表示它們之間的關系。它們之間的關系不能用一個鍵描述清楚,所以用匿名類,來表示組合鍵。還有一種是兩個表之間是用組合鍵表示關系的,不需要使用匿名類。6.可為null/不可為null的鍵關系 (Nullable/Nonnullable Key Relationship):這個實例顯示如何構造一側可為 null 而另一側不可為 null 的聯接:var q =from o in db.Ordersjoin e in db.Employeeson o.EmployeeID equals(int?)e.EmployeeID into empsfrom e in empsselect new{o.OrderID,e.FirstName};LINQ to SQL語句(5)之Order By Order By操作適用場景:對查詢出的語句進行排序,比如按時間排序等等。說明:按指定表達式對集合排序;延遲,:按指定表達式對集合排序;延遲,默認是升序,加上descending表示降序,對應的擴展方法是 OrderBy和OrderByDescending1.簡單形式這個例子使用 orderby 按雇用日期對雇員進行排序:var q =from e in db.Employeesorderby e.HireDateselect e;說明:默認為升序2.帶條件形式注意:Where 和Order By的順序并不重要。而在T-SQL中,Where和Order By有嚴格的位置限制。var q =from o in db.Orderswhere o.ShipCity == "London"orderby o.Freightselect o;語句描述:使用where和orderby按運費進行排序。3.降序排序var q =from p in db.Productsorderby p.UnitPrice descendingselect p;4.ThenBy語句描述:使用復合的 orderby 對客戶進行排序,進行排序:var q =from c in db.Customersorderby c.City, c.ContactNameselect c;說明:按多個表達式進行排序,例如先按City排序,當City相同時,按ContactName排序。這一句用Lambda表達式像這樣寫:var q =.OrderBy(c => c.City).ThenBy(c => c.ContactName).ToList();在T-SQL中沒有 ThenBy語句,其依然翻譯為OrderBy,所以也可以用下面語句來表達:var q =db.Customers.OrderBy(c => c.ContactName).OrderBy(c => c.City).ToList ();所要注意的是,多個OrderBy操作時,級連方式是按逆序。對于降序的,用相應的降序操作符替換即可。var q =db.Customers.OrderByDescending(c => c.City).ThenByDescending(c => c.ContactName).ToList();需要說明的是,OrderBy操作,不支持按type排序,也不支持匿名類。比如var q =db.Customers.OrderBy(c => new{c.City,c.ContactName}).ToList();會被拋出異常。錯誤是前面的操作有匿名類,再跟OrderBy時,比較的是類別。比如var q =db.Customers.Select(c => new{c.City,c.Address}).OrderBy(c => c).ToList();如果你想使用OrderBy(c => c),其前提條件是,前面步驟中,所產生的對象的類別必須為C#語言的基本類型。比如下句,這里 City為string類型。var q =db.Customers.Select(c => c.City).OrderBy(c => c).ToList ();5.ThenByDescending這兩個擴展方式都是用在 OrderBy/OrderByDescending之后的,第一個ThenBy/ThenByDescending擴展方法 作為第二位排序依據,第二個ThenBy/ThenByDescending則作為第三位排序依據 ,以此類推var q =from o in db.Orderswhere o.EmployeeID == 1orderby o.ShipCountry, o.Freight descendingselect o;語句描述:使用orderby先按發往國家再按運費從高到低的順序對 EmployeeID 1 的訂單進行排序。6. 帶GroupBy形式var q =from p in db.Productsgroup p by p.CategoryID into gorderby g.Keyselect new {g.Key,MostExpensiveProducts =from p2 in gwhere p2.UnitPrice == g.Max(p3 => p3.UnitPrice)select p2};語句描述:使用orderby、Max 和 Group By 得出每種類別中單價最高的產品,并按 CategoryID 對這組產品進行排序。LINQ to SQL語句(6)之GroupBy/Having Group By/Having操作符適用場景:分組數據,為我們查找數據縮小范圍。說明:分配并返回對傳入參數進行分組操作后的可枚舉對象。分組;延遲1.簡單形式:var q =from p in db.Productsgroup p by p.CategoryID into gselect g;語句描述:使用Group By按CategoryID劃分產品。說明:from p in db.Products 表示從表中將產品對象取出來。group p by p.CategoryID into g表示對p按CategoryID字段歸類。其結果命名為g,一旦重 新命名,p的作用域就結束了,所以,最后select時,只能select g。當然,也不必重新命名可以這樣寫:var q =from p in db.Productsgroup p by p.CategoryID;我們用示意圖表示:如果想遍歷某類別中所有記錄,這樣:foreach (var gp in q){if (gp.Key == 2){foreach (var item in gp){//do something}}}2.Select匿名類:var q =from p in db.Productsgroup p by p.CategoryID into gselect new { CategoryID = g.Key, g };說明:在這句LINQ語句中,有2個property:CategoryID和g。這個匿名類,其實質是對返回結果集重新進行了包裝。把g的property封裝成一個完整的分組。如下圖所示:如果想遍歷某匿名類中所有記錄,要這么做:foreach (var gp in q){if (gp.CategoryID == 2){foreach (var item in gp.g){//do something}}}3.最大值var q =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,MaxPrice = g.Max(p => p.UnitPrice)};語句描述:使用Group By和Max查找每個CategoryID的最高單價。說明:先按CategoryID歸類,判斷各個分類產品中單價最大的 Products。取出CategoryID值,并把UnitPrice值賦給MaxPrice。4.最小值var q =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,MinPrice = g.Min(p => p.UnitPrice)};語句描述:使用Group By和Min查找每個CategoryID的最低單價。說明:先按CategoryID歸類,判斷各個分類產品中單價最小的 Products。取出CategoryID值,并把UnitPrice值賦給MinPrice。5.平均值var q =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,AveragePrice = g.Average(p => p.UnitPrice)};語句描述:使用Group By和Average得到每個CategoryID的平均單價。說明:先按CategoryID歸類,取出CategoryID值和各個分類產品中單價的平均值。6.求和var q =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,TotalPrice = g.Sum(p => p.UnitPrice)};語句描述:使用Group By和Sum得到每個CategoryID 的單價總計。說明:先按CategoryID歸類,取出 CategoryID值和各個分類產品中單價的總和。7.計數var q =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,NumProducts = g.Count()};語句描述:使用Group By和Count得到每個CategoryID中產品的數量。說明:先按CategoryID歸類,取出 CategoryID值和各個分類產品的數量。8.帶條件計數var q =from p in db.Productsgroup p by p.CategoryID into gselect new {g.Key,NumProducts = g.Count(p => p.Discontinued)};語句描述:使用Group By和Count得到每個CategoryID中斷貨產品的數量。說明:先按 CategoryID歸類,取出CategoryID值和各個分類產品的斷貨數量。Count函數里,使用了Lambda表達式,Lambda表達式中的p,代表這個組里的一個元素或對象,即某一個產品。9.Where限制var q =from p in db.Productsgroup p by p.CategoryID into gwhere g.Count() >= 10select new {g.Key,ProductCount = g.Count()};語句描述:根據產品的―ID分組,查詢產品數量大于10的ID和產品數量。這個示例在Group By子句后使用Where子句查找所有至少有10種產品的類別。說明:在翻譯成SQL 語句時,在最外層嵌套了Where條件。10.多列(Multiple Columns)var categories =from p in db.Productsgroup p by new{p.CategoryID,p.SupplierID}into gselect new{g.Key,g};語句描述:使用Group By按CategoryID和 SupplierID將產品分組。說明:既按產品的分類,又按供應商分類。在 by后面,new出來一個匿名類。這里,Key其實質是一個類的對象,Key包含兩個 Property:CategoryID、SupplierID。用g.Key.CategoryID可以遍歷CategoryID 的值。11.表達式(Expression)var categories =from p in db.Productsgroup p by new { Criterion = p.UnitPrice > 10 } into gselect g;語句描述:使用Group By返回兩個產品序列。第一個序列包含單價大于10的產品。第二個序列包含單價小于或等于10的產品。說明:按產品單價是否大于10分類。其結果分為兩類,大于的是一類,小于及等于為另一類。LINQ to SQL語句(7)之Exists/In/Any/All/Contains Exists/In/Any/All/Contains操作符適用場景:用于判斷集合中元素,進一步縮小范圍。Any說明:用于判斷集合中是否有元素滿足某一條件;不延遲。(若條件為空,則集合只要不為空就返回True,否則為 False)。有2種形式,分別為簡單形式和帶條件形式。1.簡單形式:僅返回沒有訂單的客戶:var q =from c in db.Customerswhere !c.Orders.Any()select c;生成SQL語句為:SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],[t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],[t0].[PostalCode], [t0].[Country],[t0].[Phone], [t0].[Fax]FROM [dbo].[Customers] AS [t0]WHERE NOT (EXISTS(SELECT NULL AS [EMPTY] FROM [dbo].[Orders] AS [t1]WHERE [t1].[CustomerID] = [t0]. [CustomerID]))2.帶條件形式:僅返回至少有一種產品斷貨的類別:var q =from c in db.Categorieswhere c.Products.Any(p => p.Discontinued)select c;生成SQL語句為:SELECT [t0]. [CategoryID],[t0].[CategoryName], [t0].[Description],[t0]. [Picture] FROM [dbo].[Categories] AS[t0]WHERE EXISTS(SELECT NULL AS [EMPTY] FROM [dbo].[Products] AS [t1]WHERE ([t1].[Discontinued] = 1) AND([t1].[CategoryID] = [t0]. [CategoryID]))All 說明:用于判斷集合中所有元素是否都滿足某一條件;不延遲1.帶條件形式var q =from c in db.Customerswhere c.Orders.All(o => o.ShipCity == c.City)select c;語句描述:這個例子返回所有訂單都運往其所在城市的客戶或未下訂單的客戶。Contains說明:用于判斷集合中是否包含有某一元素;不延遲。它是對兩個序列進行連接操作的。string[] customerID_Set =new string[] { "AROUT", "BOLID","FISSA" };var q = (from o in db.Orderswhere customerID_Set.Contains(o.CustomerID)select o).ToList ();語句描述:查找"AROUT", "BOLID" 和 "FISSA" 這三個客戶的訂單。先定義了一個數組,在LINQ to SQL中使用Contains,數組中包含了所有的CustomerID,即返回結果中,所有的 CustomerID都在這個集合內。也就是in。你也可以把數組的定義放在LINQ to SQL語句里。比如:var q = (from o in db.Orderswhere (new string[] { "AROUT", "BOLID","FISSA" }).Contains (o.CustomerID)select o).ToList();Not Contains則取反:var q = (from o in db.Orderswhere !(new string[] { "AROUT", "BOLID","FISSA" }).Contains(o.CustomerID)select o).ToList();1.包含一個對象:var order = (from o in db.Orderswhere o.OrderID == 10248select o).First();var q = db.Customers.Where(p =>p.Orders.Contains(order)).ToList();foreach (var cust in q){foreach (var ord in cust.Orders){//do something}}語句描述:這個例子使用Contain查找哪個客戶包含OrderID為10248的訂單。2.包含多個值:string[] cities =new string[] { "Seattle", "London","Vancouver", "Paris" };var q = db.Customers.Where(p=>cities.Contains(p.City)).ToList();語句描述:這個例子使用Contains查找其所在城市為西雅圖、倫敦、巴黎或溫哥華的客戶。LINQ to SQL語句(8)之Concat/Union/Intersect/Except Concat/Union/Intersect/Except操作適用場景:對兩個集合的處理,例如追加、合并、取相同項、相交項等等。Concat(連接)說明:連接不同的集合,不會自動過濾相同項;延遲。1.簡單形式: var q = (from c in db.Customersselect c.Phone).Concat(from c in db.Customersselect c.Fax).Concat(from e in db.Employeesselect e.HomePhone);語句描述:返回所有消費者和雇員的電話和傳真。2.復合形式: var q = (from c in db.Customersselect new{Name = c.CompanyName,c.Phone}).Concat(from e in db.Employeesselect new{Name = e.FirstName + " " + e.LastName,Phone = e.HomePhone});語句描述:返回所有消費者和雇員的姓名和電話。Union(合并)說明:連接不同的集合,自動過濾相同項;延遲。即是將兩個集合進行合并操作,過濾相同的項。var q = (from c in db.Customersselect c.Country).Union(from e in db.Employeesselect e.Country);語句描述:查詢顧客和職員所在的國家。Intersect(相交)說明:取相交項;延遲。即是獲取不同集合的相同項(交集)。即先遍歷第一個集合,找出所有唯一的元素,然后遍歷第二個集合,并將每個元素與前面找出的元素作對比,返回所有在兩個集合內都出現的元素。var q = (from c in db.Customersselect c.Country).Intersect (from e in db.Employeesselect e.Country);語句描述:查詢顧客和職員同在的國家。Except(與非)說明:排除相交項;延遲。即是從某集合中刪除與另一個集合中相同的項。先遍歷第一個集合,找出所有唯一的元素,然后再遍歷第二個集合,返回第二個集合中所有未出現在前面所得元素集合中的元素。var q = (from c in db.Customersselect c.Country).Except(from e in db.Employeesselect e.Country);語句描述:查詢顧客和職員不同的國家。LINQ to SQL語句(9)之Top/Bottom和Paging和SqlMethods Top/Bottom操作適用場景:適量的取出自己想要的數據,不是全部取出,這樣性能有所加強。Take說明:獲取集合的前n個元素;延遲。即只返回限定數量的結果集。var q = (from e in db.Employeesorderby e.HireDateselect e).Take(5);語句描述:選擇所雇用的前5個雇員。Skip說明:跳過集合的前n個元素;延遲。即我們跳過給定的數目返回后面的結果集。var q = (from p in db.Productsorderby p.UnitPrice descendingselect p).Skip (10);語句描述:選擇10種最貴產品之外的所有產品。TakeWhile說明:直到某一條件成立就停止獲取;延遲。即用其條件去依次判斷源序列中的元素,返回符合判斷條件的元素,該判斷操作將在返回 false或源序列的末尾結束。SkipWhile說明:直到某一條件成立就停止跳過;延遲。即用其條件去判斷源序列中的元素并且跳過第一個符合判斷條件的元素,一旦判斷返回false,接下來將不再進行判斷并返回剩下的所有元素。Paging(分頁)操作適用場景:結合Skip和Take就可實現對數據分頁操作。1.索引 var q = (from c in db.Customersorderby c.ContactNameselect c).Skip(50).Take(10);語句描述:使用Skip和Take運算符進行分頁,跳過前50條記錄,然后返回接下來10條記錄,因此提供顯示 Products表第6頁的數據。2.按唯一鍵排序 var q = (from p in db.Productswhere p.ProductID > 50orderby p.ProductIDselect p).Take(10);語句描述:使用Where子句和Take運算符進行分頁,首先篩選得到僅50 (第5頁最后一個ProductID)以上的ProductID,然后按ProductID排序,最后取前10個結果,因此提供Products表第6頁的數據。請注意,此方法僅適用于按唯一鍵排序的情況。SqlMethods操作在LINQ to SQL語句中,為我們提供了 SqlMethods操作,進一步為我們提供了方便,例如Like方法用于自定義通配表達式,Equals用于相比較是否相等。Like自定義的通配表達式。%表示零長度或任意長度的字符串;_表示一個字符;[]表示在某范圍區間的一個字符;[^]表示不在某范圍區間的一個字符。比如查詢消費者ID以“C”開頭的消費者。var q = from c in db.Customerswhere SqlMethods.Like(c.CustomerID, "C%")select c;比如查詢消費者ID沒有“AXOXT”形式的消費者:var q = from c in db.Customerswhere ! SqlMethods.Like(c.CustomerID, "A_O_T")select c;DateDiffDay說明:在兩個變量之間比較。分別有:DateDiffDay、 DateDiffHour、DateDiffMillisecond、DateDiffMinute、DateDiffMonth、 DateDiffSecond、DateDiffYear var q = from o in db.Orderswhere SqlMethods.DateDiffDay (o.OrderDate, o.ShippedDate) < 10select o;語句描述:查詢在創建訂單后的 10 天內已發貨的所有訂單。已編譯查詢操作(Compiled Query)說明:在之前我們沒有好的方法對寫出的SQL語句進行編輯重新查詢,現在我們可以這樣做,看下面一個例子://1. 創建compiled queryNorthwindDataContext db = newNorthwindDataContext();var fn = CompiledQuery.Compile((NorthwindDataContext db2, string city) =>from c in db2.Customerswhere c.City == cityselect c);//2.查詢城市為London的消費者,用LonCusts集合表示,這時可以用數據控件 綁定var LonCusts = fn(db, "London");//3.查詢城市 為Seattle的消費者var SeaCusts = fn(db, "Seattle");語句描述:這個例子創建一個已編譯查詢,然后使用它檢索輸入城市的客戶。LINQ to SQL語句(10)之Insert 插入(Insert)1.簡單形式說明:new一個對象,使用InsertOnSubmit方法將其加入到對應的集合中,使用SubmitChanges()提交到數據庫。NorthwindDataContext db = newNorthwindDataContext();var newCustomer = new Customer{CustomerID = "MCSFT",CompanyName = "Microsoft",ContactName = "John Doe",ContactTitle = "Sales Manager",Address = "1 Microsoft Way",City = "Redmond",Region = "WA",PostalCode = "98052",Country = "USA",Phone = "(425) 555- 1234",Fax = null};db.Customers.InsertOnSubmit(newCustomer);db.SubmitChanges ();語句描述:使用InsertOnSubmit方法將新客戶添加到Customers 表對象。調用SubmitChanges 將此新Customer保存到數據庫。2.一對多關系說明:Category與Product是一對多的關系,提交Category(一端)的數據時,LINQ to SQL會自動將Product(多端)的數據一起提交。var newCategory = new Category{CategoryName = "Widgets",Description = "Widgets are the ……"};var newProduct = new Product{ProductName = "Blue Widget",UnitPrice = 34.56M,Category = newCategory};db.Categories.InsertOnSubmit(newCategory);db.SubmitChanges ();語句描述:使用InsertOnSubmit方法將新類別添加到Categories 表中,并將新Product對象添加到與此新Category有外鍵關系的Products表中。調用SubmitChanges將這些新對象及其關系保存到數據庫。3.多對多關系說明:在多對多關系中,我們需要依次提交。var newEmployee = new Employee{FirstName = "Kira",LastName = "Smith"};var newTerritory = new Territory{TerritoryID = "12345",TerritoryDescription = "Anytown",Region = db.Regions.First()};var newEmployeeTerritory = newEmployeeTerritory{Employee = newEmployee,Territory = newTerritory};db.Employees.InsertOnSubmit(newEmployee);db.Territories.InsertOnSubmit(newTerritory);db.EmployeeTerritories.InsertOnSubmit(newEmployeeTerritory);db.SubmitChanges();語句描述:使用InsertOnSubmit方法將新雇員添加到Employees 表中,將新Territory添加到Territories表中,并將新 EmployeeTerritory對象添加到與此新Employee對象和新Territory對象有外鍵關系的EmployeeTerritories表中。調用SubmitChanges將這些新對象及其關系保持到數據庫。4.使用動態CUD重寫(Overrideusing Dynamic CUD)說明:CUD就是Create、Update、Delete的縮寫。下面的例子就是新建一個ID(主鍵) 為32的Region,不考慮數據庫中有沒有ID為32的數據,如果有則替換原來的數據,沒有則插入。Region nwRegion = new Region(){RegionID = 32,RegionDescription = "Rainy"};db.Regions.InsertOnSubmit(nwRegion);db.SubmitChanges ();語句描述:使用DataContext提供的分部方法InsertRegion插入一個區域。對SubmitChanges 的調用調用InsertRegion 重寫,后者使用動態CUD運行Linq To SQL生成的默認SQL查詢。LINQ to SQL語句(11)之Update 更新(Update)說明:更新操作,先獲取對象,進行修改操作之后,直接調用SubmitChanges()方法即可提交。注意,這里是在同一個DataContext中,對于不同的DataContex看下面的講解。1.簡單形式 Customer cust =db.Customers.First(c => c.CustomerID == "ALFKI");cust.ContactTitle = "VicePresident";db.SubmitChanges();語句描述:使用 SubmitChanges將對檢索到的一個Customer對象做出的更新保持回數據庫。2.多項更改 var q = from p in db.Productswhere p.CategoryID == 1select p;foreach (var p in q){p.UnitPrice += 1.00M;}db.SubmitChanges ();語句描述:使用SubmitChanges將對檢索到的進行的更新保持回數據庫。LINQ to SQL語句(12)之Delete和使用Attach 刪除(Delete)1.簡單形式說明:調用DeleteOnSubmit方法即可。OrderDetail orderDetail =db.OrderDetails.First(c => c.OrderID == 10255 && c.ProductID == 36);db.OrderDetails.DeleteOnSubmit(orderDetail);db.SubmitChanges();語句描述:使用 DeleteOnSubmit方法從OrderDetail 表中刪除OrderDetail對象。調用 SubmitChanges 將此刪除保持到數據庫。2.一對多關系說明:Order 與OrderDetail是一對多關系,首先DeleteOnSubmit其OrderDetail(多端),其次 DeleteOnSubmit其Order(一端)。因為一端是主鍵。var orderDetails =from o in db.OrderDetailswhere o.Order.CustomerID == "WARTH" &&o.Order.EmployeeID == 3select o;var order =(from o in db.Orderswhere o.CustomerID == "WARTH" && o.EmployeeID ==3select o).First();foreach (OrderDetail od in orderDetails){db.OrderDetails.DeleteOnSubmit(od);}db.Orders.DeleteOnSubmit(order);db.SubmitChanges();語句描述語句描述:使用DeleteOnSubmit方法從Order 和Order Details表中刪除Order和Order Detail對象。首先從Order Details刪除,然后從Orders刪除。調用SubmitChanges將此刪除保持到數據庫。3.推理刪除(Inferred Delete)說明:Order與OrderDetail是一對多關系,在上面的例子,我們全部刪除CustomerID為WARTH和EmployeeID為3 的數據,那么我們不須全部刪除呢?例如Order的OrderID為10248的OrderDetail有很多,但是我們只要刪除 ProductID為11的OrderDetail。這時就用Remove方法。Order order = db.Orders.First(x =>x.OrderID == 10248);OrderDetail od =order.OrderDetails.First(d => d.ProductID == 11);order.OrderDetails.Remove(od);db.SubmitChanges();語句描述語句描述:這個例子說明在實體對象的引用實體將該對象從其EntitySet 中移除時,推理刪除如何導致在該對象上發生實際的刪除操作。僅當實體的關聯映射將DeleteOnNull設置為true且CanBeNull 為false 時,才會發生推理刪除行為。使用Attach更新(Updatewith Attach)說明:在對于在不同的 DataContext之間,使用Attach方法來更新數據。例如在一個名為tempdb的 NorthwindDataContext中,查詢出Customer和Order,在另一個 NorthwindDataContext中,Customer的地址更新為123 First Ave,Order的 CustomerID 更新為CHOPS。//通常,通過從其他層反序列化 XML 來獲取要附加的實體//不支持將實體從一個DataContext附加到另一個DataContext//因此若要復制反序列化實體的操作,將在此處重新創建這 些實體Customer c1;List<Order> deserializedOrders = newList<Order>();Customer deserializedC1;using (NorthwindDataContext tempdb = newNorthwindDataContext()){c1 = tempdb.Customers.Single(c => c.CustomerID =="ALFKI");deserializedC1 = new Customer{Address = c1.Address,City = c1.City,CompanyName = c1.CompanyName,ContactName = c1.ContactName,ContactTitle = c1.ContactTitle,Country = c1.Country,CustomerID = c1.CustomerID,Fax = c1.Fax,Phone = c1.Phone,PostalCode = c1.PostalCode,Region = c1.Region};Customer tempcust =tempdb.Customers.Single(c => c.CustomerID == "ANTON");foreach (Order o in tempcust.Orders){deserializedOrders.Add(new Order{CustomerID = o.CustomerID,EmployeeID = o.EmployeeID,Freight = o.Freight,OrderDate = o.OrderDate,OrderID = o.OrderID,RequiredDate = o.RequiredDate,ShipAddress = o.ShipAddress,ShipCity = o.ShipCity,ShipName = o.ShipName,ShipCountry = o.ShipCountry,ShippedDate = o.ShippedDate,ShipPostalCode = o.ShipPostalCode,ShipRegion = o.ShipRegion,ShipVia = o.ShipVia});}}using (NorthwindDataContext db2 = newNorthwindDataContext()){//將第一個實體附加到當前數據上下文,以跟蹤更改//對Customer更新,不能寫錯db2.Customers.Attach(deserializedC1);//更改所跟蹤的實體deserializedC1.Address = "123 First Ave";// 附加訂單列表中的所有實體db2.Orders.AttachAll (deserializedOrders);//將訂單更新為屬于其他客戶foreach (Order o in deserializedOrders){o.CustomerID = "CHOPS";}//在當前數據上下文中提交更改db2.SubmitChanges();}語句描述:從另一個層中獲取實體,使用Attach和AttachAll將反序列化后的實體附加到數據上下文,然后更新實體。更改被提交到數據庫。使用Attach更新和刪除(Update and Delete with Attach)說明:在不同的DataContext中,實現插入、更新、刪除。看下面的一個例子://通常,通過從其他層 反序列化XML獲取要附加的實體//此示例使用 LoadWith 在一個查詢中預 先加載客戶和訂單,//并禁用延遲加載Customer cust = null;using (NorthwindDataContext tempdb = newNorthwindDataContext()){DataLoadOptions shape = new DataLoadOptions();shape.LoadWith<Customer>(c => c.Orders);//加載第一個客戶實體及其訂單tempdb.LoadOptions = shape;tempdb.DeferredLoadingEnabled = false;cust = tempdb.Customers.First(x => x.CustomerID =="ALFKI");}Order orderA = cust.Orders.First();Order orderB = cust.Orders.First(x =>x.OrderID > orderA.OrderID);using (NorthwindDataContext db2 = newNorthwindDataContext()){//將第一個實體附加到當前數據上下文,以跟蹤更改db2.Customers.Attach(cust);//附加相關訂單以進行跟蹤; 否則將在提交時插入它們db2.Orders.AttachAll(cust.Orders.ToList ());//更新客戶的Phone.cust.Phone = "2345 5436";//更新第一個訂單OrderA的ShipCity.orderA.ShipCity = "Redmond";//移除第二個訂單 OrderB.cust.Orders.Remove(orderB);//添加一個新的訂單Order到客戶Customer中.Order orderC = new Order() { ShipCity = "New York" };cust.Orders.Add (orderC);//提交執行db2.SubmitChanges();}語句描述:從一個上下文提取實體,并使用 Attach 和 AttachAll 附加來自其他上下文的實體,然后更新這兩個實體,刪除一個實體,添加另一個實體。更改被提交到數據庫。LINQ to SQL語句(13)之開放式并發控制和事務 Simultaneous Changes開放式并發控制下表介紹 LINQ to SQL 文檔中涉及開放式并發的術語:術語說明并發兩個或更多用戶同時嘗試更新同一數據庫行的情形。并發沖突兩個或更多用戶同時嘗試向一行的一列或多列提交沖突值的情形。并發控制用于解決并發沖突的技術。開放式并發控制先調查其他事務是否已更改了行中的值,再允許提交更改的技術。相比之下,保守式并發控制則是通過鎖定記錄來避免發生并發沖突。之所以稱作開放式控制,是因為它將一個事務干擾另一事務視為不太可能發生。沖突解決通過重新查詢數據庫刷新出現沖突的項,然后協調差異的過程。刷新對象時,LINQ to SQL 更改跟蹤器會保留以下數據:最初從數據庫獲取并用于更新檢查的值通過后續查詢獲得的新數據庫值。 LINQ to SQL 隨后會確定相應對象是否發生沖突(即它的一個或多個成員值是否已發生更改)。如果此對象發生沖突,LINQ to SQL 下一步會確定它的哪些成員發生沖突。LINQ to SQL 發現的任何成員沖突都會添加到沖突列表中。在 LINQ to SQL 對象模型中,當以下兩個條件都得到滿足時,就會發生“開放式并發沖突”:客戶端嘗試向數據庫提交更改;數據庫中的一個或多個更新檢查值自客戶端上次讀取它們以來已得到更新。此沖突的解決過程包括查明對象的哪些成員發生沖突,然后決定您希望如何進行處理。開放式并發(Optimistic Concurrency)說明:這個例子中在你讀取數據之前,另外一個用戶已經修改并提交更新了這個數據,所以不會出現沖突。//我們打開一個新的連接來模擬另外一個用戶NorthwindDataContext otherUser_db = newNorthwindDataContext();var otherUser_product =otherUser_db.Products.First(p => p.ProductID == 1);otherUser_product.UnitPrice = 999.99M;otherUser_db.SubmitChanges();//我們當前連接var product = db.Products.First(p =>p.ProductID == 1);product.UnitPrice = 777.77M;try{db.SubmitChanges();//當前連接執行成功}catch (ChangeConflictException){}說明:我們讀取數據之后,另外一個用戶獲取并提交更新了這個數據,這時,我們更新這個數據時,引起了一個并發沖突。系統發生回滾,允許你可以從數據庫檢索新更新的數據,并決定如何繼續進行您自己的更新。//當前 用戶var product = db.Products.First(p =>p.ProductID == 1);//我們打開一個新的連接來模擬另外一個用戶NorthwindDataContext otherUser_db = newNorthwindDataContext() ;var otherUser_product =otherUser_db.Products.First(p => p.ProductID == 1);otherUser_product.UnitPrice = 999.99M;otherUser_db.SubmitChanges();//當前用戶修改product.UnitPrice = 777.77M;try{db.SubmitChanges();}catch (ChangeConflictException){//發生異常!}Transactions事務LINQto SQL 支持三種事務模型,分別是:顯式本地事務:調用 SubmitChanges 時,如果 Transaction 屬性設置為事務,則在同一事務的上下文中執行 SubmitChanges 調用。成功執行事務后,要由您來提交或回滾事務。與事務對應的連接必須與用于構造 DataContext 的連接匹配。如果使用其他連接,則會引發異常。顯式可分發事務:可以在當前 Transaction 的作用域中調用 LINQ to SQL API(包括但不限于 SubmitChanges)。LINQ to SQL 檢測到調用是在事務的作用域內,因而不會創建新的事務。在這種情況下, <token>vbtecdlinq</token> 還會避免關閉連接。您可以在此類事 務的上下文中執行查詢和SubmitChanges 操作。隱式事務:當您調用 SubmitChanges 時,LINQ to SQL 會檢查此調用是否在 Transaction 的作用域內或者 Transaction 屬性是否設置為由用戶啟動的本地事務。如果這兩個事務它均未找到,則 LINQ to SQL 啟動本地事務,并使用此事務執行所生成的 SQL 命令。當所有 SQL 命令均已成功執行完畢時,LINQ to SQL 提交本地事務并返回。1.Implicit(隱式)說明:這個例子在執行SubmitChanges ()操作時,隱式地使用了事務。因為在更新2種產品的庫存數量時,第二個產品庫存數量為負數了,違反了服務器上的 CHECK 約束。這導致了更新產品全部失敗了,系統回滾到這個操作的初始狀態。try{Product prod1 = db.Products.First(p => p.ProductID == 4);Product prod2 = db.Products.First(p => p.ProductID == 5);prod1.UnitsInStock -= 3;prod2.UnitsInStock -= 5;//錯誤:庫存 數量的單位不能是負數//要么全部成功要么全部失敗db.SubmitChanges();}catch (System.Data.SqlClient.SqlExceptione){//執行異常處理}2.Explicit(顯式)說明:這個例子使用顯式事務。通過在事務中加入對數據的讀取以防止出現開放式并發異常,顯式事務可以提供更多的保護。如同上一個查詢中,更新 prod2 的 UnitsInStock 字段將使該字段為負值,而這違反了數據庫中的 CHECK 約束。這導致更新這兩個產品的事務失敗,此時將回滾所有更改。using (TransactionScope ts = new TransactionScope()){try{Product prod1 = db.Products.First(p => p.ProductID == 4);Product prod2 = db.Products.First(p => p.ProductID == 5);prod1.UnitsInStock -= 3;prod2.UnitsInStock -= 5;//錯誤:庫存數量的單位不能是負數db.SubmitChanges();}catch (System.Data.SqlClient.SqlException e){//執行異常處理}}LINQ to SQL語句(14)之Null語義和DateTime Null語義說明:下面第一個例子說明查詢ReportsToEmployee為null的雇員。第二個例子使用Nullable<T>.HasValue查詢雇員,其結果與第一個例 子相同。在第三個例子中,使用Nullable<T>.Value來返回ReportsToEmployee不為null的雇員的ReportsTo的值。1.Null查找不隸屬于另一個雇員的所有雇員:var q =from e in db.Employeeswhere e.ReportsToEmployee == nullselect e;2.Nullable<T>.HasValue查找不隸屬于另一個雇員的所有雇員:var q =from e in db.Employeeswhere !e.ReportsTo.HasValueselect e;3.Nullable<T>.Value返回前者的EmployeeID 編號。請注意 .Value 為可選:var q =from e in db.Employeeswhere e.ReportsTo.HasValueselect new{e.FirstName,e.LastName,ReportsTo = e.ReportsTo.Value};日期函數LINQ to SQL支持以下 DateTime方法。但是,SQLServer和CLR的DateTime類型在范圍和計時周期精度上不同,如下表。類型最小值 最大 值 計時周期System.DateTime 0001 年 1 月 1 日 9999 年 12 月 31 日 100 毫微秒(0.0000001秒)T-SQL DateTime 1753 年 1 月 1 日 9999 年 12 月 31 日 3.33… 毫秒(0.0033333 秒)T-SQL SmallDateTime 1900 年 1 月 1 日 2079 年 6 月 6 日 1 分鐘(60 秒)CLR DateTime 類型與SQL Server類型相比,前者范圍更 大、精度更高。因此來自SQLServer的數據用CLR類型表示時,絕不會損失量值或精度。但如果反過來的話,則范圍可能會減小,精度可能會降低;SQL Server 日期不存在TimeZone概念,而在CLR中支持這個功能。我們在LINQ to SQL查詢使用以當地時間、UTC 或固定時間要自己執行轉換。下面用三個實例說明一下。1.DateTime.Year var q =from o in db.Orderswhere o.OrderDate.Value.Year == 1997select o;語句描述:這個例子使用DateTime 的Year 屬性查找1997 年下的訂單。2.DateTime.Month var q =from o in db.Orderswhere o.OrderDate.Value.Month == 12select o;語句描述:這個例子使用DateTime的Month屬性查找十二月下的訂單。3.DateTime.Day var q =from o in db.Orderswhere o.OrderDate.Value.Day == 31select o;語句描述:這個例子使用DateTime的Day屬性查找某月 31 日下的訂單。LINQ to SQL語句(15)之String 字符串(String)LINQ to SQL支持以下String方法。但是不同的是默認 情況下System.String方法區分大小寫。而SQL則不區分大小寫。1.字符串串聯(StringConcatenation) var q =from c in db.Customersselect new{c.CustomerID,Location = c.City + ", " + c.Country};語句描述:這個例子使用+運算符在形成經計算得出的客戶Location值過程中將字符串字段和字符串串聯在一起。2.String.Length var q =from p in db.Productswhere p.ProductName.Length < 10select p;語句描述:這個例子使用Length屬性查找名稱短于10個字符的所有產品。3.String.Contains(substring) var q =from c in db.Customerswhere c.ContactName.Contains ("Anders")select c;語句描述:這個例子使用Contains方法查找所有其聯系人姓名中包含“Anders”的客戶。4.String.IndexOf(substring) var q =from c in db.Customersselect new{c.ContactName,SpacePos = c.ContactName.IndexOf(" ")};語句描述:這個例子使用IndexOf方法查找每個客戶聯系人姓名中出現第一個空格的位置。5.String.StartsWith (prefix) var q =from c in db.Customerswhere c.ContactName.StartsWith("Maria")select c;語句描述:這個例子使用StartsWith方法查找聯系人姓名以“Maria”開頭的客戶。6.String.EndsWith(suffix) var q =from c in db.Customerswhere c.ContactName.EndsWith("Anders")select c;語句描述:這個例子使用EndsWith方法查找聯系人姓名以“Anders”結尾的客戶。7.String.Substring(start) var q =from p in db.Productsselect p.ProductName.Substring(3);語句描述:這個例子使用Substring方法返回產品名稱中從第四個字母開始的部分。8.String.Substring (start, length) var q =from e in db.Employeeswhere e.HomePhone.Substring(6, 3) == "555"select e;語句描述:這個例子使用Substring方法查找家庭電話號碼第七位到第九位是“555”的雇員。9.String.ToUpper() var q =from e in db.Employeesselect new{LastName = e.LastName.ToUpper(),e.FirstName};語句描述:這個例子使用ToUpper方法返回姓氏已轉換為大寫的雇員姓名。10.String.ToLower() var q =from c in db.Categoriesselect c.CategoryName.ToLower();語句描述:這個例子使用ToLower方法返回已轉換為小寫的類別名稱。11.String.Trim() var q =from e in db.Employeesselect e.HomePhone.Substring(0, 5).Trim ();語句描述:這個例子使用Trim方法返回雇員家庭電話號碼的前五位,并移除前導和尾隨空格。12.String.Insert(pos, str) var q =from e in db.Employeeswhere e.HomePhone.Substring(4, 1) == ")"select e.HomePhone.Insert(5, ":");語句描述:這個例子使用 Insert方法返回第五位為 ) 的雇員電話號碼的序列,并在 ) 后面插入一個 :。13.String.Remove(start) var q =from e in db.Employeeswhere e.HomePhone.Substring(4, 1) == ") "select e.HomePhone.Remove(9);語句描述:這個例子使用Remove方法返回第五位為 ) 的雇員電話號碼的序列,并移除從第十個字符開始的所有字符。14.String.Remove(start, length) var q =from e in db.Employeeswhere e.HomePhone.Substring(4, 1) == ")"select e.HomePhone.Remove(0, 6);語句描述:這個例子使用Remove方法返回第五位為 ) 的雇員電話號碼的序列,并移除前六個字符。15.String.Replace(find, replace) var q =from s in db.Suppliersselect new{s.CompanyName,Country = s.Country.Replace ("UK", "United Kingdom").Replace ("USA", "United States of America")};語句描述:這個例子使用 Replace 方法返回 Country 字段中UK 被替換為 United Kingdom 以及USA 被替換為 United States of America 的供 應商信息。LINQ to SQL語句(16)之對象標識 對象標識運行庫中的對象具有唯一標識。引用同一對象的兩個變量實際上是引用此對象的同一實例。你更改一個變量后,可以通過另一個變量看到這些更改。關系數據庫表中的行不具有唯一標識。由于每一行都具有唯一的主鍵,因此任何兩行都不會共用同一鍵值。實際上,通常我們是將數據從數據庫中提取出來放入另一層中,應用程序在該層對數據進行處理。這就是 LINQ to SQL 支持的模型。將數據作為行從數據庫中提取出來時,你不期望表示相同數據的兩行實際上對應于相同的行實例。如果您查詢特定客戶兩次,您將獲得兩行數據。每一行包含相同的信息。對于對象。你期望在你反復向 DataContext 索取相同的信息時,它實際上會為你提供同一對象實例。你將它們設計為層次結構或關系圖。你希望像檢索實物一樣檢索它們,而不希望僅僅因為你多次索要同一內容而收到大量的復制實例。在 LINQ to SQL 中, DataContext 管理對象標識。只要你從數據庫中檢索新行,該行就會由其主鍵記錄到標識表中,并且會創建一個新的對象。只要您檢索該行,就會將原始對象實例傳遞回應用程序。通過這種方式,DataContext 將數據庫看到的標識(即主鍵)的概念轉換成相應語言看到的標識(即實例)的概念。應用程序只看到處于第一次檢索時的狀態的對象。新數據如果不同,則會被丟棄。LINQ to SQL 使用此方法來管理本地對象的完整性,以支持開放式更新。由于在最初創建對象 后唯一發生的更改是由應用程序做出的,因此應用程序的意向是很明確的。如果在中間階段外部某一方做了更改,則在調用 SubmitChanges() 時會識別出這些更改。以上來自MSDN,的確,看了有點“正規”,下面我用兩個例子說明一下。對象緩存在第一個示例中,如果我們執行同一查詢兩次,則每次都會收到對內存中同一對象的引用。很明顯,cust1和cust2是同一個對象引用。Customer cust1 = db.Customers.First(c =>c.CustomerID == "BONAP");Customer cust2 = db.Customers.First(c =>c.CustomerID == "BONAP");下面的示例中,如果您執行返回數據庫中同一行的不同查詢,則您每次都會收到對內存中同一對象的引用。cust1和cust2是同一個對象引用,但是數據庫查詢了兩次。Customer cust1 = db.Customers.First(c =>c.CustomerID == "BONAP");Customer cust2 = (from o in db.Orderswhere o.Customer.CustomerID == "BONAP"select o ).First().Customer;LINQ to SQL語句(17)之對象加載 對象加載延遲加載在查詢某對象時,實際上你只查詢該對象。不會同時自動獲取這個對象。這就是延遲加載。例如,您可能需要查看客戶數據和訂單數據。你最初不一定需要檢索與每個客戶有關的所有訂單數據。其優點是你可以使用延遲加載將額外信息的檢索操作延遲到你確實需要檢索它們時再進行。請看下面的示例:檢索出來CustomerID,就根據這個ID查詢出OrderID。var custs =from c in db.Customerswhere c.City == "Sao Paulo"select c;//上面 的查詢句法不會導致語句立即執行,僅僅是一個描述性的語句,只有需要的時候才會執行它foreach (var cust in custs){foreach (var ord in cust.Orders){//同時查看客戶數據和訂單數據}}語句描述:原始查詢未請求數據,在所檢索到各個對象的鏈接中導航如何能導致觸發對數據庫的新查詢。預先加載:LoadWith 方法你如果想要同時查詢出一些對象的集合的方法。LINQ to SQL 提供了 DataLoadOptions用于立即加載對象。方法包括:LoadWith 方法,用于立即加載與主目標相關的數據。AssociateWith 方法,用于篩選為特定關系檢索到的對象。使用 LoadWith方法指定應同時檢索與主目標相關的哪些數據。例如,如果你知道你需要有關客戶的訂單的信息,則可以使用 LoadWith 來確保在檢索客戶信息的同時檢索訂單信息。使用此方法可僅訪問一次數據庫,但同時獲取兩組信息。在下面的示例中,我們通過設置DataLoadOptions,來指示DataContext 在加載Customers的同時把對應的Orders一起加載,在執行查詢時會檢索位于Sao Paulo的所有 Customers 的所有 Orders。這樣一來,連續訪問 Customer 對象的 Orders 屬性不會觸發新的數據庫查詢。在執行時生成的SQL語句使用了左連接。NorthwindDataContext db = newNorthwindDataContext ();DataLoadOptions ds = new DataLoadOptions();ds.LoadWith<Customer>(p =>p.Orders);db.LoadOptions = ds;var custs = (from c in db2.Customerswhere c.City == "Sao Paulo"select c);foreach (var cust in custs){foreach (var ord in cust.Orders){Console.WriteLine ("CustomerID {0} has an OrderID {1}.",cust.CustomerID,ord.OrderID);}}語句描述:在原始查詢過程中使用 LoadWith 請求相關數據,以便稍后在檢索到的各個對象中導航時不需要對數據庫進行額外的往返。LINQ to SQL語句(18)之運算符轉換 運算符轉換1.AsEnumerable:將類型轉換為泛型 IEnumerable使用 AsEnumerable<TSource> 可返回類型化為泛型 IEnumerable的參數。在 此示例中,LINQ toSQL(使用默認泛型 Query)會嘗試將查詢轉換為 SQL 并在服務器上執行。但 where 子句引用用戶定義的客戶端方法 (isValidProduct),此方法無法轉換為 SQL。解決方法是指定 where 的客戶端泛型 IEnumerable<T> 實現以替換泛型 IQueryable<T>。可通過調用 AsEnumerable<TSource>運算符來執行此操作。var q =from p in db.Products.AsEnumerable()where isValidProduct(p)select p;語句描述:這個例子就是使用AsEnumerable以便使用Where的客戶端IEnumerable實現,而不是默認的 IQueryable將在服務器上轉換為SQL并執行的默認Query<T>實現。這很有必要,因為Where子句引用了用戶定義的客戶端方法isValidProduct,該方法不能轉換為SQL。2.ToArray:將序列轉換為數組使用 ToArray <TSource>可從序列創建數組。var q =from c in db.Customerswhere c.City == "London"select c;Customer[] qArray = q.ToArray();語句描述:這個例子使用 ToArray 將查詢直接計算為數組。3.ToList:將序列轉換為泛型列表使用 ToList<TSource>可從序列創建泛型列表。下面的示例使用 ToList<TSource>直接將查詢的計算結果放入泛型 List<T>。var q =from e in db.Employeeswhere e.HireDate >= new DateTime(1994, 1, 1)select e;List<Employee> qList = q.ToList();4.ToDictionary:將序列轉化為字典使用Enumerable.ToDictionary<TSource, TKey>方法可 以將序列轉化為字典。TSource表示source中的元素的類型;TKey表示keySelector返回的鍵的類型。其返回一個包含鍵和值的Dictionary<TKey, TValue>。var q =from p in db.Productswhere p.UnitsInStock <= p.ReorderLevel && ! p.Discontinuedselect p;Dictionary<int, Product> qDictionary=q.ToDictionary(p => p.ProductID);foreach (int key in qDictionary.Keys){Console.WriteLine(key);}語句描述:這個例子使用 ToDictionary 將查詢和鍵表達式直接鍵表達式直接計算為 Dictionary<K, T>。LINQ to SQL語句(19)之ADO.NET與LINQ to SQL ADO.NET與LINQ to SQL它基于由 ADO.NET 提供程序模型提供的服務。因此,我們可以將 LINQ to SQL 代碼與現有的 ADO.NET 應用程序混合在一起,將當前 ADO.NET 解決方案遷移到 LINQ to SQL。1.連接在創建 LINQ to SQL DataContext 時,可以提供現有 ADO.NET 連接。對DataContext 的所有操作(包括查詢)都使用所提供的這個連接。如果此連接已經打開,則在您使用完此連接時,LINQ to SQL 會保持它的打開狀態不變。我們始終可以訪問此連接,另外還可以使用 Connection 屬性自行關閉它。//新建一個 標準的ADO.NET連接:SqlConnection nwindConn = new SqlConnection(connString);nwindConn.Open();// ... 其它的ADO.NET數據操作 代碼... ////利用現有的ADO.NET連接來創建一個DataContext:Northwind interop_db = new Northwind(nwindConn);var orders =from o in interop_db.Orderswhere o.Freight > 500.00Mselect o;//返回Freight>500.00M的訂單nwindConn.Close();語句描述:這個例子使用預先存在的ADO.NET 連接創建Northwind對象,本例中的查詢返回運費至少為500.00 的所有訂單。2.事務當我們已經啟動了自己的數據庫事務并且我們希望 DataContext 包含在內時,我們可以向 DataContext 提供此事務。通過 .NET Framework 創建事務的首選方法是使用 TransactionScope 對象。通過使用此方法,我們可以創建跨數據庫及其他駐留在內存中的資源管理器執行的分布式事務。事務范圍幾乎不需要資源就可以啟動。它們僅在事務范圍內存在多個連接時才將自身提升為分布式事務。using (TransactionScope ts = newTransactionScope()){db.SubmitChanges();ts.Complete();}注意:不能將此方法用于所有數據庫。例如,SqlClient 連接在針對 SQL Server 2000 服務器使用時無法提升系統事務。它采取的方法是,只要它發現有使用事務范圍的情況,它就會自動向完整的分布式事務登記。下面用一個例子說明一下事務的使用方法。在這里,也說明了重用 ADO.NET 命令和 DataContext 之間的同一連接。var q =from p in db.Productswhere p.ProductID == 3select p;//使用LINQ to SQL查詢出來//新建一個標準的ADO.NET連接:SqlConnection nwindConn = newSqlConnection(connString);nwindConn.Open();//利用現有的 ADO.NET連接來創建一個DataContext:Northwind interop_db = newNorthwind(nwindConn);SqlTransaction nwindTxn =nwindConn.BeginTransaction();try{SqlCommand cmd = new SqlCommand("UPDATE Products SET"+"QuantityPerUnit = 'single item' WHERE ProductID = 3");cmd.Connection = nwindConn;cmd.Transaction = nwindTxn;cmd.ExecuteNonQuery();interop_db.Transaction = nwindTxn;Product prod1 = interop_db.Products.First(p => p.ProductID == 4);Product prod2 = interop_db.Products.First(p => p.ProductID == 5);prod1.UnitsInStock -= 3;prod2.UnitsInStock -= 5;//這有一個錯 誤,不能為負數interop_db.SubmitChanges();nwindTxn.Commit();}catch (Exception e){// 如果有一個錯誤,所有的操作回滾Console.WriteLine (e.Message);}nwindConn.Close();語句描述:這個例子使用預先存在的 ADO.NET 連接創建 Northwind 對象,然后與此對象共享一個 ADO.NET 事務。此事務既用于通過 ADO.NET 連接執行 SQL 命令,又用于通過 Northwind 對象提交更改。當事務因違反 CHECK 約束而中止時,將回滾所有更改,包括通過 SqlCommand 做出的更改,以及通過Northwind 對象做出的更改。LINQ to SQL語句(20)之存儲過程 存儲過程在我們編寫程序中,往往需要一些存儲過程,在LINQ to SQL中怎么使用呢?也許比原來的更簡單些。下面我們以NORTHWND.MDF數據庫中自帶的幾個存儲過程來理解一下。1.標量返回在數據庫中,有名為 Customers Count By Region的存儲過程。該存儲過程返回顧客所在"WA"區域的數量。ALTER PROCEDURE [dbo]. [NonRowset](@param1 NVARCHAR(15))ASBEGINSET NOCOUNT ON;DECLARE @count intSELECT @count = COUNT(*)FROM CustomersWHERECustomers.Region = @Param1RETURN @countEND我們只要把這個存儲過程拖到O/R設計器內,它自動生成了以下代碼段:[Function(Name = "dbo.[Customers CountBy Region]")]public intCustomers_Count_By_Region([Parameter(DbType = "NVarChar (15)")]string param1){IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo) (MethodInfo.GetCurrentMethod())), param1);return ((int) (result.ReturnValue));}我們需要時,直接調用就可以了,例如:int count = db.CustomersCountByRegion("WA");Console.WriteLine(count);語句描述:這個實例使用存儲過程返回在“WA”地區的客戶數。2.單一結果集從數據庫中返回行集合,并包含用于篩選結果的輸入參數。當我們執行 返回行集合的存儲過程時,會用到結果類,它存儲從存儲過程中返回的結果。下面的示例表示一個存儲過程,該存儲過程返回客戶行并使用輸入參數來僅返回將“London”列為客戶城市的那些行的固定幾列。 ALTER PROCEDURE [dbo].[Customers By City]-- Add the parameters for the stored procedure here(@param1 NVARCHAR(20))ASBEGIN-- SET NOCOUNT ON added to prevent extra result sets from-- interfering with SELECT statements.SET NOCOUNT ON;SELECT CustomerID, ContactName, CompanyName, City fromCustomers as c where c.City=@param1END拖到O/R設計器內,它自動生成了以下代碼段:[Function(Name="dbo.[Customers ByCity]")]publicISingleResult<Customers_By_CityResult> Customers_By_City([Parameter(DbType="NVarChar(20)")]string param1){IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo) (MethodInfo.GetCurrentMethod())), param1);return ((ISingleResult<Customers_By_CityResult>)(result.ReturnValue));}我們用下面的代碼調用:ISingleResult<Customers_By_CityResult>result =db.Customers_By_City("London");foreach (Customers_By_CityResult cust inresult){Console.WriteLine("CustID={0}; City={1}",cust.CustomerID,cust.City);}語句描述:這個實例使用存儲過程返回在倫敦的客戶的 CustomerID和City。3.多個可能形狀的單一結果集當存儲過程可以返回多個結果形狀時,返回類型無法強類型化為單個投影形狀。盡管 LINQ to SQL 可以生成所有可能的投影類型,但它無法獲知將以何種順序返回它們。 ResultTypeAttribute 屬性適用于返回多個結果類型的存儲過程,用以指定該過程可以返回的類型的集合。在下面的 SQL 代碼示例中,結果形狀取決于輸入(param1 = 1或param1 = 2)。我們不知道先返回哪個投影。ALTER PROCEDURE [dbo].[SingleRowset_MultiShape]-- Add the parameters for the stored procedure here(@param1 int )ASBEGIN-- SET NOCOUNT ON added to prevent extra result sets from-- interfering with SELECT statements.SET NOCOUNT ON;if(@param1 = 1)SELECT * from Customers as c where c.Region = 'WA'else if (@param1 = 2)SELECT CustomerID, ContactName, CompanyName fromCustomers as c where c.Region = 'WA'END拖到O/R 設計器內,它自動生成了以下代碼段:[Function (Name="dbo.[Whole Or PartialCustomers Set]")]publicISingleResult<Whole_Or_Partial_Customers_SetResult>Whole_Or_Partial_Customers_Set([Parameter(DbType="Int")]System.Nullable<int> param1){IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);return ((ISingleResult<Whole_Or_Partial_Customers_SetResult>)(result.ReturnValue));}但是,VS2008會把多結果集存儲過程識別為單結果集的存儲過程,默認生成的代碼我們要手動修改一下,要求返回多個結果集,像這樣:[Function(Name="dbo.[Whole Or PartialCustomers Set]")][ResultType(typeof (WholeCustomersSetResult))][ResultType(typeof(PartialCustomersSetResult))]public IMultipleResultsWhole_Or_Partial_Customers_Set([Parameter(DbType="Int")]System.Nullable<int> param1){IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo)(MethodInfo.GetCurrentMethod())), param1);return ((IMultipleResults)(result.ReturnValue));}我們分別定義了兩個分部類,用于指定返回的類型。WholeCustomersSetResult類 如 下:public partial classWholeCustomersSetResult{private string _CustomerID;private string _CompanyName;private string _ContactName;private string _ContactTitle;private string _Address;private string _City;private string _Region;private string _PostalCode;private string _Country;private string _Phone;private string _Fax;public WholeCustomersSetResult(){}[Column (Storage = "_CustomerID", DbType ="NChar(5)")]public string CustomerID{get { return this._CustomerID; }set{if ((this._CustomerID != value))this._CustomerID = value;}}[Column(Storage = "_CompanyName", DbType ="NVarChar(40)")]public string CompanyName{get { return this._CompanyName; }set{if ((this._CompanyName != value))this._CompanyName = value;}}[Column (Storage = "_ContactName", DbType ="NVarChar(30) ")]public string ContactName{get { return this._ContactName; }set{if ((this._ContactName != value))this._ContactName = value;}}[Column (Storage = "_ContactTitle", DbType ="NVarChar(30) ")]public string ContactTitle{get { return this._ContactTitle; }set{if ((this._ContactTitle != value))this._ContactTitle = value;}}[Column(Storage = "_Address", DbType = "NVarChar(60)")]public string Address{get { return this._Address; }set{if ((this._Address != value))this._Address = value;}}[Column(Storage = "_City", DbType = "NVarChar(15)")]public string City{get { return this._City; }set{if ((this._City != value))this._City = value;}}[Column(Storage = "_Region", DbType = "NVarChar(15)")]public string Region{get { return this._Region; }set{if ((this._Region != value))this._Region = value;}}[Column(Storage = "_PostalCode", DbType ="NVarChar(10)")]public string PostalCode{get { return this._PostalCode; }set{if ((this._PostalCode != value))this._PostalCode = value;}}[Column(Storage = "_Country", DbType ="NVarChar(15)")]public string Country{get { return this._Country; }set{if ((this._Country != value))this._Country = value;}}[Column(Storage = "_Phone", DbType ="NVarChar(24)")]public string Phone{get { return this._Phone; }set{if ((this._Phone != value))this._Phone = value;}}[Column(Storage = "_Fax", DbType ="NVarChar(24)")]public string Fax{get { return this._Fax; }set{if ((this._Fax != value))this._Fax = value;}}}PartialCustomersSetResult類 如下:public partial classPartialCustomersSetResult{private string _CustomerID;private string _ContactName;private string _CompanyName;public PartialCustomersSetResult(){}[Column (Storage = "_CustomerID", DbType ="NChar(5)")]public string CustomerID{get { return this._CustomerID; }set{if ((this._CustomerID != value))this._CustomerID = value;}}[Column(Storage = "_ContactName", DbType ="NVarChar(30)")]public string ContactName{get { return this._ContactName; }set{if ((this._ContactName != value))this._ContactName = value;}}[Column (Storage = "_CompanyName", DbType ="NVarChar(40) ")]public string CompanyName{get { return this._CompanyName; }set{if ((this._CompanyName != value))this._CompanyName = value;}}}這樣就可以使用了,下面代碼直接調用,分別返回各自的結果集合。//返回全部Customer結果集IMultipleResults result =db.Whole_Or_Partial_Customers_Set(1);IEnumerable<WholeCustomersSetResult>shape1 =result.GetResult<WholeCustomersSetResult>();foreach (WholeCustomersSetResult compNamein shape1){Console.WriteLine(compName.CompanyName);}//返回部分 Customer結果集result =db.Whole_Or_Partial_Customers_Set(2);IEnumerable<PartialCustomersSetResult>shape2 =result.GetResult<PartialCustomersSetResult>();foreach (PartialCustomersSetResult con inshape2){Console.WriteLine(con.ContactName);}語句描述:這個實例使用存儲過程返回“WA”地區中的一組客戶。返回的結果集形狀取決于傳入的參數。如果參數等于 1,則返回所有客戶屬性。如果參數等于2,則返回ContactName屬性。4.多個結果集這種存儲過程可以生成多個結果形狀,但我們已經知道結果的返回順序。下面是一個按順序返回多個結果集的存儲過程Get Customer And Orders。 返回顧客ID為"SEVES"的顧客和他們所有的訂單。ALTER PROCEDURE [dbo].[Get Customer AndOrders](@CustomerID nchar(5))-- Add the parameters for the stored procedure hereASBEGIN-- SET NOCOUNT ON added to prevent extra result sets from-- interfering with SELECT statements.SET NOCOUNT ON;SELECT * FROM Customers AS c WHERE c.CustomerID = @CustomerID SELECT * FROM Orders AS o WHERE o.CustomerID = @CustomerIDEND拖到設計器代碼如下:[Function (Name="dbo.[Get Customer AndOrders]")]publicISingleResult<Get_Customer_And_OrdersResult>Get_Customer_And_Orders([Parameter(Name="CustomerID",DbType="NChar(5)")] stringcustomerID){IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo)(MethodInfo.GetCurrentMethod())), customerID);return ((ISingleResult<Get_Customer_And_OrdersResult>)(result.ReturnValue));}同樣,我們要修改自動生成的代碼:[Function(Name="dbo.[Get Customer AndOrders] ")][ResultType(typeof(CustomerResultSet))][ResultType(typeof(OrdersResultSet))]public IMultipleResultsGet_Customer_And_Orders([Parameter(Name="CustomerID",DbType="NChar(5)")]string customerID){IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo) (MethodInfo.GetCurrentMethod())), customerID);return ((IMultipleResults)(result.ReturnValue));}同樣,自己手寫類,讓其存儲過程返回各自的結果集。CustomerResultSet類public partial class CustomerResultSet{private string _CustomerID;private string _CompanyName;private string _ContactName;private string _ContactTitle;private string _Address;private string _City;private string _Region;private string _PostalCode;private string _Country;private string _Phone;private string _Fax;public CustomerResultSet(){}[Column(Storage = "_CustomerID", DbType ="NChar(5)")]public string CustomerID{get { return this._CustomerID; }set{if ((this._CustomerID != value))this._CustomerID = value;}}[Column(Storage = "_CompanyName", DbType ="NVarChar(40)")]public string CompanyName{get { return this._CompanyName; }set{if ((this._CompanyName != value))this._CompanyName = value;}}[Column (Storage = "_ContactName", DbType ="NVarChar(30) ")]public string ContactName{get { return this._ContactName; }set{if ((this._ContactName != value))this._ContactName = value;}}[Column (Storage = "_ContactTitle", DbType ="NVarChar(30) ")]public string ContactTitle{get { return this._ContactTitle; }set{if ((this._ContactTitle != value))this._ContactTitle = value;}}[Column(Storage = "_Address", DbType = "NVarChar(60)")]public string Address{get { return this._Address; }set{if ((this._Address != value))this._Address = value;}}[Column(Storage = "_City", DbType ="NVarChar(15)")]public string City{get { return this._City; }set{if ((this._City != value))this._City = value;}}[Column(Storage = "_Region", DbType = "NVarChar(15)")]public string Region{get { return this._Region; }set{if ((this._Region != value))this._Region = value;}}[Column(Storage = "_PostalCode", DbType ="NVarChar(10)")]public string PostalCode{get { return this._PostalCode; }set{if ((this._PostalCode != value))this._PostalCode = value;}}[Column(Storage = "_Country", DbType ="NVarChar(15)")]public string Country{get { return this._Country; }set{if ((this._Country != value))this._Country = value;}}[Column(Storage = "_Phone", DbType ="NVarChar(24)")]public string Phone{get { return this._Phone; }set{if ((this._Phone != value))this._Phone = value;}}[Column(Storage = "_Fax", DbType ="NVarChar(24)")]public string Fax{get { return this._Fax; }set{if ((this._Fax != value))this._Fax = value;}}}OrdersResultSet 類public partial class OrdersResultSet{private System.Nullable<int> _OrderID;private string _CustomerID;private System.Nullable<int> _EmployeeID;private System.Nullable<System.DateTime> _OrderDate;private System.Nullable<System.DateTime> _RequiredDate;private System.Nullable<System.DateTime> _ShippedDate;private System.Nullable<int> _ShipVia;private System.Nullable<decimal> _Freight;private string _ShipName;private string _ShipAddress;private string _ShipCity;private string _ShipRegion;private string _ShipPostalCode;private string _ShipCountry;public OrdersResultSet(){}[Column(Storage = "_OrderID", DbType = "Int")]public System.Nullable<int> OrderID{get { return this._OrderID; }set{if ((this._OrderID != value))this._OrderID = value;}}[Column(Storage = "_CustomerID", DbType ="NChar(5)")]public string CustomerID{get { return this._CustomerID; }set{if ((this._CustomerID != value))this._CustomerID = value;}}[Column(Storage = "_EmployeeID", DbType ="Int")]public System.Nullable<int> EmployeeID{get { return this._EmployeeID; }set{if ((this._EmployeeID != value))this._EmployeeID = value;}}[Column(Storage = "_OrderDate", DbType ="DateTime")]public System.Nullable<System.DateTime> OrderDate{get { return this._OrderDate; }set{if ((this._OrderDate != value))this._OrderDate = value;}}[Column (Storage = "_RequiredDate", DbType ="DateTime")]public System.Nullable<System.DateTime> RequiredDate{get { return this._RequiredDate; }set{if ((this._RequiredDate != value))this._RequiredDate = value;}}[Column(Storage = "_ShippedDate", DbType ="DateTime")]public System.Nullable<System.DateTime> ShippedDate{get { return this._ShippedDate; }set{if ((this._ShippedDate != value))this._ShippedDate = value;}}[Column(Storage = "_ShipVia", DbType = "Int")]public System.Nullable<int> ShipVia{get { return this._ShipVia; }set{if ((this._ShipVia != value))this._ShipVia = value;}}[Column (Storage = "_Freight", DbType ="Money")]public System.Nullable<decimal> Freight{get { return this._Freight; }set{if ((this._Freight != value))this._Freight = value;}}[Column (Storage = "_ShipName", DbType ="NVarChar(40)")]public string ShipName{get { return this._ShipName; }set{if ((this._ShipName != value))this._ShipName = value;}}[Column(Storage = "_ShipAddress", DbType ="NVarChar(60)")]public string ShipAddress{get { return this._ShipAddress; }set{if ((this._ShipAddress != value))this._ShipAddress = value;}}[Column (Storage = "_ShipCity", DbType ="NVarChar(15)")]public string ShipCity{get { return this._ShipCity; }set{if ((this._ShipCity != value))this._ShipCity = value;}}[Column(Storage = "_ShipRegion", DbType ="NVarChar(15)")]public string ShipRegion{get { return this._ShipRegion; }set{if ((this._ShipRegion != value))this._ShipRegion = value;}}[Column(Storage = "_ShipPostalCode", DbType ="NVarChar(10)")]public string ShipPostalCode{get { return this._ShipPostalCode; }set{if ((this._ShipPostalCode != value))this._ShipPostalCode = value;}}[Column(Storage = "_ShipCountry", DbType = "NVarChar(15)")]public string ShipCountry{get { return this._ShipCountry; }set{if ((this._ShipCountry != value))this._ShipCountry = value;}}}這時,只要調用就可以了。IMultipleResults result =db.Get_Customer_And_Orders("SEVES");//返回 Customer結果集IEnumerable<CustomerResultSet>customer =result.GetResult<CustomerResultSet>();//返回Orders結果集IEnumerable<OrdersResultSet> orders =result.GetResult<OrdersResultSet>();//在這里,我們讀取CustomerResultSet中的數據foreach (CustomerResultSet cust incustomer){Console.WriteLine(cust.CustomerID);}語句描述:這個實例使用存儲過程返回客戶“SEVES”及其所有訂單。5.帶輸出參數LINQ to SQL 將輸出參數映射到引用參數 ,并且對于值類型,它將參數聲明為可以為null。下面的示例帶有單個輸入參數(客戶 ID)并返回一個輸出參數(該客戶的總銷售額)。ALTER PROCEDURE [dbo].[CustOrderTotal]@CustomerID nchar(5),@TotalSales money OUTPUTASSELECT @TotalSales =SUM(OD.UNITPRICE*(1-OD.DISCOUNT) * OD.QUANTITY)FROM ORDERS O, "ORDER DETAILS" ODwhere O.CUSTOMERID = @CustomerID AND O.ORDERID= OD.ORDERID把這個存儲過程拖到設計器中,圖片如下:其生成代碼如下:[Function(Name="dbo.CustOrderTotal")]public int CustOrderTotal ([Parameter(Name="CustomerID",DbType="NChar(5) ")]string customerID,[Parameter (Name="TotalSales",DbType="Money")]ref System.Nullable<decimal> totalSales){IExecuteResult result = this.ExecuteMethodCall(this,((MethodInfo)(MethodInfo.GetCurrentMethod())),customerID, totalSales);totalSales = ((System.Nullable<decimal>)(result.GetParameterValue(1)));return ((int) (result.ReturnValue));}我們使用下面的語句調用此存儲過程:注意:輸出參數是按引用傳遞的,以支持參數為“in/out”的方案。在這種情況下,參數僅為“out”。decimal? totalSales = 0;string customerID = "ALFKI";db.CustOrderTotal(customerID, reftotalSales);Console.WriteLine("Total Sales forCustomer '{0}' = {1:C}",customerID, totalSales);語句描述:這個實例使用返回 Out 參數的存儲過程。好了,就說到這里了,其增刪改操作同理。相信大家通過這5個實例理解了存儲過程。LINQ to SQL語句(21)之用戶定義函數 用戶定義函數我們可以在LINQ to SQL中使用用戶定義函數。只要把用戶定義函數拖到O/R設計器中,LINQ to SQL自動使用FunctionAttribute屬性和ParameterAttribute屬性(如果需要)將其函數指定為方法。這時,我們只需簡單調用即可。在這里注意:使用用戶定義函數的時候必須滿足以下形式之一,否則會出現InvalidOperationException異常情況。具有正確映射屬性的方法調用的函數。這里使用FunctionAttribute屬性和 ParameterAttribute屬性。特定于LINQ to SQL的靜態SQL方法。.NET Framework方法支持的函數。下面介紹幾個例子:1.在Select中使用用戶定義的標量函數所謂標量函數是指返回在 RETURNS 子句中定義的類型的單個數據值。可以使用所有標量數據類型,包括 bigint 和 sql_variant。不支持 timestamp 數據類型、用戶定義數據類型和非標量類型(如 table 或 cursor)。在 BEGIN...END 塊中定義的函數主體包含返回該值的 Transact-SQL 語句系列。返回類型可以是除 text、ntext、image 、cursor 和 timestamp 之外的任何數據類型。我們在系統自帶的 NORTHWND.MDF數據庫中,有3個自定義函數,這里使用 TotalProductUnitPriceByCategory,其代碼如下:ALTER FUNCTION[dbo].[TotalProductUnitPriceByCategory](@categoryID int)RETURNS MoneyASBEGIN-- Declare the return variable hereDECLARE @ResultVar Money-- Add the T-SQL statements to compute the return value hereSELECT @ResultVar = (Select SUM(UnitPrice)from Productswhere CategoryID = @categoryID)-- Return the result of the functionRETURN @ResultVarEND我們將其拖到設計器中,LINQ to SQL通過使用 FunctionAttribute 屬性將類中定義的客戶端方法映射到用戶定義的函數。請注意,這個方法體會構造一個捕獲方法調用意向的表達式,并將該表達式傳遞給 DataContext 進行轉換和執行。[Function(Name="dbo.TotalProductUnitPriceByCategory",IsComposable=true)]public System.Nullable<decimal>TotalProductUnitPriceByCategory([Parameter (DbType="Int")]System.Nullable<int> categoryID){return ((System.Nullable<decimal>)(this.ExecuteMethodCall(this,((MethodInfo) (MethodInfo.GetCurrentMethod())), categoryID).ReturnValue));}我們使用時,可以用以下代碼來調用:var q = from c in db.Categoriesselect new{c.CategoryID,TotalUnitPrice =db.TotalProductUnitPriceByCategory(c.CategoryID)};這時,LINQ to SQL自動生成SQL語句如下:SELECT [t0].[CategoryID],CONVERT(Decimal(29,4),[dbo].[TotalProductUnitPriceByCategory]([t0].[CategoryID]))AS [TotalUnitPrice] FROM [dbo].[Categories]AS [t0]2.在Where從句中 使用用戶定義的標量函數 這個例子使用方法同上一個例子原理基本相同了,MinUnitPriceByCategory自定義函數如下:ALTER FUNCTION[dbo].[MinUnitPriceByCategory](@categoryID INT)RETURNS MoneyASBEGIN-- Declare the return variable hereDECLARE @ResultVar Money-- Add the T -SQL statements to compute the return value hereSELECT @ResultVar = MIN(p.UnitPrice) FROM Products as pWHERE p.CategoryID = @categoryID-- Return the result of the functionRETURN @ResultVarEND拖到設計器中,生成代碼如下:[Function (Name="dbo.MinUnitPriceByCategory",IsComposable=true)]public System.Nullable<decimal>MinUnitPriceByCategory([Parameter(DbType="Int")]System.Nullable<int> categoryID){return ((System.Nullable<decimal>) (this.ExecuteMethodCall(this, ((MethodInfo) (MethodInfo.GetCurrentMethod())),categoryID).ReturnValue));}這時可以使用了:注意這里在 LINQ to SQL 查詢中,對生成的用戶定義函數方法 MinUnitPriceByCategory的內聯調用。此函數不會立即執行,這是因為查詢會延 遲執行。延遲執行的查詢中包含的函數直到此查詢執行時才會執行。為此查詢生成的 SQL 會轉換成對數據庫中用戶定義函數的調用(請參見此查詢后面的生成的 SQL語句),當在查詢外部調用這個函數時,LINQ to SQL 會用方法調用表達式創建一個簡單查詢并執行。 var q =from p in db.Productswhere p.UnitPrice ==db.MinUnitPriceByCategory(p.CategoryID)select p;它自動生成的SQL語句如下:SELECT [t0]. [ProductID],[t0].[ProductName], [t0].[SupplierID],[t0]. [CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],[t0]. [UnitsInStock],[t0].[UnitsOnOrder],[t0].[ReorderLevel],[t0]. [Discontinued]FROM [dbo].[Products]AS [t0]WHERE [t0]. [UnitPrice] =[dbo].[MinUnitPriceByCategory]([t0].[CategoryID])3.使用用戶定義的表值函數表值函數返回單個行集(與存儲過程不同,存儲過程可返回多個結果形狀)。由于表值函數的返回類型為 Table,因此在 SQL 中可以使用表的任何地方均可以使用表值函數。此外,您還可以完全像處理表那樣來處理表值函數。下面的 SQL 用戶定義函數顯式聲明其返回一個 TABLE。因此,隱式定義了所返回的行集結構。ALTER FUNCTION[dbo].[ProductsUnderThisUnitPrice](@price Money)RETURNS TABLEASRETURNSELECT *FROM Products as PWhere p.UnitPrice < @price拖到設計器中,LINQ to SQL 按如下方式映射此函數:[Function(Name="dbo.ProductsUnderThisUnitPrice",IsComposable=true)]publicIQueryable<ProductsUnderThisUnitPriceResult>ProductsUnderThisUnitPrice([Parameter(DbType="Money")]System.Nullable<decimal> price){return this.CreateMethodCallQuery<ProductsUnderThisUnitPriceResult>(this,((MethodInfo) (MethodInfo.GetCurrentMethod())), price);}這時我們小小的修改一下Discontinued屬性為可空的bool類型。private System.Nullable<bool>_Discontinued;public System.Nullable<bool>Discontinued{}我們可以這樣調用使用了:var q = from p indb.ProductsUnderThisUnitPrice(10.25M)where ! (p.Discontinued ?? false)select p;其生成 SQL語句如下:SELECT [t0].[ProductID],[t0].[ProductName], [t0].[SupplierID],[t0].[CategoryID], [t0].[QuantityPerUnit],[t0].[UnitPrice],[t0].[UnitsInStock], [t0].[UnitsOnOrder],[t0].[ReorderLevel],[t0].[Discontinued]FROM [dbo].[ProductsUnderThisUnitPrice](@p0) AS [t0]WHERE NOT ((COALESCE([t0].[Discontinued],@p1)) = 1)-- @p0: Input Money (Size = 0; Prec = 19;Scale = 4) [10.25]-- @p1: Input Int (Size = 0; Prec = 0;Scale = 0) [0]4.以聯接方式使用用戶定義的表值函數我們利用上面的ProductsUnderThisUnitPrice用戶定義函數,在 LINQ to SQL 中, 調用如下:var q =from c in db.Categoriesjoin p in db.ProductsUnderThisUnitPrice(8.50M) onc.CategoryID equals p.CategoryID into prodsfrom p in prodsselect new{c.CategoryID,c.CategoryName,p.ProductName,p.UnitPrice};其生成的 SQL 代碼說明對此函數返回的表執行聯接。SELECT [t0].[CategoryID], [t0]. [CategoryName],[t1].[ProductName], [t1].[UnitPrice]FROM [dbo].[Categories] AS [t0]CROSS JOIN [dbo].[ProductsUnderThisUnitPrice](@p0) AS [t1]WHERE ([t0]. [CategoryID]) =[t1].[CategoryID]-- @p0: Input Money (Size = 0; Prec = 19;Scale = 4) [8.50]LINQ to SQL語句(22)之DataContext DataContextDataContext作為LINQ to SQL框架的主入口點,為我們 提供了一些方法和屬性,本文用幾個例子說明DataContext幾個典型的應用。創建和刪除數據庫CreateDatabase方法用于在服務器上創建數據庫。DeleteDatabase方法用于刪除由DataContext連接字符串標識的數據 庫。數據庫的名稱有以下方法來定義:如果數據庫在連接字符串中標識,則使用該連接字符串的名稱。如果存在DatabaseAttribute屬性 (Attribute),則將其Name屬性(Property)用作數據庫的名稱。如果連接字符串中沒有數據庫標記,并且使用強類型的DataContext,則會檢查與 DataContext繼承類名稱相同的數據庫。如果使用弱類型的DataContext,則會引發異常。如果已通過使用文件名創建了DataContext,則會創建與該文件名相對應的數據庫。我們首先用實體類描述關系數據庫表和列的結構的屬性。再調用DataContext的CreateDatabase方法,LINQ to SQL會用我們的定義的實體類結構來構造一個新的數據庫實例。還可以通過使用 .mdf 文件或只使用目錄名(取決于連接字符串),將 CreateDatabase與SQL Server一起使用。 LINQ to SQL使用連接字符串來定義要創建的數據庫和作為數據庫創建位置的服務器。說了這么多,用一段實例說明一下吧!首先,我們新建一個NewCreateDB類用于創建一個名為NewCreateDB.mdf的新數據庫,該數據庫有一個Person表,有三個字段,分別為PersonID、PersonName、Age。public class NewCreateDB : DataContext{public Table<Person> Persons;public NewCreateDB (string connection):base(connection){}public NewCreateDB(System.Data.IDbConnection connection):base(connection){}}[Table(Name = "Person")]public partial class Person :INotifyPropertyChanged{private int _PersonID;private string _PersonName;private System.Nullable<int> _Age;public Person() { }[Column(Storage = "_PersonID", DbType = "INT",IsPrimaryKey = true)]public int PersonID{get { return this._PersonID; }set{if ((this._PersonID != value)){this.OnPropertyChanged("PersonID");this._PersonID = value;this.OnPropertyChanged ("PersonID");}}}[Column(Storage = "_PersonName", DbType ="NVarChar(30)")]public string PersonName{get { return this._PersonName; }set{if ((this._PersonName != value)){this.OnPropertyChanged ("PersonName");this._PersonName = value;this.OnPropertyChanged ("PersonName");}}}[Column(Storage = "_Age", DbType = "INT")]public System.Nullable<int> Age{get { return this._Age; }set{if ((this._Age != value)){this.OnPropertyChanged("Age");this._Age = value;this.OnPropertyChanged("Age");}}}public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged (string PropertyName){if ((this.PropertyChanged != null)){this.PropertyChanged(this,new PropertyChangedEventArgs(PropertyName));}}}接下來的一段代碼先創建一個數據庫,在調用 CreateDatabase后,新的數據庫就會存在并且會接受一般的查詢和命令。接著插入一條記錄并且查詢。最后刪除這個數據庫。//1.新建一個臨時 文件夾來存放新建的數據庫string userTempFolder =Environment.GetEnvironmentVariable("SystemDrive") +@"YJingLee";Directory.CreateDirectory (userTempFolder);//2.新建數據庫NewCreateDBstring userMDF = System.IO.Path.Combine(userTempFolder,@"NewCreateDB.mdf");string connStr = String.Format (@"DataSource=.SQLEXPRESS;AttachDbFilename={0};IntegratedSecurity=True;Connect Timeout=30;User Instance=True;Integrated Security = SSPI;",userMDF);NewCreateDB newDB = newNewCreateDB(connStr);newDB.CreateDatabase();//3.插入 數據并查詢var newRow = new Person{PersonID = 1,PersonName = "YJingLee",Age = 22};newDB.Persons.InsertOnSubmit(newRow);newDB.SubmitChanges();var q = from x in newDB.Personsselect x;//4.刪除數據庫newDB.DeleteDatabase();//5.刪除臨時目錄Directory.Delete (userTempFolder);數據庫驗證DatabaseExists方法用于 嘗試通過使用DataContext中的連接打開數據庫,如果成功返回true。下面代碼說明是否存在Northwind數據庫和NewCreateDB數據庫。// 檢測Northwind數據庫是否存在if (db.DatabaseExists())Console.WriteLine("Northwind數據庫存在");elseConsole.WriteLine("Northwind數據庫不存在");//檢測 NewCreateDB數據庫是否存在string userTempFolder =Environment.GetEnvironmentVariable("Temp");string userMDF =System.IO.Path.Combine(userTempFolder,@"NewCreateDB.mdf");NewCreateDB newDB = newNewCreateDB(userMDF);if (newDB.DatabaseExists())Console.WriteLine("NewCreateDB數據庫存在");elseConsole.WriteLine("NewCreateDB數據庫不存在 ");數據庫更改SubmitChanges方法計算要插入、更 新或刪除的已修改對象的集,并執行相應命令以實現對數據庫的更改。無論對象做了多少項更改,都只是在更改內存中的副本。并未對數據庫中的實際數據做任何更改。直到對DataContext顯式調用SubmitChanges,所做的更改才會傳輸到服務器。調用時,DataContext會設法將我們所做的更改轉換為等效的SQL 命令。我們也可以使用自己的自定義邏輯來重寫這些操作,但提交順序是由 DataContext的一項稱作“更改處理器”的服務來協調的。事件的順序如下:當調用SubmitChanges時,LINQ to SQL會檢查已知對象的集合以確定新實例是否已附加到它們。如果已附加,這些新實例將添加到被跟蹤對象的集合。所有具有掛起更改的對象將按照它們之間的依賴關系排序成一個對象序列。如果一個對象的更改依賴于其他對象,則這個對象將排在其依賴項之后。在即將傳輸任何實際更改時,LINQ to SQL會啟動一個事務來封裝由各條命令組成的系列。對對象的更改會逐個轉換為SQL命令,然后發送到服務器。如果數據庫檢測到任何錯誤,都會造成提交進程停止并引發異常。將回滾對數據庫的所有更改,就像未進行過提交一樣。DataContext 仍具有所有更改的完整記錄。下面代碼說明的是在數據庫中查詢CustomerID 為ALFKI的顧客,然后修改其公司名稱,第一次更新并調用SubmitChanges()方法,第二次更新了數據但并未調用SubmitChanges()方法。//查詢Customer cust = db.Customers.First(c =>c.CustomerID == "ALFKI");//更新數據并調用SubmitChanges()方法cust.CompanyName = "YJingLee'sBlog";db.SubmitChanges();//更新數據沒有調用SubmitChanges()方法cust.CompanyName ="http://lyj.cnblogs.com";動態查詢使用動態查詢,這個例子用CreateQuery()方法創建一個 IQueryable<T>類型表達式輸出查詢的語句。這里給個例子說明一下。有關動態查詢具體內容,下一篇介紹。var c1 =Expression.Parameter(typeof(Customer), "c");PropertyInfo City =typeof(Customer).GetProperty ("City");var pred =Expression.Lambda<Func<Customer, bool>>(Expression.Equal(Expression.Property(c1, City),Expression.Constant("Seattle")), c1);IQueryable custs = db.Customers;Expression expr =Expression.Call(typeof(Queryable), "Where",new Type[] { custs.ElementType }, custs.Expression, pred);IQueryable<Customer> q =db.Customers.AsQueryable().Provider.CreateQuery<Customer>(expr);日志Log屬性用于將SQL查詢或命令打印到TextReader。此方法對了解 LINQto SQL 功能和調試特定的問題可能很有用。下面的示例使用Log屬性在 SQL代碼執行前在控制臺窗口中顯示此代碼。我們可以將此屬性與查詢、插入、更新和刪除命令一起使用。//關閉日志功能//db.Log = null;//使用日志功能:日志輸出到控制臺窗口db.Log = Console.Out;var q = from c in db.Customerswhere c.City == "London"select c;//日志輸出到 文件StreamWriter sw = newStreamWriter(Server.MapPath ("log.txt"), true);db.Log = sw;var q = from c in db.Customerswhere c.City == "London"select c;sw.Close();LINQ to SQL語句(23)之動態查詢 動態查詢有這樣一個場景:應用程序可能會提供一個用戶界面,用戶可以使用該用戶界面指定一個或多個謂詞來篩選數據。這種情況在編譯時不知道查詢的細節,動態查詢將十分有用。在LINQ中,Lambda表達式是許多標準查詢運算符的基礎,編譯器創建lambda表達式以捕獲基礎查詢方法(例如 Where、Select、Order By、Take While 以及其他方法)中定義的計算。表達式目錄樹用于針對數據源的結構化查詢,這些數據源實現IQueryable<T>。例如,LINQ to SQL 提供程序實現 IQueryable<T>接口,用于查詢關系數據存儲。C#和Visual Basic編譯器會針對此類數據源的查詢編譯為代碼,該代碼在運行時將生成一個表達式目錄樹。然后,查詢提供程序可以遍歷表達式目錄樹數據結構,并將其轉換為適合于數據源的查詢語言。表達式目錄樹在 LINQ中用于表示分配給類型為Expression<TDelegate>的變量的Lambda表 達式。還可用于創建動態LINQ查詢。System.Linq.Expressions命名空間 提供用于手動生成表達式目錄樹的API。Expression類包含創建特定類型的表達 式目錄樹節點的靜態工廠方法,例如,ParameterExpression(表示一個已命名的參數表達式)或 MethodCallExpression(表示一個方法調用)。編譯器生成的表達式目錄樹的根始終在類型Expression<TDelegate>的節點中,其中 TDelegate是包含至多五個輸入參數的任何TDelegate委托;也就是說,其根節點是表示一個lambda表達式。下面幾個例子描述如何使用表達式目錄樹來創建動態LINQ查詢。1.Select下面例子說明如何使用表達式樹依據 IQueryable 數據源構造一個動態查詢,查詢出每個顧客的ContactName,并用GetCommand方法獲取其生成SQL語句。//依據IQueryable數據 源構造一個查詢IQueryable<Customer> custs =db.Customers;//組建一個表達式樹來創建一個參數ParameterExpression param =Expression.Parameter(typeof (Customer), "c");//組建表達式樹:c.ContactNameExpression selector =Expression.Property(param,typeof (Customer).GetProperty("ContactName"));Expression pred =Expression.Lambda(selector, param);//組建表達式樹:Select(c=>c.ContactName)Expression expr = Expression.Call(typeof(Queryable), "Select",new Type[] { typeof (Customer), typeof(string) },Expression.Constant(custs), pred);//使用表達式樹來生成動態查詢IQueryable<string> query =db.Customers.AsQueryable().Provider.CreateQuery<string>(expr);//使用GetCommand方法 獲取SQL語句System.Data.Common.DbCommand cmd =db.GetCommand (query);Console.WriteLine(cmd.CommandText);生成的 SQL語句為:SELECT [t0].[ContactName] FROM [dbo]. [Customers]AS [t0]2.Where下面一個例子是“搭建”Where用法來動態查詢城市在倫敦的顧客。IQueryable<Customer> custs =db.Customers;// 創建一個參數cParameterExpression param =Expression.Parameter(typeof(Customer), "c");//c.City=="London"Expression left = Expression.Property(param,typeof(Customer).GetProperty ("City"));Expression right = Expression.Constant("London");Expression filter = Expression.Equal(left,right);Expression pred = Expression.Lambda(filter,param);//Where(c=>c.City=="London")Expression expr = Expression.Call(typeof(Queryable),"Where",new Type[] { typeof(Customer) },Expression.Constant(custs), pred);//生成動態查詢IQueryable<Customer> query =db.Customers.AsQueryable().Provider.CreateQuery<Customer>(expr);生成的SQL 語句為:SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],[t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],[t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]FROM [dbo].[Customers] AS [t0] WHERE [t0].[City] = @p0-- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]3.OrderBy本例既實現排序功能又實現了過濾功能。IQueryable<Customer> custs =db.Customers;//創建一個 參數cParameterExpression param =Expression.Parameter (typeof(Customer), "c");//c.City=="London"Expression left = Expression.Property(param,typeof(Customer).GetProperty ("City"));Expression right = Expression.Constant("London");Expression filter = Expression.Equal(left,right);Expression pred = Expression.Lambda(filter,param);//Where(c=>c.City=="London")MethodCallExpression whereCallExpression =Expression.Call(typeof(Queryable), "Where",new Type[] { typeof(Customer) },Expression.Constant(custs), pred);//OrderBy(ContactName => ContactName)MethodCallExpression orderByCallExpression= Expression.Call(typeof(Queryable), "OrderBy",new Type[] { typeof(Customer), typeof(string) },whereCallExpression,Expression.Lambda(Expression.Property(param, "ContactName"), param));//生成動態查詢IQueryable<Customer> query =db.Customers.AsQueryable().Provider.CreateQuery<Customer> (orderByCallExpression);下面一張截圖顯示了怎么動態生成動態查詢的過程生成的SQL語句為:SELECT [t0].[CustomerID],[t0].[CompanyName], [t0].[ContactName],[t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],[t0].[PostalCode], [t0].[Country], [t0].[Phone],[t0].[Fax]FROM [dbo].[Customers] AS [t0] WHERE[t0].[City] = @p0ORDER BY [t0].[ContactName]-- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]4.Union下面的例子使用表達式樹動態查詢顧客和雇員同在的城市。//e.CityIQueryable<Customer> custs = db.Customers;     ParameterExpression param1 =Expression.Parameter(typeof(Customer),"e");Expression left1 =Expression.Property(param1,typeof (Customer).GetProperty("City"));Expression pred1 = Expression.Lambda(left1,param1);//c.CityIQueryable<Employee> employees =db.Employees;ParameterExpression param2 =Expression.Parameter(typeof (Employee),"c");Expression left2 =Expression.Property(param2,typeof(Employee).GetProperty ("City"));Expression pred2 = Expression.Lambda(left2,param2);//Select(e=>e.City)Expression expr1 =Expression.Call(typeof(Queryable), "Select",new Type[] { typeof(Customer), typeof(string) },Expression.Constant(custs), pred1);//Select(c=>c.City)Expression expr2 =Expression.Call(typeof(Queryable), "Select",new Type[] { typeof(Employee), typeof (string) },Expression.Constant(employees), pred2);//生 成動態查詢IQueryable<string> q1 =db.Customers.AsQueryable().Provider.CreateQuery<string>(expr1);IQueryable<string> q2 =db.Employees.AsQueryable().Provider.CreateQuery<string>(expr2);//并集var q3 = q1.Union(q2);生成的SQL語句為:SELECT [t2].[City]FROM (SELECT [t0].[City] FROM [dbo]. [Customers] AS [t0]UNIONSELECT [t1].[City] FROM [dbo].[Employees] AS [t1]) AS [t2]LINQ to SQL語句(24)之視圖 視圖我們使用視圖和使用數據表類似,只需將視圖從“服務器資源管理器/數據庫資源管理器”拖動到O/R 設計器上,自動可以創建基于這些視圖的實體類。我們可以同操作數據表一樣來操作視圖了。這里注意:O/R 設計器是一個簡單的對象關系映射器,因為它僅支持 1:1 映射關系。換句話說,實體類與數據庫表或視圖之間只能具有 1:1 映射關系。不支持復雜映射(例如,將一個實體類映射到多個表)。但是,可以將一個實體類映射到一個聯接多個相關表的視圖。 下面使用NORTHWND數據庫中自帶的Invoices、QuarterlyOrders 兩個視圖為例,寫出兩個范例。查詢:匿名類型形式我們使用下面代碼來查詢出ShipCity 在London的發票。var q =from i in db.Invoiceswhere i.ShipCity == "London"select new{i.OrderID,i.ProductName,i.Quantity,i.CustomerName};這里,生成的SQL語句同使用數據表類似:SELECT [t0].[OrderID], [t0].[ProductName],[t0]. [Quantity],[t0].[CustomerName] FROM [dbo].[Invoices]AS [t0]WHERE [t0].[ShipCity] = @p0-- @p0: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]查詢:標識映射形式下例查詢出每季的訂單。var q =from qo in db.Quarterly_Ordersselect qo;生成SQL語句為:SELECT [t0].[CustomerID],[t0].[CompanyName], [t0]. [City],[t0].[Country] FROM [dbo].[QuarterlyOrders] AS [t0]LINQ to SQL語句(25)之繼承 繼承支持LINQ to SQL 支持單表映射,其整個繼承層次結構存儲在單個數據庫表中。該表包含整個層次結構的所有可能數據列的平展聯合。(聯合是將兩個表組合成一個表的結果,組合后的表包含任一原始表中存在的行。)每行中不適用于該行所表示的實例類型的列為 null。單表映射策略是最簡單的繼承表示形式,為許多不同類別的查詢提供了良好的性能特征,如果我們要在 LINQ to SQL 中實現這種映射,必須在繼承層次結構的根類中指定屬性 (Attribute) 和屬性 (Attribute) 的屬性 (Property)。我們還可以使用O/R設計器來映射繼承層次結構,它自動生成了代碼。下面為了演示下面的幾個例子,我們在O/R設計器內設計如下圖所示的類及其繼承關系。我們學習的時候還是看看其生成的代碼吧!具體設置映射繼承層次結構有如下幾步:根類添加TableAttribute屬性。為層次結構中的每個類添加InheritanceMappingAttribute屬性,同樣是添加到根類中。每個InheritanceMappingAttribute屬性,定義一個Code屬性和一個Type屬性。Code 屬性的值顯示在數據庫表的IsDiscriminator列中,用來指示該行數據所屬的類或子類。Type屬性值指定鍵值所表示的類或子類。僅在其中一個 InheritanceMappingAttribute屬性上,添加一個IsDefault屬性用來在數據庫表 中的鑒別器值在繼承映射中不與任何Code值匹配時指定回退映射。為 ColumnAttribute屬性添加一個IsDiscriminator屬性來表示這是保存Code值的列。下面是這張圖生成的代碼的框架(由于生成的代碼太多,我刪除了很多“枝葉”,僅僅保留了主要的框架用于指出其實質的東西):[Table(Name = "dbo.Contacts")][InheritanceMapping(Code ="Unknown", Type = typeof (Contact),IsDefault = true)][InheritanceMapping(Code ="Employee", Type = typeof (EmployeeContact))][InheritanceMapping(Code ="Supplier", Type = typeof(SupplierContact))][InheritanceMapping(Code ="Customer", Type = typeof (CustomerContact))][InheritanceMapping(Code ="Shipper", Type = typeof(ShipperContact))]public partial class Contact :INotifyPropertyChanging,INotifyPropertyChanged{[Column(Storage = "_ContactID",IsPrimaryKey = true,IsDbGenerated = true)]public int ContactID{ }[Column(Storage = "_ContactType",IsDiscriminator = true)]public string ContactType{ }}public abstract partial class FullContact :Contact{ }public partial class EmployeeContact :FullContact{ }public partial class SupplierContact :FullContact{ }public partial class CustomerContact :FullContact{ }public partial class ShipperContact :Contact{ }1.一般形式日常我們經常寫的形式,對單表查詢。var cons = from c in db.Contactsselect c;foreach (var con in cons) {Console.WriteLine("Company name: {0}", con.CompanyName);Console.WriteLine("Phone: {0}", con.Phone);Console.WriteLine("This is a {0}", con.GetType());}2.OfType形式這里我僅僅讓其返回顧客的聯系方式。var cons = from c indb.Contacts.OfType<CustomerContact>()select c;初步學習,我們還是看看生成的SQL語句,這樣容易理解。在 SQL語句中查詢了ContactType為Customer的聯系方式。SELECT [t0].[ContactType],[t0].[ContactName], [t0].[ContactTitle],[t0].[Address],[t0].[City], [t0].[Region],[t0].[PostalCode],[t0].[Country],[t0].[Fax],[t0].[ContactID], [t0].[CompanyName],[t0].[Phone] FROM [dbo].[Contacts] AS [t0]WHERE ([t0]. [ContactType] = @p0) AND([t0].[ContactType] IS NOT NULL)-- @p0: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]3.IS形式這個例子查找一下發貨人的聯系方式。var cons = from c in db.Contactswhere c is ShipperContactselect c;生成的SQL語句如下:查詢了ContactType為Shipper的聯系方式。大致一看好像很上面的一樣,其實這里查詢出來的列多了很多。實際上是Contacts表的全部字段。SELECT [t0].[ContactType],[t0].[ContactID], [t0]. [CompanyName],[t0].[Phone],[t0].[HomePage], [t0].[ContactName],[t0].[ContactTitle], [t0].[Address], [t0].[City],[t0].[Region], [t0].[PostalCode],[t0].[Country],[t0].[Fax],[t0].[PhotoPath], [t0].[Photo],[t0].[Extension]FROM [dbo].[Contacts] AS [t0] WHERE([t0].[ContactType] = @p0)AND ([t0].[ContactType] IS NOT NULL)-- @p0: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Shipper]4.AS形式這個例子就通吃了,全部查找了一番。var cons = from c in db.Contactsselect c as FullContact;生成 SQL語句如下:查詢整個Contacts表。SELECT [t0]. [ContactType],[t0].[HomePage], [t0].[ContactName],[t0]. [ContactTitle],[t0].[Address],[t0].[City],[t0].[Region], [t0]. [PostalCode],[t0].[Country],[t0].[Fax], [t0].[ContactID],[t0].[CompanyName],[t0].[Phone],[t0].[PhotoPath],[t0].[Photo], [t0].[Extension]FROM [dbo].[Contacts] AS [t0]5.Cast形式使用Case形式查找出在倫敦的顧客的聯系方式。var cons = from c in db.Contactswhere c.ContactType == "Customer" &&((CustomerContact)c).City == "London"select c;生成SQL語句如下,自己可以看懂了。SELECT [t0].[ContactType],[t0].[ContactID], [t0]. [CompanyName],[t0].[Phone], [t0].[HomePage],[t0].[ContactName],[t0].[ContactTitle], [t0].[Address],[t0].[City], [t0].[Region],[t0].[PostalCode], [t0].[Country],[t0].[Fax], [t0].[PhotoPath],[t0].[Photo], [t0].[Extension]FROM [dbo].[Contacts] AS [t0]WHERE ([t0].[ContactType] = @p0) AND ([t0].[City] = @p1)-- @p0: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]-- @p1: Input NVarChar (Size = 6; Prec = 0;Scale = 0) [London]6.UseAsDefault形式當插入一條記錄時,使用默認的映射關系了,但是在查詢時,使用繼承的關系了。具體看看生成的SQL 語句就直截了當了。//插入一條數據默認使用正常的映射關系Contact contact = new Contact(){ContactType = null,CompanyName = "Unknown Company",Phone = "333-444-5555"};db.Contacts.InsertOnSubmit(contact);db.SubmitChanges();//查詢一條數據默認使用繼承映射關系var con =(from c in db.Contactswhere c.CompanyName == "Unknown Company" &&c.Phone == "333-444-5555"select c).First();生成SQL語句如下:INSERT INTO [dbo].[Contacts]([ContactType], [CompanyName],[Phone]) VALUES (@p0, @p1, @p2)SELECT TOP (1) [t0].[ContactType], [t0].[ContactID],[t0]. [CompanyName],[t0].[Phone],[t0].[HomePage],[t0].[ContactName], [t0].[ContactTitle],[t0].[Address],[t0].[City],[t0].[Region],[t0].[PostalCode], [t0].[Country],[t0].[Fax], [t0].[PhotoPath], [t0].[Photo],[t0].[Extension]FROM [dbo].[Contacts] AS [t0]WHERE ([t0].[CompanyName] = @p0) AND([t0].[Phone] = @p1)-- @p0: Input NVarChar (Size = 15; Prec =0; Scale = 0)[Unknown Company]-- @p1: Input NVarChar (Size = 12; Prec =0; Scale = 0)[333-444-5555]7.插入新的記錄這個例子說明如何插入發貨人的聯系方式的一條記錄。//1.在插入之前查詢一下,沒有數據 var ShipperContacts =from sc in db.Contacts.OfType<ShipperContact>()where sc.CompanyName == "Northwind Shipper"select sc;//2.插入數據 ShipperContact nsc = new ShipperContact(){CompanyName = "Northwind Shipper",Phone = "(123)-456-7890"};db.Contacts.InsertOnSubmit(nsc);db.SubmitChanges();//3.查詢數據,有一條記錄 ShipperContacts =from sc in db.Contacts.OfType<ShipperContact>()where sc.CompanyName == "Northwind Shipper"select sc;//4.刪除記錄 db.Contacts.DeleteOnSubmit (nsc);db.SubmitChanges();生成SQL語句如下:SELECT COUNT(*) AS [value] FROM[dbo].[Contacts] AS [t0]WHERE ([t0].[CompanyName] = @p0) AND([t0].[ContactType] = @p1)AND ([t0].[ContactType] IS NOT NULL)-- @p0: Input NVarChar [Northwind Shipper]-- @p1: Input NVarChar [Shipper]INSERT INTO [dbo].[Contacts]([ContactType],[CompanyName], [Phone])VALUES (@p0, @p1, @p2)-- @p0: Input NVarChar [Shipper]-- @p1: Input NVarChar [NorthwindShipper]-- @p2: Input NVarChar [(123)-456-7890]SELECT COUNT(*) AS [value] FROM[dbo].[Contacts] AS [t0]WHERE ([t0].[CompanyName] = @p0) AND([t0].[ContactType] = @p1)AND ([t0].[ContactType] IS NOT NULL)-- @p0: Input NVarChar [Northwind Shipper]-- @p1: Input NVarChar [Shipper]DELETE FROM [dbo].[Contacts] WHERE ([ContactID]= @p0) AND([ContactType] = @p1) AND ([CompanyName] =@p2) AND ([Phone] = @p3)-- @p0: Input Int [159]-- @p1: Input NVarChar [Shipper]-- @p2: Input NVarChar [NorthwindShipper]-- @p3: Input NVarChar [(123)-456-7890]-- @p4: Input NVarChar [Unknown]-- @p5: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Supplier]-- @p6: Input NVarChar (Size = 7; Prec = 0;Scale = 0) [Shipper]-- @p7: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Employee]-- @p8: Input NVarChar (Size = 8; Prec = 0;Scale = 0) [Customer]

  

轉載于:https://www.cnblogs.com/ruishuang208/p/5972567.html

總結

以上是生活随笔為你收集整理的LINQ to SQL语句(1)之Where(抄的好)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

欧美freesex黑人又粗又大 | 国产两女互慰高潮视频在线观看 | 国内揄拍国内精品少妇国语 | 国产麻豆精品精东影业av网站 | 色狠狠av一区二区三区 | 国产高清av在线播放 | 国产亚av手机在线观看 | 成人无码视频在线观看网站 | 麻豆国产人妻欲求不满谁演的 | 久久久精品456亚洲影院 | 人人妻人人澡人人爽人人精品 | 亚洲gv猛男gv无码男同 | 精品国产aⅴ无码一区二区 | 好男人社区资源 | 国产av一区二区三区最新精品 | 少妇激情av一区二区 | 男人扒开女人内裤强吻桶进去 | 欧美zoozzooz性欧美 | 国产精品办公室沙发 | 国内精品久久久久久中文字幕 | 久久久久成人片免费观看蜜芽 | 老熟妇仑乱视频一区二区 | 夜精品a片一区二区三区无码白浆 | 精品国产一区av天美传媒 | 天天综合网天天综合色 | 天海翼激烈高潮到腰振不止 | 久久久婷婷五月亚洲97号色 | 亚洲精品中文字幕乱码 | 18禁止看的免费污网站 | 欧美一区二区三区视频在线观看 | 免费无码午夜福利片69 | 国产综合久久久久鬼色 | 国产va免费精品观看 | 亚洲国产高清在线观看视频 | 久久99精品久久久久久动态图 | 无码免费一区二区三区 | 国产精品va在线观看无码 | 亚洲无人区一区二区三区 | 成人一在线视频日韩国产 | 午夜嘿嘿嘿影院 | 亚洲综合在线一区二区三区 | 波多野结衣av一区二区全免费观看 | 波多野42部无码喷潮在线 | 无遮挡国产高潮视频免费观看 | 亚洲男人av天堂午夜在 | 国产精品亚洲专区无码不卡 | 最近免费中文字幕中文高清百度 | 国产绳艺sm调教室论坛 | 丁香花在线影院观看在线播放 | 蜜桃无码一区二区三区 | 欧洲熟妇色 欧美 | 亚洲日韩av一区二区三区中文 | 久久国产精品偷任你爽任你 | 日本精品人妻无码免费大全 | 亚洲大尺度无码无码专区 | 波多野结衣乳巨码无在线观看 | 国产精品人妻一区二区三区四 | 亚洲日本一区二区三区在线 | 国产免费无码一区二区视频 | 亚洲日韩一区二区三区 | 欧洲熟妇精品视频 | 久久久久99精品成人片 | 久久无码专区国产精品s | 欧美丰满少妇xxxx性 | 天堂在线观看www | 久久天天躁狠狠躁夜夜免费观看 | 中文字幕无码热在线视频 | 欧美性猛交xxxx富婆 | 中文字幕精品av一区二区五区 | 国产三级久久久精品麻豆三级 | 久久人人97超碰a片精品 | 无码人妻丰满熟妇区五十路百度 | 日本熟妇大屁股人妻 | 2019nv天堂香蕉在线观看 | 成人一在线视频日韩国产 | 久在线观看福利视频 | 国产乱码精品一品二品 | 扒开双腿吃奶呻吟做受视频 | 高中生自慰www网站 | √天堂中文官网8在线 | 中文字幕无码日韩专区 | 欧美人妻一区二区三区 | 色综合视频一区二区三区 | 国产另类ts人妖一区二区 | 久久综合久久自在自线精品自 | 97se亚洲精品一区 | 亚洲伊人久久精品影院 | 婷婷丁香六月激情综合啪 | 人妻天天爽夜夜爽一区二区 | 亚洲男人av天堂午夜在 | 国产av一区二区三区最新精品 | 亚洲精品国产第一综合99久久 | 激情国产av做激情国产爱 | 色老头在线一区二区三区 | 波多野42部无码喷潮在线 | 免费人成在线视频无码 | 亚洲欧美日韩国产精品一区二区 | 最新版天堂资源中文官网 | 亚洲娇小与黑人巨大交 | 欧美一区二区三区 | 欧美性猛交内射兽交老熟妇 | 中文字幕av无码一区二区三区电影 | 国产一区二区不卡老阿姨 | 伊人久久大香线蕉午夜 | 欧美35页视频在线观看 | 狠狠cao日日穞夜夜穞av | 兔费看少妇性l交大片免费 | 三级4级全黄60分钟 | 久久精品人妻少妇一区二区三区 | 99久久99久久免费精品蜜桃 | 欧美色就是色 | 少妇邻居内射在线 | 午夜男女很黄的视频 | 97久久国产亚洲精品超碰热 | 国产精品爱久久久久久久 | 性做久久久久久久免费看 | 欧美 日韩 人妻 高清 中文 | 亚洲一区二区三区含羞草 | 国产国语老龄妇女a片 | 白嫩日本少妇做爰 | 亚洲精品中文字幕乱码 | 亚洲精品一区二区三区在线观看 | 国产精品丝袜黑色高跟鞋 | 奇米影视888欧美在线观看 | 鲁大师影院在线观看 | 4hu四虎永久在线观看 | 亚洲а∨天堂久久精品2021 | 狠狠色色综合网站 | 国产精品美女久久久 | 国产成人精品无码播放 | 欧美xxxxx精品 | 影音先锋中文字幕无码 | 久久精品女人的天堂av | 极品尤物被啪到呻吟喷水 | 国产成人精品必看 | 荫蒂添的好舒服视频囗交 | 蜜桃无码一区二区三区 | 国产网红无码精品视频 | 少妇愉情理伦片bd | 欧洲精品码一区二区三区免费看 | 亚洲综合无码久久精品综合 | 日日摸日日碰夜夜爽av | 最近的中文字幕在线看视频 | 精品国产aⅴ无码一区二区 | 青草青草久热国产精品 | 十八禁真人啪啪免费网站 | 亚洲一区二区三区国产精华液 | 欧美阿v高清资源不卡在线播放 | 国产女主播喷水视频在线观看 | 久久国产精品萌白酱免费 | 久久久精品成人免费观看 | √8天堂资源地址中文在线 | 亚洲色欲色欲欲www在线 | 亚洲区小说区激情区图片区 | 中文字幕+乱码+中文字幕一区 | 国产人妻人伦精品1国产丝袜 | 久在线观看福利视频 | 久久精品女人天堂av免费观看 | 成人一在线视频日韩国产 | 国产av一区二区三区最新精品 | 国产激情艳情在线看视频 | 丰满人妻一区二区三区免费视频 | 久久久久成人片免费观看蜜芽 | 久久精品丝袜高跟鞋 | 爱做久久久久久 | 亚洲男女内射在线播放 | 亚洲区欧美区综合区自拍区 | 日韩亚洲欧美精品综合 | 大地资源网第二页免费观看 | 国产激情一区二区三区 | 波多野42部无码喷潮在线 | 亚洲精品国产品国语在线观看 | 亚洲国产欧美日韩精品一区二区三区 | 亚洲人成影院在线观看 | 久久亚洲日韩精品一区二区三区 | 99riav国产精品视频 | av无码不卡在线观看免费 | 久久亚洲中文字幕无码 | 国产免费久久久久久无码 | 国产农村妇女高潮大叫 | 国产精品鲁鲁鲁 | 亚洲乱码中文字幕在线 | 丰满人妻一区二区三区免费视频 | 高清国产亚洲精品自在久久 | 国产色精品久久人妻 | 超碰97人人做人人爱少妇 | 成人性做爰aaa片免费看不忠 | 久久精品国产亚洲精品 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产欧美精品一区二区三区 | 内射白嫩少妇超碰 | 亚洲成a人一区二区三区 | 国产精品永久免费视频 | 国産精品久久久久久久 | 国产精品亚洲专区无码不卡 | 狂野欧美性猛xxxx乱大交 | 免费无码一区二区三区蜜桃大 | 无码帝国www无码专区色综合 | 樱花草在线播放免费中文 | 亚洲无人区一区二区三区 | 色婷婷久久一区二区三区麻豆 | 精品 日韩 国产 欧美 视频 | 久久久久久av无码免费看大片 | 极品嫩模高潮叫床 | 日本va欧美va欧美va精品 | 成人免费视频视频在线观看 免费 | 欧美freesex黑人又粗又大 | 青春草在线视频免费观看 | 无码人妻丰满熟妇区毛片18 | 中文字幕乱码中文乱码51精品 | a国产一区二区免费入口 | www国产精品内射老师 | 夜夜躁日日躁狠狠久久av | aⅴ在线视频男人的天堂 | 精品厕所偷拍各类美女tp嘘嘘 | 88国产精品欧美一区二区三区 | 亚洲综合伊人久久大杳蕉 | 亚洲色偷偷偷综合网 | 两性色午夜视频免费播放 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 性欧美牲交xxxxx视频 | 人人妻人人澡人人爽欧美一区九九 | 亚洲理论电影在线观看 | 亚洲熟妇色xxxxx亚洲 | 国产成人精品无码播放 | 成人女人看片免费视频放人 | 人妻无码αv中文字幕久久琪琪布 | 国产三级久久久精品麻豆三级 | 亚洲精品国偷拍自产在线麻豆 | 伊人久久婷婷五月综合97色 | 婷婷综合久久中文字幕蜜桃三电影 | 欧美日韩在线亚洲综合国产人 | 天下第一社区视频www日本 | 精品国产福利一区二区 | 国产亚洲精品久久久久久久久动漫 | 好男人www社区 | 欧美精品在线观看 | 天下第一社区视频www日本 | 老熟妇乱子伦牲交视频 | 99精品视频在线观看免费 | 国产精品第一区揄拍无码 | 无码国产激情在线观看 | 久久精品视频在线看15 | 午夜福利不卡在线视频 | 国产成人无码午夜视频在线观看 | 日本熟妇乱子伦xxxx | 人人爽人人澡人人高潮 | 在线播放亚洲第一字幕 | 欧美国产日韩久久mv | 中文久久乱码一区二区 | 人妻少妇被猛烈进入中文字幕 | 97精品人妻一区二区三区香蕉 | 成人无码精品1区2区3区免费看 | 少妇激情av一区二区 | 免费播放一区二区三区 | 日韩av无码中文无码电影 | 综合激情五月综合激情五月激情1 | 丰满肥臀大屁股熟妇激情视频 | 国产精品va在线播放 | 纯爱无遮挡h肉动漫在线播放 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 国产亚洲美女精品久久久2020 | 97色伦图片97综合影院 | 澳门永久av免费网站 | 午夜无码人妻av大片色欲 | 亚洲中文无码av永久不收费 | 青青青手机频在线观看 | 国产激情无码一区二区 | 无码乱肉视频免费大全合集 | 亚洲欧美色中文字幕在线 | 日日摸夜夜摸狠狠摸婷婷 | 又粗又大又硬又长又爽 | 成人性做爰aaa片免费看 | av无码不卡在线观看免费 | 一本一道久久综合久久 | 狠狠亚洲超碰狼人久久 | 亚洲精品国产a久久久久久 | 国产黑色丝袜在线播放 | 国产成人无码av片在线观看不卡 | 红桃av一区二区三区在线无码av | 99久久精品午夜一区二区 | 亚洲午夜福利在线观看 | 中文字幕中文有码在线 | 国内丰满熟女出轨videos | 秋霞成人午夜鲁丝一区二区三区 | www国产亚洲精品久久网站 | 奇米影视7777久久精品 | 国产在线精品一区二区三区直播 | 色欲久久久天天天综合网精品 | 国产激情无码一区二区 | 娇妻被黑人粗大高潮白浆 | 日本爽爽爽爽爽爽在线观看免 | 成人影院yy111111在线观看 | 最近免费中文字幕中文高清百度 | 97色伦图片97综合影院 | 亚洲综合另类小说色区 | 久久视频在线观看精品 | 国产人妻大战黑人第1集 | 精品一区二区不卡无码av | 巨爆乳无码视频在线观看 | 少妇厨房愉情理9仑片视频 | 性色av无码免费一区二区三区 | 亚洲精品国产精品乱码视色 | 波多野结衣一区二区三区av免费 | 高潮毛片无遮挡高清免费视频 | 图片区 小说区 区 亚洲五月 | 少妇无套内谢久久久久 | 精品水蜜桃久久久久久久 | 久久精品国产一区二区三区 | 98国产精品综合一区二区三区 | 国产超级va在线观看视频 | 亚洲男女内射在线播放 | 一个人看的www免费视频在线观看 | 欧美freesex黑人又粗又大 | 欧美日韩人成综合在线播放 | 欧美日韩综合一区二区三区 | 波多野结衣高清一区二区三区 | 在线看片无码永久免费视频 | 国产两女互慰高潮视频在线观看 | 日韩在线不卡免费视频一区 | 日韩视频 中文字幕 视频一区 | 国产精品99久久精品爆乳 | 1000部啪啪未满十八勿入下载 | 999久久久国产精品消防器材 | 国产精品久久久久久亚洲毛片 | 国产9 9在线 | 中文 | 亚洲国产av美女网站 | 亚洲日韩一区二区 | 中文字幕乱码亚洲无线三区 | 亚洲综合在线一区二区三区 | 免费播放一区二区三区 | 亚洲狠狠色丁香婷婷综合 | 好男人www社区 | 美女扒开屁股让男人桶 | 国产一区二区三区日韩精品 | 日韩欧美中文字幕公布 | 国产人妻精品午夜福利免费 | 国内揄拍国内精品人妻 | 国产成人综合在线女婷五月99播放 | 性欧美疯狂xxxxbbbb | 国精品人妻无码一区二区三区蜜柚 | 人妻有码中文字幕在线 | 男女作爱免费网站 | 欧美大屁股xxxxhd黑色 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 国产精品-区区久久久狼 | 国产又粗又硬又大爽黄老大爷视 | 亚洲精品一区二区三区在线 | 精品 日韩 国产 欧美 视频 | 无码av最新清无码专区吞精 | 一本久道久久综合狠狠爱 | 成人三级无码视频在线观看 | 久久精品中文字幕大胸 | 欧美性生交活xxxxxdddd | 国产九九九九九九九a片 | 欧美freesex黑人又粗又大 | 性色欲情网站iwww九文堂 | 国产精品无码一区二区三区不卡 | 欧美精品一区二区精品久久 | 国产精品久久久久久无码 | 一本久久伊人热热精品中文字幕 | 国色天香社区在线视频 | 中文字幕无码av激情不卡 | 丰满人妻被黑人猛烈进入 | 亚洲综合另类小说色区 | 国产特级毛片aaaaaaa高清 | 国产在线精品一区二区高清不卡 | 精品国产aⅴ无码一区二区 | 成 人 免费观看网站 | 夜精品a片一区二区三区无码白浆 | 欧美国产日韩久久mv | 学生妹亚洲一区二区 | 熟妇人妻无乱码中文字幕 | 久久久久久久女国产乱让韩 | 国产精品美女久久久网av | 未满小14洗澡无码视频网站 | 狂野欧美性猛xxxx乱大交 | 国产乱人伦av在线无码 | 亚洲自偷自偷在线制服 | 欧美成人高清在线播放 | 国产精品无码成人午夜电影 | yw尤物av无码国产在线观看 | 国产又爽又黄又刺激的视频 | 亚洲熟熟妇xxxx | 亚洲国产综合无码一区 | 日本熟妇人妻xxxxx人hd | 国内少妇偷人精品视频免费 | 久久久久99精品国产片 | 少妇厨房愉情理9仑片视频 | 中文无码成人免费视频在线观看 | 免费中文字幕日韩欧美 | 精品久久综合1区2区3区激情 | 国产成人人人97超碰超爽8 | 亚洲精品综合一区二区三区在线 | 精品少妇爆乳无码av无码专区 | 人人澡人人透人人爽 | 在线欧美精品一区二区三区 | 亚洲精品国产精品乱码不卡 | 狂野欧美性猛交免费视频 | 国产成人精品三级麻豆 | 国产亚洲欧美日韩亚洲中文色 | 撕开奶罩揉吮奶头视频 | 99久久精品日本一区二区免费 | 免费人成在线观看网站 | 疯狂三人交性欧美 | 99久久人妻精品免费二区 | 亚洲中文字幕va福利 | 少妇无套内谢久久久久 | 国产精品视频免费播放 | 国产精品久久久久久久影院 | 夜夜影院未满十八勿进 | 全黄性性激高免费视频 | 亚洲成av人影院在线观看 | 国产精品自产拍在线观看 | 免费视频欧美无人区码 | av在线亚洲欧洲日产一区二区 | 国产热a欧美热a在线视频 | 成人精品一区二区三区中文字幕 | 99国产欧美久久久精品 | 中文字幕精品av一区二区五区 | 国产特级毛片aaaaaa高潮流水 | 草草网站影院白丝内射 | 高潮毛片无遮挡高清免费视频 | 鲁大师影院在线观看 | 图片小说视频一区二区 | 在线亚洲高清揄拍自拍一品区 | 国产内射老熟女aaaa | 国产亚洲精品久久久久久久 | 牲欲强的熟妇农村老妇女 | 领导边摸边吃奶边做爽在线观看 | 国产精品毛片一区二区 | 人人妻人人澡人人爽欧美一区 | 成人欧美一区二区三区 | 激情人妻另类人妻伦 | 亚洲中文字幕无码中字 | 无遮无挡爽爽免费视频 | 在线视频网站www色 | 丰满少妇人妻久久久久久 | 人人妻人人澡人人爽欧美精品 | 成人无码精品一区二区三区 | 色欲久久久天天天综合网精品 | 精品日本一区二区三区在线观看 | 99久久人妻精品免费二区 | 久久精品国产亚洲精品 | 丰满少妇熟乱xxxxx视频 | 国产成人综合色在线观看网站 | 最近的中文字幕在线看视频 | 欧美丰满老熟妇xxxxx性 | 亚洲日韩中文字幕在线播放 | 图片小说视频一区二区 | 午夜熟女插插xx免费视频 | 国色天香社区在线视频 | 在线观看国产一区二区三区 | 国产亚洲视频中文字幕97精品 | 精品无码国产自产拍在线观看蜜 | 4hu四虎永久在线观看 | 亚洲精品一区国产 | 人妻与老人中文字幕 | 国产一区二区三区四区五区加勒比 | av无码久久久久不卡免费网站 | 久久精品视频在线看15 | 国产激情综合五月久久 | 成人欧美一区二区三区黑人免费 | 性欧美videos高清精品 | 两性色午夜免费视频 | 性做久久久久久久免费看 | 天堂无码人妻精品一区二区三区 | 无遮挡啪啪摇乳动态图 | 亚洲人成无码网www | 水蜜桃色314在线观看 | 成人毛片一区二区 | 老头边吃奶边弄进去呻吟 | 免费无码一区二区三区蜜桃大 | 亚洲精品午夜国产va久久成人 | 日韩精品乱码av一区二区 | 国产小呦泬泬99精品 | 国产又粗又硬又大爽黄老大爷视 | 精品国产一区二区三区四区在线看 | 欧美 日韩 亚洲 在线 | 97精品国产97久久久久久免费 | 青草青草久热国产精品 | av在线亚洲欧洲日产一区二区 | 亚洲色偷偷偷综合网 | 亚洲熟妇色xxxxx欧美老妇 | 国产va免费精品观看 | 国产又爽又黄又刺激的视频 | 精品国偷自产在线视频 | 国产人妻大战黑人第1集 | 久久久久久久女国产乱让韩 | 亚洲综合无码一区二区三区 | 国产成人无码a区在线观看视频app | 一本色道久久综合亚洲精品不卡 | av无码久久久久不卡免费网站 | 国产午夜视频在线观看 | 两性色午夜视频免费播放 | 国产人妻人伦精品1国产丝袜 | 亚洲欧洲日本无在线码 | 99久久99久久免费精品蜜桃 | 亚洲熟妇色xxxxx欧美老妇 | 综合人妻久久一区二区精品 | 成人三级无码视频在线观看 | 在线播放无码字幕亚洲 | 天堂亚洲2017在线观看 | 啦啦啦www在线观看免费视频 | 少妇被粗大的猛进出69影院 | 日韩成人一区二区三区在线观看 | 精品无码一区二区三区的天堂 | 亚洲欧美精品aaaaaa片 | 国产在线无码精品电影网 | 少妇的肉体aa片免费 | 久久人妻内射无码一区三区 | 99久久久无码国产aaa精品 | 色欲av亚洲一区无码少妇 | 97夜夜澡人人双人人人喊 | 精品国精品国产自在久国产87 | 欧美真人作爱免费视频 | 久久久久se色偷偷亚洲精品av | 伊在人天堂亚洲香蕉精品区 | 亚洲热妇无码av在线播放 | 国产午夜亚洲精品不卡下载 | 九九在线中文字幕无码 | 久久人妻内射无码一区三区 | 日韩在线不卡免费视频一区 | 亚洲精品国偷拍自产在线观看蜜桃 | 国产在线一区二区三区四区五区 | 免费国产黄网站在线观看 | 麻豆国产人妻欲求不满谁演的 | 国产成人精品一区二区在线小狼 | 4hu四虎永久在线观看 | 亚洲精品国偷拍自产在线麻豆 | 亚洲成av人综合在线观看 | 午夜不卡av免费 一本久久a久久精品vr综合 | 67194成是人免费无码 | 高清国产亚洲精品自在久久 | 青青青手机频在线观看 | 美女极度色诱视频国产 | √天堂中文官网8在线 | 小sao货水好多真紧h无码视频 | 久久综合给合久久狠狠狠97色 | 欧美黑人乱大交 | 性欧美熟妇videofreesex | 国产美女极度色诱视频www | 国产美女极度色诱视频www | 国产国产精品人在线视 | 成人aaa片一区国产精品 | 久久久精品欧美一区二区免费 | 国产亚洲精品久久久久久久 | 成人免费视频在线观看 | 色综合久久88色综合天天 | 黑人巨大精品欧美黑寡妇 | 久久精品人人做人人综合试看 | 亚洲国产精品无码久久久久高潮 | 丝袜人妻一区二区三区 | 99久久亚洲精品无码毛片 | 奇米影视7777久久精品人人爽 | 中文字幕av日韩精品一区二区 | 性欧美熟妇videofreesex | 欧美xxxx黑人又粗又长 | 国产精品人人妻人人爽 | 毛片内射-百度 | 理论片87福利理论电影 | 日本又色又爽又黄的a片18禁 | 乱人伦人妻中文字幕无码 | 中文字幕亚洲情99在线 | 全球成人中文在线 | 偷窥日本少妇撒尿chinese | 精品久久久中文字幕人妻 | 欧美乱妇无乱码大黄a片 | 自拍偷自拍亚洲精品10p | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 久久97精品久久久久久久不卡 | 2019午夜福利不卡片在线 | 久久99精品久久久久久动态图 | 国产精品亚洲一区二区三区喷水 | 日本丰满护士爆乳xxxx | 国产精品永久免费视频 | 男人的天堂2018无码 | 国产va免费精品观看 | 无遮挡国产高潮视频免费观看 | 久久精品国产日本波多野结衣 | 无码人妻出轨黑人中文字幕 | 少女韩国电视剧在线观看完整 | 久久午夜夜伦鲁鲁片无码免费 | 强开小婷嫩苞又嫩又紧视频 | 小鲜肉自慰网站xnxx | 久久久久亚洲精品男人的天堂 | 国产午夜精品一区二区三区嫩草 | 精品厕所偷拍各类美女tp嘘嘘 | 国产成人综合色在线观看网站 | 300部国产真实乱 | 少妇被黑人到高潮喷出白浆 | 伊人色综合久久天天小片 | 国产精品人人妻人人爽 | 亚洲精品午夜无码电影网 | 久久久久久亚洲精品a片成人 | 亚洲成色www久久网站 | 久久精品女人天堂av免费观看 | 中文字幕日产无线码一区 | 青青草原综合久久大伊人精品 | 熟女俱乐部五十路六十路av | 精品久久久无码中文字幕 | 成人三级无码视频在线观看 | 久久99国产综合精品 | 人妻aⅴ无码一区二区三区 | a在线观看免费网站大全 | 熟妇人妻中文av无码 | 国产又爽又黄又刺激的视频 | 51国偷自产一区二区三区 | 色综合久久88色综合天天 | 成熟女人特级毛片www免费 | 亚洲中文字幕成人无码 | 丰满少妇女裸体bbw | 中文字幕人妻丝袜二区 | 欧美色就是色 | 国产后入清纯学生妹 | 女人高潮内射99精品 | 影音先锋中文字幕无码 | 国产人妻久久精品二区三区老狼 | 国产精品多人p群无码 | 国产性生大片免费观看性 | 久久精品人人做人人综合试看 | 人妻体内射精一区二区三四 | 无码精品人妻一区二区三区av | 日韩精品乱码av一区二区 | 鲁一鲁av2019在线 | 国产熟女一区二区三区四区五区 | 国产高清不卡无码视频 | 亚洲成av人片天堂网无码】 | 永久免费观看国产裸体美女 | 18精品久久久无码午夜福利 | 亚洲熟妇色xxxxx亚洲 | 亚洲自偷自偷在线制服 | 国产人妻人伦精品1国产丝袜 | 好男人www社区 | 日本爽爽爽爽爽爽在线观看免 | 久久久久成人精品免费播放动漫 | 18禁黄网站男男禁片免费观看 | 国产精品美女久久久久av爽李琼 | 久久综合香蕉国产蜜臀av | 日韩欧美成人免费观看 | 少妇无码av无码专区在线观看 | 国产乱人偷精品人妻a片 | 欧美国产日韩久久mv | 九九久久精品国产免费看小说 | 性生交大片免费看女人按摩摩 | 国内精品久久毛片一区二区 | 丰满护士巨好爽好大乳 | 无码av岛国片在线播放 | 国产精品第一区揄拍无码 | 一二三四在线观看免费视频 | a片免费视频在线观看 | 澳门永久av免费网站 | 熟女体下毛毛黑森林 | 亚洲国产精品成人久久蜜臀 | 国产成人精品一区二区在线小狼 | 国产sm调教视频在线观看 | 成人欧美一区二区三区黑人免费 | 亚洲成av人综合在线观看 | aa片在线观看视频在线播放 | 中文字幕av无码一区二区三区电影 | 色婷婷av一区二区三区之红樱桃 | 一区二区传媒有限公司 | 大乳丰满人妻中文字幕日本 | 欧美亚洲日韩国产人成在线播放 | 国产精品理论片在线观看 | 日韩人妻无码中文字幕视频 | 伊人色综合久久天天小片 | 偷窥日本少妇撒尿chinese | 天堂а√在线中文在线 | 日韩精品成人一区二区三区 | 国产电影无码午夜在线播放 | 高中生自慰www网站 | 成人性做爰aaa片免费看不忠 | 欧美一区二区三区视频在线观看 | 国产成人综合美国十次 | 国内少妇偷人精品视频免费 | 亚洲熟妇色xxxxx欧美老妇 | 亚洲无人区一区二区三区 | 精品一区二区三区无码免费视频 | 捆绑白丝粉色jk震动捧喷白浆 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 亚洲精品美女久久久久久久 | 99久久精品国产一区二区蜜芽 | 亚洲一区二区三区无码久久 | 欧美精品无码一区二区三区 | 蜜桃臀无码内射一区二区三区 | 无人区乱码一区二区三区 | 久久久www成人免费毛片 | 日韩精品无码免费一区二区三区 | 成人亚洲精品久久久久软件 | 俺去俺来也在线www色官网 | 性色欲网站人妻丰满中文久久不卡 | 成人一区二区免费视频 | 奇米影视888欧美在线观看 | 久久 国产 尿 小便 嘘嘘 | 亚洲人成网站免费播放 | 久久精品人人做人人综合 | 国产va免费精品观看 | 久久精品无码一区二区三区 | 中文字幕无码视频专区 | 丰满人妻一区二区三区免费视频 | 亚洲呦女专区 | 美女毛片一区二区三区四区 | 麻花豆传媒剧国产免费mv在线 | 国产精品久久久av久久久 | 久久综合给久久狠狠97色 | 99久久精品无码一区二区毛片 | 精品亚洲韩国一区二区三区 | 日本精品人妻无码77777 天堂一区人妻无码 | 亚洲天堂2017无码中文 | 久久精品视频在线看15 | 女人被男人爽到呻吟的视频 | 日日摸天天摸爽爽狠狠97 | 国产97人人超碰caoprom | 国产精品va在线观看无码 | ass日本丰满熟妇pics | 性做久久久久久久久 | 一本久久伊人热热精品中文字幕 | 国产成人无码av片在线观看不卡 | 最新国产乱人伦偷精品免费网站 | 国产女主播喷水视频在线观看 | 久久人人爽人人爽人人片ⅴ | 99视频精品全部免费免费观看 | | 国产亚洲精品久久久闺蜜 | 男女性色大片免费网站 | 欧美怡红院免费全部视频 | ass日本丰满熟妇pics | 午夜精品一区二区三区的区别 | 特黄特色大片免费播放器图片 | 我要看www免费看插插视频 | 国产精品久久久久无码av色戒 | 亚洲成a人片在线观看无码 | 久久国产精品精品国产色婷婷 | 99精品无人区乱码1区2区3区 | 亚洲国产成人a精品不卡在线 | 麻豆国产丝袜白领秘书在线观看 | 国产无遮挡又黄又爽免费视频 | 人人妻人人藻人人爽欧美一区 | 亚洲伊人久久精品影院 | 偷窥村妇洗澡毛毛多 | 国产成人一区二区三区在线观看 | 51国偷自产一区二区三区 | 中文字幕日产无线码一区 | 麻豆人妻少妇精品无码专区 | 日韩欧美中文字幕公布 | 性欧美牲交在线视频 | 老头边吃奶边弄进去呻吟 | 日韩少妇内射免费播放 | 丁香花在线影院观看在线播放 | √天堂资源地址中文在线 | 高潮毛片无遮挡高清免费视频 | 东京热一精品无码av | 蜜臀aⅴ国产精品久久久国产老师 | 欧美怡红院免费全部视频 | 女人和拘做爰正片视频 | 99riav国产精品视频 | 亚洲熟妇色xxxxx欧美老妇 | 午夜时刻免费入口 | 久久99精品国产麻豆蜜芽 | 国产av一区二区精品久久凹凸 | 一本久久a久久精品vr综合 | 久激情内射婷内射蜜桃人妖 | 学生妹亚洲一区二区 | 水蜜桃色314在线观看 | 国产成人亚洲综合无码 | 亚洲精品国偷拍自产在线观看蜜桃 | 麻豆人妻少妇精品无码专区 | 久久久久国色av免费观看性色 | 久久国产劲爆∧v内射 | 大地资源中文第3页 | 欧洲熟妇色 欧美 | 国产网红无码精品视频 | 久久久久成人片免费观看蜜芽 | 少妇被黑人到高潮喷出白浆 | 欧美人与动性行为视频 | 国产性生交xxxxx无码 | 亚洲成熟女人毛毛耸耸多 | 丝袜 中出 制服 人妻 美腿 | 国内老熟妇对白xxxxhd | 国产成人午夜福利在线播放 | 亚洲综合另类小说色区 | 4hu四虎永久在线观看 | 婷婷色婷婷开心五月四房播播 | 蜜桃av抽搐高潮一区二区 | 亚洲 高清 成人 动漫 | 人人妻在人人 | 久久综合久久自在自线精品自 | 久久午夜夜伦鲁鲁片无码免费 | 在线a亚洲视频播放在线观看 | 久久久久亚洲精品男人的天堂 | 中国女人内谢69xxxx | 88国产精品欧美一区二区三区 | 在线 国产 欧美 亚洲 天堂 | 亚洲成色在线综合网站 | 极品嫩模高潮叫床 | 国产网红无码精品视频 | 日韩精品a片一区二区三区妖精 | 四十如虎的丰满熟妇啪啪 | 亚洲日本va午夜在线电影 | 国产精品怡红院永久免费 | 老熟妇乱子伦牲交视频 | 玩弄人妻少妇500系列视频 | 激情综合激情五月俺也去 | 久久午夜无码鲁丝片午夜精品 | 人人爽人人澡人人人妻 | 131美女爱做视频 | 国产精品毛片一区二区 | 高潮喷水的毛片 | 成熟人妻av无码专区 | 在线观看国产一区二区三区 | 激情人妻另类人妻伦 | 亚洲精品一区二区三区大桥未久 | 亚洲精品综合五月久久小说 | 老熟女乱子伦 | 中文字幕无码av激情不卡 | 永久黄网站色视频免费直播 | 国产97在线 | 亚洲 | 国产精品毛多多水多 | 亚洲日韩乱码中文无码蜜桃臀网站 | 亚洲色偷偷偷综合网 | 成人片黄网站色大片免费观看 | 熟女少妇人妻中文字幕 | 欧美肥老太牲交大战 | 欧美性生交xxxxx久久久 | 一本加勒比波多野结衣 | 中文字幕av伊人av无码av | 最近的中文字幕在线看视频 | 中文字幕乱码中文乱码51精品 | 久久久www成人免费毛片 | 国产va免费精品观看 | 国产精品办公室沙发 | 国产精品鲁鲁鲁 | 人妻尝试又大又粗久久 | 九九在线中文字幕无码 | aⅴ在线视频男人的天堂 | 欧美亚洲日韩国产人成在线播放 | 亚洲中文无码av永久不收费 | 久久久久亚洲精品中文字幕 | а√资源新版在线天堂 | 国产一区二区三区日韩精品 | 亚洲国产日韩a在线播放 | 少妇性l交大片欧洲热妇乱xxx | 国产精品爱久久久久久久 | 久久99国产综合精品 | 青青青爽视频在线观看 | 水蜜桃亚洲一二三四在线 | 亚洲精品综合一区二区三区在线 | 亚洲日韩乱码中文无码蜜桃臀网站 | 精品少妇爆乳无码av无码专区 | 天堂久久天堂av色综合 | 精品国产av色一区二区深夜久久 | 水蜜桃亚洲一二三四在线 | 精品久久久中文字幕人妻 | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲国产精品一区二区美利坚 | 久久久久久亚洲精品a片成人 | 性开放的女人aaa片 | 免费无码一区二区三区蜜桃大 | 久久精品中文字幕大胸 | 激情国产av做激情国产爱 | 国产suv精品一区二区五 | 久久久国产精品无码免费专区 | 久久久亚洲欧洲日产国码αv | 极品尤物被啪到呻吟喷水 | 久久综合香蕉国产蜜臀av | 国产亚洲精品久久久久久大师 | 亚洲а∨天堂久久精品2021 | 久久精品人人做人人综合 | 国内精品九九久久久精品 | 日本在线高清不卡免费播放 | 捆绑白丝粉色jk震动捧喷白浆 | 乱人伦中文视频在线观看 | 丰满少妇熟乱xxxxx视频 | 精品人妻人人做人人爽 | 夜夜高潮次次欢爽av女 | 久久精品国产一区二区三区肥胖 | 亚洲精品久久久久中文第一幕 | 国内精品九九久久久精品 | 日韩精品无码免费一区二区三区 | 老熟妇乱子伦牲交视频 | 国产成人亚洲综合无码 | 丝袜足控一区二区三区 | 一二三四社区在线中文视频 | 真人与拘做受免费视频一 | 76少妇精品导航 | 精品人妻人人做人人爽夜夜爽 | 男女性色大片免费网站 | 亚洲欧美日韩国产精品一区二区 | 国产成人av免费观看 | 日韩av无码一区二区三区 | 亚洲 日韩 欧美 成人 在线观看 | 久久精品无码一区二区三区 | 久久精品国产一区二区三区肥胖 | 国产熟女一区二区三区四区五区 | 国产成人一区二区三区在线观看 | 国产麻豆精品精东影业av网站 | 国产网红无码精品视频 | 日韩精品无码一本二本三本色 | 人妻少妇精品久久 | 成人欧美一区二区三区黑人免费 | 男女猛烈xx00免费视频试看 | 国产午夜亚洲精品不卡 | 中文毛片无遮挡高清免费 | 国产亚洲精品久久久久久久久动漫 | 国产精品资源一区二区 | 国产亚洲美女精品久久久2020 | 亚洲综合无码久久精品综合 | 国产精品无套呻吟在线 | 无码帝国www无码专区色综合 | 国产亚洲精品久久久久久 | 毛片内射-百度 | 老司机亚洲精品影院 | 日韩av无码一区二区三区 | 无遮挡国产高潮视频免费观看 | 国产99久久精品一区二区 | 俄罗斯老熟妇色xxxx | 人人妻人人澡人人爽精品欧美 | 国产午夜精品一区二区三区嫩草 | 日韩av无码一区二区三区不卡 | 亚洲乱码国产乱码精品精 | 亚洲国产日韩a在线播放 | 性色欲网站人妻丰满中文久久不卡 | 国产乱子伦视频在线播放 | 亚洲 高清 成人 动漫 | 国产欧美熟妇另类久久久 | 亚洲经典千人经典日产 | 亚洲熟妇色xxxxx亚洲 | 欧美日本免费一区二区三区 | 国内精品久久毛片一区二区 | 久久久久久国产精品无码下载 | 亚洲精品午夜国产va久久成人 | 中文字幕日产无线码一区 | 色欲人妻aaaaaaa无码 | av无码不卡在线观看免费 | 大色综合色综合网站 | 久久99精品久久久久久 | 亚洲精品一区二区三区婷婷月 | 国产激情无码一区二区app | 内射爽无广熟女亚洲 | 巨爆乳无码视频在线观看 | 国产精品无码一区二区三区不卡 | 国产精品亚洲а∨无码播放麻豆 | 少妇性俱乐部纵欲狂欢电影 | 少妇被黑人到高潮喷出白浆 | 国产成人精品优优av | 中文无码成人免费视频在线观看 | 亚洲自偷自拍另类第1页 | 5858s亚洲色大成网站www | 亚洲男女内射在线播放 | 午夜福利试看120秒体验区 | 欧美xxxx黑人又粗又长 | 久精品国产欧美亚洲色aⅴ大片 | 亚洲欧美日韩国产精品一区二区 | 熟女俱乐部五十路六十路av | 国产片av国语在线观看 | 99久久久无码国产aaa精品 | 无码一区二区三区在线观看 | 图片区 小说区 区 亚洲五月 | 久久zyz资源站无码中文动漫 | 中文字幕久久久久人妻 | 一本精品99久久精品77 | 亚洲精品久久久久久一区二区 | 国产综合久久久久鬼色 | 中文字幕无码日韩专区 | 国产电影无码午夜在线播放 | 国产深夜福利视频在线 | 中文无码精品a∨在线观看不卡 | 人妻无码αv中文字幕久久琪琪布 | 国产无套粉嫩白浆在线 | 久久亚洲精品中文字幕无男同 | 学生妹亚洲一区二区 | 成人性做爰aaa片免费看 | 精品乱码久久久久久久 | 国内少妇偷人精品视频 | 色五月五月丁香亚洲综合网 | 国产乱人无码伦av在线a | 人人超人人超碰超国产 | 国产熟妇高潮叫床视频播放 | 无码午夜成人1000部免费视频 | 蜜臀aⅴ国产精品久久久国产老师 | 免费看男女做好爽好硬视频 | 午夜福利一区二区三区在线观看 | 野外少妇愉情中文字幕 | 天堂无码人妻精品一区二区三区 | 欧美日本精品一区二区三区 | 久久久久久av无码免费看大片 | 国产亚洲精品久久久久久久久动漫 | 97se亚洲精品一区 | 波多野结衣av一区二区全免费观看 | 在线看片无码永久免费视频 | 无码av中文字幕免费放 | 国产精品内射视频免费 | 国模大胆一区二区三区 | 国产精品va在线观看无码 | 国内少妇偷人精品视频 | 国产农村乱对白刺激视频 | 精品一二三区久久aaa片 | 久久综合香蕉国产蜜臀av | 中文字幕无码人妻少妇免费 | av无码久久久久不卡免费网站 | 久久99久久99精品中文字幕 | 精品一区二区三区波多野结衣 | aa片在线观看视频在线播放 | 日日橹狠狠爱欧美视频 | 中文字幕人成乱码熟女app | 狂野欧美激情性xxxx | 国产精品福利视频导航 | 无码吃奶揉捏奶头高潮视频 | 国产av无码专区亚洲a∨毛片 | 亚洲中文字幕无码中文字在线 | 亚洲阿v天堂在线 | 久久人人爽人人爽人人片ⅴ | 综合网日日天干夜夜久久 | 日韩人妻无码一区二区三区久久99 | 一区二区三区乱码在线 | 欧洲 | 丰满护士巨好爽好大乳 | 伊人久久大香线蕉亚洲 | 好屌草这里只有精品 | 国产97人人超碰caoprom | 久久久久久亚洲精品a片成人 | 乱码午夜-极国产极内射 | 成人三级无码视频在线观看 | 性欧美疯狂xxxxbbbb | 亚洲国产av美女网站 | 熟妇女人妻丰满少妇中文字幕 | 夜夜高潮次次欢爽av女 | 天海翼激烈高潮到腰振不止 | 中国女人内谢69xxxx | 成 人 网 站国产免费观看 | 久久zyz资源站无码中文动漫 | 中文字幕人妻无码一区二区三区 | 露脸叫床粗话东北少妇 | 久久精品国产一区二区三区 | 国产成人综合在线女婷五月99播放 | 免费人成在线观看网站 | 亚洲爆乳大丰满无码专区 | 中文字幕无码视频专区 | 无码乱肉视频免费大全合集 | 中文字幕无码视频专区 | 色综合久久久久综合一本到桃花网 | 老熟妇乱子伦牲交视频 | 97无码免费人妻超级碰碰夜夜 | 中文字幕无线码免费人妻 | 国产99久久精品一区二区 | 大屁股大乳丰满人妻 | 久久97精品久久久久久久不卡 | 狠狠cao日日穞夜夜穞av | 欧美精品一区二区精品久久 | 国产综合色产在线精品 | 女人高潮内射99精品 | 亚洲色www成人永久网址 | 亚洲 另类 在线 欧美 制服 | 中文字幕乱码人妻无码久久 | 亚洲日韩精品欧美一区二区 | 欧美日本日韩 | 亚洲热妇无码av在线播放 | 国产精品久久久久影院嫩草 | 精品aⅴ一区二区三区 | 国产无套内射久久久国产 | 久久久久亚洲精品中文字幕 | 精品国产aⅴ无码一区二区 | 亚洲自偷自拍另类第1页 | 最新版天堂资源中文官网 | 在教室伦流澡到高潮hnp视频 | 最近免费中文字幕中文高清百度 | 日本精品人妻无码免费大全 | 免费人成在线观看网站 | 97久久超碰中文字幕 | 精品久久久无码人妻字幂 | 在线观看国产午夜福利片 | 无码乱肉视频免费大全合集 | 正在播放东北夫妻内射 | 国产办公室秘书无码精品99 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲の无码国产の无码影院 | 亚洲一区av无码专区在线观看 | 亚洲国产一区二区三区在线观看 | 欧美成人午夜精品久久久 | 一二三四社区在线中文视频 | 国产艳妇av在线观看果冻传媒 | 成人精品天堂一区二区三区 | а√资源新版在线天堂 | 女人被男人爽到呻吟的视频 | 人妻少妇精品无码专区动漫 | 国产免费无码一区二区视频 | 中文字幕中文有码在线 | 亚洲欧美日韩成人高清在线一区 | 中文亚洲成a人片在线观看 | 久久亚洲国产成人精品性色 | 亚洲乱码国产乱码精品精 | 曰韩无码二三区中文字幕 | 娇妻被黑人粗大高潮白浆 | 人妻少妇精品无码专区动漫 | 在线天堂新版最新版在线8 | 乱中年女人伦av三区 | 成人亚洲精品久久久久软件 | 强伦人妻一区二区三区视频18 | 国内老熟妇对白xxxxhd | 亚洲国产精华液网站w | 人人妻人人澡人人爽欧美一区 | 成年美女黄网站色大免费全看 | 国产精品久久久久9999小说 | 免费中文字幕日韩欧美 | 日本欧美一区二区三区乱码 | 国产精品美女久久久网av | 日本熟妇人妻xxxxx人hd | 国产人妻人伦精品1国产丝袜 | аⅴ资源天堂资源库在线 | 无码午夜成人1000部免费视频 | 国产69精品久久久久app下载 | 人人妻人人澡人人爽人人精品浪潮 | 国产成人久久精品流白浆 | 亚洲综合精品香蕉久久网 | 亚洲精品欧美二区三区中文字幕 | 男人扒开女人内裤强吻桶进去 | 国产超碰人人爽人人做人人添 | 乱码av麻豆丝袜熟女系列 | 激情亚洲一区国产精品 | 国产激情艳情在线看视频 | 思思久久99热只有频精品66 | 欧美第一黄网免费网站 | 久久 国产 尿 小便 嘘嘘 | 国产成人无码av在线影院 | 正在播放东北夫妻内射 | 亚洲人成影院在线观看 | 国产成人一区二区三区在线观看 | 国产成人无码午夜视频在线观看 | 精品无人区无码乱码毛片国产 | 国产成人无码a区在线观看视频app | 成 人影片 免费观看 | 自拍偷自拍亚洲精品被多人伦好爽 | 欧美xxxxx精品 | 骚片av蜜桃精品一区 | 久久综合久久自在自线精品自 | 欧美丰满熟妇xxxx性ppx人交 | 国产成人无码区免费内射一片色欲 | 欧美真人作爱免费视频 | 女高中生第一次破苞av | 欧美第一黄网免费网站 | 精品久久久久香蕉网 | 久久精品人人做人人综合试看 | 久久精品国产一区二区三区肥胖 | 爽爽影院免费观看 | 国产熟妇另类久久久久 | 99久久人妻精品免费二区 | 国产成人精品优优av | 1000部夫妻午夜免费 | 老司机亚洲精品影院无码 | 中文久久乱码一区二区 | 亚洲热妇无码av在线播放 | 人人妻人人澡人人爽欧美精品 | 国产成人综合在线女婷五月99播放 | 青青青手机频在线观看 | 中文字幕av伊人av无码av | 久久99精品国产麻豆蜜芽 | 欧美freesex黑人又粗又大 | 中国大陆精品视频xxxx | 人人澡人人妻人人爽人人蜜桃 | 两性色午夜免费视频 | 亚洲国产精品一区二区第一页 | 久久久精品456亚洲影院 | 亚洲国精产品一二二线 | 好爽又高潮了毛片免费下载 | 大屁股大乳丰满人妻 | 日本精品少妇一区二区三区 | 国产成人无码专区 | 亚洲一区二区三区四区 | 精品国精品国产自在久国产87 | 亚洲成av人综合在线观看 | 性生交片免费无码看人 | 国产精品18久久久久久麻辣 | 图片小说视频一区二区 | 日韩av无码一区二区三区不卡 | 2019nv天堂香蕉在线观看 | 激情国产av做激情国产爱 | av在线亚洲欧洲日产一区二区 | 亚洲精品午夜无码电影网 | 欧美人与物videos另类 | 夫妻免费无码v看片 | 精品国产一区二区三区av 性色 | 亚洲中文字幕乱码av波多ji | 久9re热视频这里只有精品 | 国产午夜无码精品免费看 | 亚洲熟妇色xxxxx欧美老妇 | 精品亚洲成av人在线观看 | 99精品久久毛片a片 | 欧美精品一区二区精品久久 | 东京热一精品无码av | 台湾无码一区二区 | 欧美亚洲国产一区二区三区 | 999久久久国产精品消防器材 | 国产女主播喷水视频在线观看 | 久久久av男人的天堂 | 无码吃奶揉捏奶头高潮视频 | 无码人妻出轨黑人中文字幕 | 亚洲精品鲁一鲁一区二区三区 | 无遮挡啪啪摇乳动态图 | 亚洲一区二区三区四区 | 最近的中文字幕在线看视频 | 白嫩日本少妇做爰 | 人妻插b视频一区二区三区 | 亚洲欧美国产精品久久 | 亚洲精品一区三区三区在线观看 | 国产精品久久久久久亚洲影视内衣 | 成人精品视频一区二区 | 亚洲国精产品一二二线 | 在线播放免费人成毛片乱码 | 激情综合激情五月俺也去 | 欧美人与善在线com | 国内综合精品午夜久久资源 | 国产精品欧美成人 | 久久久www成人免费毛片 | 装睡被陌生人摸出水好爽 | 国产激情无码一区二区app | 少妇无套内谢久久久久 | 扒开双腿疯狂进出爽爽爽视频 | 国产香蕉尹人综合在线观看 | 乱人伦中文视频在线观看 | 久久www免费人成人片 | 色窝窝无码一区二区三区色欲 | 国产莉萝无码av在线播放 | 亚洲色偷偷偷综合网 | 免费网站看v片在线18禁无码 | 男女爱爱好爽视频免费看 | 国产精品嫩草久久久久 | 久久精品国产亚洲精品 | 久久久婷婷五月亚洲97号色 | 日本一本二本三区免费 | 无码国模国产在线观看 | 精品无码国产一区二区三区av | 久久久久免费精品国产 | 一本色道婷婷久久欧美 | 国产乱子伦视频在线播放 | 久久亚洲日韩精品一区二区三区 | 久久人人爽人人爽人人片ⅴ | 国产av无码专区亚洲awww | 国产亚洲美女精品久久久2020 | 精品人人妻人人澡人人爽人人 | 国产成人精品视频ⅴa片软件竹菊 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 无码一区二区三区在线观看 | 亚洲精品一区二区三区四区五区 | 99国产精品白浆在线观看免费 | 亚洲国产日韩a在线播放 | 九九久久精品国产免费看小说 | 熟妇人妻无码xxx视频 | 67194成是人免费无码 | 国产人妻大战黑人第1集 | 97久久国产亚洲精品超碰热 | 久久国产精品_国产精品 | 国产精品毛片一区二区 | 亚洲 另类 在线 欧美 制服 | 国产精品内射视频免费 | 影音先锋中文字幕无码 | 亚洲日韩av一区二区三区中文 | 亚洲狠狠色丁香婷婷综合 | 日本熟妇乱子伦xxxx | 在线视频网站www色 | 十八禁视频网站在线观看 | 成人欧美一区二区三区 | 少妇性荡欲午夜性开放视频剧场 | 久久久久久久久888 | 欧美刺激性大交 | 男女下面进入的视频免费午夜 | 一本大道伊人av久久综合 | 久久精品人妻少妇一区二区三区 | 又湿又紧又大又爽a视频国产 | 色欲av亚洲一区无码少妇 | 水蜜桃亚洲一二三四在线 | 国产97人人超碰caoprom | 思思久久99热只有频精品66 | 国产亚洲精品久久久久久久久动漫 | 亚洲欧美日韩成人高清在线一区 | 中文字幕无码人妻少妇免费 | 两性色午夜免费视频 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲乱码中文字幕在线 | 亚洲国产精品毛片av不卡在线 | 亚洲大尺度无码无码专区 | 国产精品国产自线拍免费软件 | 牲欲强的熟妇农村老妇女 | 性史性农村dvd毛片 | 久久亚洲a片com人成 | 东京热一精品无码av | 亚洲日韩精品欧美一区二区 | 国产精品久久久久影院嫩草 | 55夜色66夜色国产精品视频 | 国产无套内射久久久国产 | 一本大道伊人av久久综合 | 国产成人精品必看 | 亚洲gv猛男gv无码男同 | 欧美国产日韩久久mv | 亚洲中文字幕成人无码 | 国产99久久精品一区二区 | 国产两女互慰高潮视频在线观看 | 国内综合精品午夜久久资源 | 久久精品中文字幕大胸 | 亚洲精品国产a久久久久久 | 男女超爽视频免费播放 | 人妻少妇精品视频专区 | 国产精品亚洲一区二区三区喷水 | 波多野结衣一区二区三区av免费 | 国产特级毛片aaaaaa高潮流水 | 国产深夜福利视频在线 | 色综合久久久久综合一本到桃花网 | 色婷婷久久一区二区三区麻豆 | 黑人巨大精品欧美一区二区 | 一本久道高清无码视频 | 久久 国产 尿 小便 嘘嘘 | 国产网红无码精品视频 | 任你躁国产自任一区二区三区 | 色一情一乱一伦一区二区三欧美 | 成人无码视频在线观看网站 | 日本免费一区二区三区最新 | 夜夜高潮次次欢爽av女 | 九一九色国产 | 久久成人a毛片免费观看网站 | 亚洲春色在线视频 | 露脸叫床粗话东北少妇 | 国产人妖乱国产精品人妖 | 夫妻免费无码v看片 | 51国偷自产一区二区三区 | 国产亚洲精品久久久久久 | 99精品国产综合久久久久五月天 | 日韩精品一区二区av在线 | 熟妇女人妻丰满少妇中文字幕 | 牲欲强的熟妇农村老妇女视频 | 欧美性生交活xxxxxdddd | 人妻少妇精品视频专区 | 色综合久久中文娱乐网 | 国产激情无码一区二区app | 久久久久亚洲精品男人的天堂 | 又紧又大又爽精品一区二区 | 成人精品天堂一区二区三区 | 天天燥日日燥 | 亚洲精品鲁一鲁一区二区三区 | 亚洲日韩av一区二区三区四区 | 成熟女人特级毛片www免费 | 亚洲狠狠色丁香婷婷综合 | 内射爽无广熟女亚洲 | 国产特级毛片aaaaaa高潮流水 | 欧美日韩一区二区免费视频 | 性色欲情网站iwww九文堂 | 天堂在线观看www | 夜夜躁日日躁狠狠久久av | 漂亮人妻洗澡被公强 日日躁 | 亚洲第一无码av无码专区 | 国产人妖乱国产精品人妖 | 国产综合在线观看 | av无码不卡在线观看免费 | 亚洲欧美国产精品专区久久 | 超碰97人人射妻 | 中文字幕无码乱人伦 | 亚洲熟妇色xxxxx亚洲 | 中文字幕 亚洲精品 第1页 | 欧美丰满熟妇xxxx性ppx人交 | 国产精品久久久久7777 | 久久久久99精品国产片 | 日本精品高清一区二区 | 内射巨臀欧美在线视频 | 精品无码国产自产拍在线观看蜜 | 国产精品亚洲综合色区韩国 | 精品成在人线av无码免费看 | 激情国产av做激情国产爱 | 一二三四社区在线中文视频 | 内射后入在线观看一区 | 好屌草这里只有精品 | 欧美老熟妇乱xxxxx | 沈阳熟女露脸对白视频 | 欧洲精品码一区二区三区免费看 | 久久久婷婷五月亚洲97号色 | 国产午夜精品一区二区三区嫩草 | 国产精品嫩草久久久久 | 婷婷丁香五月天综合东京热 | 国产做国产爱免费视频 | 亚洲精品中文字幕久久久久 | 成人试看120秒体验区 | 久久www免费人成人片 | 亚洲欧美国产精品专区久久 | 中文精品久久久久人妻不卡 | 任你躁国产自任一区二区三区 | 国产av无码专区亚洲awww | 日本一本二本三区免费 | ass日本丰满熟妇pics | 精品久久综合1区2区3区激情 | 中文字幕无码日韩专区 | 国产午夜福利亚洲第一 | 思思久久99热只有频精品66 | 国产 浪潮av性色四虎 | 奇米影视888欧美在线观看 | 香港三级日本三级妇三级 | 又黄又爽又色的视频 | 天堂无码人妻精品一区二区三区 | 蜜臀av无码人妻精品 | 在线精品国产一区二区三区 | 亚洲国产成人a精品不卡在线 | 亚洲一区二区三区在线观看网站 | 波多野42部无码喷潮在线 | 国产在线无码精品电影网 | 中文精品久久久久人妻不卡 | 偷窥日本少妇撒尿chinese | 特级做a爰片毛片免费69 | 性欧美牲交xxxxx视频 | 免费国产成人高清在线观看网站 | 欧美精品无码一区二区三区 | 无码毛片视频一区二区本码 | 狠狠色丁香久久婷婷综合五月 | 国产 浪潮av性色四虎 | 国产精品怡红院永久免费 | 六十路熟妇乱子伦 | 天天躁夜夜躁狠狠是什么心态 | 又大又硬又黄的免费视频 | 中文字幕无码av激情不卡 | 亚洲欧美日韩国产精品一区二区 | 无码吃奶揉捏奶头高潮视频 | 国产乱人伦av在线无码 | 无套内谢老熟女 | 国产精品福利视频导航 | 国产精品a成v人在线播放 | 99久久婷婷国产综合精品青草免费 | 初尝人妻少妇中文字幕 | 亚洲码国产精品高潮在线 | 蜜桃臀无码内射一区二区三区 | 图片小说视频一区二区 | 丁香花在线影院观看在线播放 | 亚洲成色www久久网站 | 亚洲国产一区二区三区在线观看 | 动漫av一区二区在线观看 | 国产乱子伦视频在线播放 | 色窝窝无码一区二区三区色欲 | 亚洲乱码中文字幕在线 | 大胆欧美熟妇xx | 精品欧美一区二区三区久久久 | 性欧美videos高清精品 | 国产精品久久福利网站 | 亚洲а∨天堂久久精品2021 | 少妇愉情理伦片bd | 国产特级毛片aaaaaaa高清 | 久久国产精品萌白酱免费 | 久久成人a毛片免费观看网站 | 精品国精品国产自在久国产87 | 性色欲网站人妻丰满中文久久不卡 | 久久人妻内射无码一区三区 | 女人色极品影院 | 国产av久久久久精东av | 99久久人妻精品免费二区 | 国内精品久久久久久中文字幕 | 欧美一区二区三区 | 国产精品-区区久久久狼 | 国产人成高清在线视频99最全资源 | 日本熟妇人妻xxxxx人hd | 亚洲欧美日韩成人高清在线一区 | 中文字幕人妻无码一区二区三区 | 久久综合九色综合97网 | 人人妻人人澡人人爽精品欧美 | 国产人成高清在线视频99最全资源 | 一本大道伊人av久久综合 | 久久亚洲中文字幕无码 | 色噜噜亚洲男人的天堂 | 亚洲熟妇色xxxxx欧美老妇 | 日日碰狠狠躁久久躁蜜桃 | 性色av无码免费一区二区三区 | av无码电影一区二区三区 | 成人无码精品1区2区3区免费看 | 国产农村妇女高潮大叫 | 精品无码国产自产拍在线观看蜜 | 久久天天躁狠狠躁夜夜免费观看 | 老熟妇乱子伦牲交视频 | 无码午夜成人1000部免费视频 | 成人三级无码视频在线观看 | 国产精品美女久久久 | 国产亚洲精品久久久久久大师 | 免费无码一区二区三区蜜桃大 | 国产香蕉尹人视频在线 | 亚洲中文字幕在线无码一区二区 | 极品嫩模高潮叫床 | 久久精品国产精品国产精品污 | 久久综合久久自在自线精品自 | 国产一区二区三区精品视频 | 久久亚洲a片com人成 | 国产人妖乱国产精品人妖 | 成人无码视频在线观看网站 | 麻豆国产丝袜白领秘书在线观看 | 免费人成网站视频在线观看 | 久久久精品456亚洲影院 | 水蜜桃色314在线观看 | 国产精品第一区揄拍无码 | а√资源新版在线天堂 | 国产无遮挡又黄又爽免费视频 | 日本精品久久久久中文字幕 | 牛和人交xxxx欧美 | 亚洲中文字幕av在天堂 | 18禁止看的免费污网站 | 日韩人妻无码中文字幕视频 | 午夜肉伦伦影院 | 偷窥日本少妇撒尿chinese | 麻豆国产人妻欲求不满谁演的 | av无码电影一区二区三区 | 人妻少妇精品久久 | 东京一本一道一二三区 | 日本丰满护士爆乳xxxx | 少妇久久久久久人妻无码 | 奇米影视7777久久精品 | 国产 精品 自在自线 | 中文字幕人妻丝袜二区 | 成熟女人特级毛片www免费 | 免费国产成人高清在线观看网站 | 成人欧美一区二区三区黑人 | 日韩av无码一区二区三区 | 奇米影视7777久久精品人人爽 | 波多野42部无码喷潮在线 | 亚洲精品一区二区三区大桥未久 | 亚拍精品一区二区三区探花 | 国产成人无码av片在线观看不卡 | 小泽玛莉亚一区二区视频在线 | 自拍偷自拍亚洲精品被多人伦好爽 | 久久久久成人精品免费播放动漫 | 伊人久久大香线蕉亚洲 | 久精品国产欧美亚洲色aⅴ大片 | 亚洲一区二区三区偷拍女厕 | 在线观看国产午夜福利片 | 成在人线av无码免观看麻豆 | 欧美激情内射喷水高潮 | 成 人影片 免费观看 | 久久久久免费看成人影片 | 国产三级精品三级男人的天堂 | 成人av无码一区二区三区 | 一区二区传媒有限公司 | 麻豆精品国产精华精华液好用吗 | 国内精品人妻无码久久久影院蜜桃 | 国产精品无码一区二区桃花视频 | 国产办公室秘书无码精品99 | 曰本女人与公拘交酡免费视频 | 亚洲欧美日韩综合久久久 | 国产va免费精品观看 | 国产精品久久国产三级国 | 亚洲精品国产精品乱码视色 | 国产精品资源一区二区 | 欧美 日韩 人妻 高清 中文 | 最新国产麻豆aⅴ精品无码 | 麻豆精品国产精华精华液好用吗 | 在线播放无码字幕亚洲 | 精品无码成人片一区二区98 | 国产精品久久福利网站 | 亚洲成a人片在线观看日本 | 偷窥日本少妇撒尿chinese | 一个人免费观看的www视频 | 丝袜足控一区二区三区 | 欧美xxxxx精品 | 国产电影无码午夜在线播放 | av小次郎收藏 | 色诱久久久久综合网ywww | 亚洲熟妇色xxxxx亚洲 | 人妻熟女一区 | 国内揄拍国内精品少妇国语 | 国内精品一区二区三区不卡 | 欧美大屁股xxxxhd黑色 | 精品无码国产一区二区三区av | 精品国产一区二区三区四区在线看 | 中文字幕人妻无码一区二区三区 | 午夜精品久久久久久久 | 大屁股大乳丰满人妻 | 人人超人人超碰超国产 | 鲁鲁鲁爽爽爽在线视频观看 | 久久久婷婷五月亚洲97号色 | 国产精品久久久久9999小说 | 欧美成人高清在线播放 | 宝宝好涨水快流出来免费视频 | 毛片内射-百度 | 欧美精品免费观看二区 | 成人无码视频在线观看网站 | 国产欧美精品一区二区三区 | 性做久久久久久久久 | 帮老师解开蕾丝奶罩吸乳网站 | 亚洲欧美国产精品专区久久 | 色窝窝无码一区二区三区色欲 | 成人无码精品一区二区三区 | 国产乱人无码伦av在线a | 午夜精品一区二区三区在线观看 | 夜精品a片一区二区三区无码白浆 | 鲁一鲁av2019在线 | 97色伦图片97综合影院 | 日韩av激情在线观看 | 欧美第一黄网免费网站 | 中文亚洲成a人片在线观看 | 国产精华av午夜在线观看 | 日韩无套无码精品 | 免费播放一区二区三区 | 草草网站影院白丝内射 | 帮老师解开蕾丝奶罩吸乳网站 | 亚洲国产欧美在线成人 | 1000部夫妻午夜免费 | 国产麻豆精品一区二区三区v视界 | 国产疯狂伦交大片 | 久久人人爽人人爽人人片av高清 | 大肉大捧一进一出好爽视频 | 天堂在线观看www | 2019nv天堂香蕉在线观看 | 99久久精品日本一区二区免费 | 亚洲中文字幕无码中字 | 午夜精品久久久久久久久 | 麻花豆传媒剧国产免费mv在线 | 美女极度色诱视频国产 | 东京一本一道一二三区 | 国产无遮挡吃胸膜奶免费看 | 国产一区二区不卡老阿姨 | 中文字幕无码免费久久99 | 亚洲成av人片天堂网无码】 | 国产疯狂伦交大片 | 中文字幕无码人妻少妇免费 | 精品 日韩 国产 欧美 视频 | 中文无码伦av中文字幕 | 国产疯狂伦交大片 | 久久久久久久女国产乱让韩 | 久久精品国产日本波多野结衣 | 久久99精品国产.久久久久 | 免费播放一区二区三区 | 18禁止看的免费污网站 | 亚洲爆乳精品无码一区二区三区 | 无码人妻久久一区二区三区不卡 | 扒开双腿吃奶呻吟做受视频 | 性生交大片免费看女人按摩摩 | 初尝人妻少妇中文字幕 | 亚洲国产一区二区三区在线观看 | 亚洲欧美精品伊人久久 | 亚洲色无码一区二区三区 | 狠狠色噜噜狠狠狠狠7777米奇 | 日日摸日日碰夜夜爽av | 亚洲国产精品一区二区美利坚 | 狂野欧美性猛交免费视频 | 呦交小u女精品视频 | 国产精品久久福利网站 | 日韩人妻系列无码专区 | 亚洲日韩乱码中文无码蜜桃臀网站 | 亚洲成色在线综合网站 | 久激情内射婷内射蜜桃人妖 | 久久精品国产99久久6动漫 | 亚洲a无码综合a国产av中文 | 欧美人妻一区二区三区 | 国产成人无码av一区二区 | 永久免费观看美女裸体的网站 | 少妇无码吹潮 | 中文精品久久久久人妻不卡 | 亚洲精品综合五月久久小说 | 欧美性黑人极品hd | 欧美性生交xxxxx久久久 | 十八禁真人啪啪免费网站 | 一本无码人妻在中文字幕免费 | 日韩精品无码免费一区二区三区 | 奇米影视888欧美在线观看 | 中文精品无码中文字幕无码专区 | 亚洲の无码国产の无码影院 | 精品无码成人片一区二区98 | 久久无码中文字幕免费影院蜜桃 | 国产美女精品一区二区三区 | 在线精品国产一区二区三区 | 日韩欧美群交p片內射中文 | 老司机亚洲精品影院无码 | 国产艳妇av在线观看果冻传媒 | 亚洲成a人片在线观看无码3d | 性生交片免费无码看人 | 亚洲色欲久久久综合网东京热 | 午夜福利试看120秒体验区 | 国产三级久久久精品麻豆三级 | 中文字幕无码免费久久9一区9 | 国产人妻大战黑人第1集 | 精品国产国产综合精品 | 任你躁国产自任一区二区三区 | 国产特级毛片aaaaaa高潮流水 | 亚洲欧美中文字幕5发布 | 无码成人精品区在线观看 | 国产香蕉尹人综合在线观看 | 成在人线av无码免观看麻豆 | 午夜精品久久久久久久久 | 青青青爽视频在线观看 |