亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識庫 > 在ASP.NET 2.0中操作數據之四十八:對SqlDataSource控件使用開放式并發

在ASP.NET 2.0中操作數據之四十八:對SqlDataSource控件使用開放式并發

熱門標簽:聯通官網400電話辦理 臨沂智能電話機器人加盟 400電話辦理怎么樣 蘇州如何辦理400電話 百應電話機器人外呼系統 西寧呼叫中心外呼系統線路商 網絡電話外呼系統上海 外呼電話機器人成本 地圖標注軟件免費下載

導言:

  在前面的教程里,我們考察了如何為SqlDataSource控件添加插入、更新、刪除功能。簡而言之,就是為其nsertCommand, UpdateCommand和DeleteCommd屬性賦以相應的INSERT,UPDATE和DELETESQL語句,并將相應的參數放置在InsertParameters>, UpdateParameters>和DeleteParameters>標簽里。我們可以手工書寫這些代碼,也可以通過在設置數據源向導里單擊“高級”按鈕,選擇“自動生成INSERT, UPDATE和DELETE命令”,自動的生成語句。

  在“高級SQL生成選項”對話框里有個“使用開放式并發”選項(見圖1)。當
選擇該項后,數據庫中的數據在自上一次成功保存以來沒發生任何改變的情況下,才能成功地執行更新或刪除操作。


圖1:在“高級SQL生成選項”對話框添加開放式并發支持

  在實現開放式并發教程路我們探討了開放式并發控制的基本原理以及如何對ObjectDataSource控件使用開放式并發。在本教程我們看如何對SqlDataSource控件使用開放式并發。

新的開放式并發

  在一個允許多人同時編輯或刪除相同數據的應用程序里,有這種可能:一個人修改后的記錄意外地被另一個人修改的記錄所覆蓋。在Implementing Optimistic Concurrency 這篇教程我們例舉過這樣的例子:

  例如,假設兩個用戶,Jisun和Sam,都訪問我們的應用軟件中的一個頁面,這個頁面允許訪問者通過一個GridView控件更新和刪除產品數據。他們都同時點擊GridView控件中的Edit按鈕。Jisun把產品名稱更改為“Chai Tea”并點擊Update按鈕,實質結果是向數據庫發送一個UPDATE語句,它將更新此產品的所有可修改的字段(盡管Jisun實際上只修改了一個字段:ProductName)。在這一刻,數據庫中包含有這條產品記錄“Chai Tea”—種類為Beverages、供應商為Exotic Liquids、等該產品的詳細信息。然而,在Sam的屏幕中的GridView里,當前編輯行里顯示的產片名稱依舊是“Chai”。在Jisun的更改被提交后片刻,Sam把種類更改為“Condiments”并點擊Update按鈕。這個發送到數據庫的UPDATE語句的結果是將產品名稱更改為“Chai”、CategoryID字段的值是種類Beverages對應的ID,等等。Jisun所作的對產品名稱的更改就被覆蓋了。

圖2展示了這些連續的事件


圖2:當兩個用戶同時更新一條記錄,則存在一個用戶的更改覆蓋另一個的更改的可能性

  為了應對這種可能性,我們必須執行某種并發控制。本文的焦點——開放式并發控制便是其中之一,它適合于這種情況:假定并發沖突只是偶爾發生,絕大多數的時候并不會出現。 當發生一個沖突時,僅僅簡單的告知用戶,他所作的更改不能保存,因為別的用戶已經修改了同一條記錄。

  注意:對應用程序來說,假定并發沖突經常發生,且無法容忍。在這種情況下最后用保守式并發控制。關于保守式并發控制的更多討論,請參考Implementing Optimistic Concurrency 教程。


  開放式并發控制的作用在于:確保要更新或刪除的記錄的值與該記錄在updating or deleting階段的值相同。比如,例如,當在一個可編輯的GridView里點擊編輯按鈕時,該記錄的原始值從數據庫中讀取出來并顯示在TextBox和其他Web控件中。這些原始的值保存在GridView里。隨后,當用戶完成他的修改并點擊更新按鈕,這些原始值加上修改后的新值發送到業務邏輯層,然后到數據訪問層。數據訪問層必定發出一個SQL語句,它將僅僅更新那些開始編輯時的原始值根數據庫中的值一致的記錄。圖3描述了這些事件發生的順序。


圖3:為了更新或刪除能夠成功,原始值必須與數據庫中相應的值一致

  有多種方法可以實現開放式并發控制(查看Peter A. Bromberg的文章  Optmistic Concurrency Updating Logic,從摘要中看到許多選擇)。SqlDataSource控件使用該方法(就像數據訪問層中ADO.NET類型的數據集使用的那樣)擴展WHERE字句,用以包含用來做比較的原始值。例如下面的UPDATE語句,當當前數據庫中的值與GridView中開始編輯的原始值一致才更新某個產品的名稱和價格。@ProductName 和 @UnitPrice參數包含的是用戶輸入的新值,而參數@original_ProductName 和 @original_UnitPrice則包含最初點擊編輯按鈕時加載到GridView中的值:

UPDATE Products SET
 ProductName = @ProductName,
 UnitPrice = @UnitPrice
WHERE
 ProductID = @original_ProductID AND
 ProductName = @original_ProductName AND
 UnitPrice = @original_UnitPrice

  就像我們將在本教程看到的一樣,使SqlDataSource能實現開放式并發控制是很簡單的事情。

第一步:創建一個支持開放式并發的SqlDataSource控件

  打開SqlDataSource文件夾中的OptimisticConcurrency.aspx頁面,從工具箱拖一個SqlDataSource控件到頁面,設置其ID為ProductsDataSourceWithOptimisticConcurrency。在其智能標簽里點“設置數據源”,數據庫選為“NORTHWINDConnectionString”,點下一步。


圖4:選“ORTHWINDConnectionString”數據庫

  在此例子里,我們將添加一個GridView控件以編輯表Products。所以在“Configure the Select Statement”界面選擇從表Products返回ProductID, ProductName, UnitPrice和Discontinued列,如圖5所示:


圖5:從表Products返回ProductID, ProductName, UnitPrice和Discontinued列

  然后,點“高級”按鈕,打開“Advanced SQL Generation Options”對話框,選擇“Generate INSERT, UPDATE, and DELETE statements”和“Use optimistic concurrency”2項,點“OK”(見圖1)。再點下一步、完成,結束設置。

  完成設置數據源向導后,花幾分鐘查看DeleteCommand和UpdateCommand屬性,以及DeleteParameters和UpdateParameters標簽。最快的方法是切換到“源模式”直接在頁面代碼查看,你會看到UpdateCommand的值像這樣:

UPDATE [Products] SET
 [ProductName] = @ProductName,
 [UnitPrice] = @UnitPrice,
 [Discontinued] = @Discontinued
WHERE
 [ProductID] = @original_ProductID AND
 [ProductName] = @original_ProductName AND
 [UnitPrice] = @original_UnitPrice AND
 [Discontinued] = @original_Discontinued

同時在UpdateParameters>標簽里有7個參數:

asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
 runat="server" ...>
 DeleteParameters>
 ...
 /DeleteParameters>
 UpdateParameters>
 asp:Parameter Name="ProductName" Type="String" />
 asp:Parameter Name="UnitPrice" Type="Decimal" />
 asp:Parameter Name="Discontinued" Type="Boolean" />
 asp:Parameter Name="original_ProductID" Type="Int32" />
 asp:Parameter Name="original_ProductName" Type="String" />
 asp:Parameter Name="original_UnitPrice" Type="Decimal" />
 asp:Parameter Name="original_Discontinued" Type="Boolean" />
 /UpdateParameters>
 ...
/asp:SqlDataSource>

同樣的,DeleteCommand屬性和DeleteParameters>標簽如下:

DELETE FROM [Products]
WHERE
 [ProductID] = @original_ProductID AND
 [ProductName] = @original_ProductName AND
 [UnitPrice] = @original_UnitPrice AND
 [Discontinued] = @original_Discontinued
asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
 runat="server" ...>
 DeleteParameters>
 asp:Parameter Name="original_ProductID" Type="Int32" />
 asp:Parameter Name="original_ProductName" Type="String" />
 asp:Parameter Name="original_UnitPrice" Type="Decimal" />
 asp:Parameter Name="original_Discontinued" Type="Boolean" />
 /DeleteParameters>
 UpdateParameters>
 ...
 /UpdateParameters>
 ...
/asp:SqlDataSource>

選擇了“Use optimistic concurrency”選項后,不僅擴展了UpdateCommand 和DeleteCommand屬性里的WHERE字句(同時在相關參數集里添加了參數),同時調整了以下2個屬性:

1. 將ConflictDetection屬性由“OverwriteChanges”(默認值)改為   “CompareAllValues ”
2. 將OldValuesParameterFormatString屬性由“{0}”(默認值)改為    “original_{0}”

  當數據Web控件調用SqlDataSource的Update()或Delete()方法時,它將傳遞原始值。當SqlDataSource的ConflictDetection屬性設置為“CompareAllValues”時,就會將這些原始值添加到命令中。而OldValuesParameterFormatString屬性則為這些原始值提供了命名規范,向導以“original_{0}”的形式為 UpdateCommand和DeleteCommand中的原始值以及UpdateParameters>和DeleteParameters>中的參數命名。

  注意:由于我們沒有使用SqlDataSource控件的插入功能,因此可以將InsertCommand 屬性和InsertParameters>標簽清除。

正確地處理NULL值

  不幸的是,當使用開放式并發的時候,由設置數據源向導自動生成的、擴展成包含WHERE字句的UPDATE和 DELETE命令不能處理那些含有NULL值的記錄。為什么呢?先看SqlDataSource的UpdateCommand語句:

UPDATE [Products] SET
 [ProductName] = @ProductName,
 [UnitPrice] = @UnitPrice,
 [Discontinued] = @Discontinued
WHERE
 [ProductID] = @original_ProductID AND
 [ProductName] = @original_ProductName AND
 [UnitPrice] = @original_UnitPrice AND
 [Discontinued] = @original_Discontinued

  表Products的UnitPrice列的值允許為NULL,如何某條記錄的UnitPrice確實為NULL,那么WHERE字句的“[UnitPrice] = @original_UnitPrice”總是為False,NULL = NULL總是返回False。所以凡是y包含NULL值的記錄不能被編輯或刪除,因為UPDATE和DELETE命令中的WHERE字句不能返回記錄。

  注意:這個漏洞最早于2004年6月報告給微軟,據業內傳言,微軟將在ASP.NET的下一個版本修補該漏洞。

  為修補該漏洞,我們需要在UpdateCommand和DeleteCommand屬性里手工修改所有允許為NULL值的列。一般來說,將[ColumnName] = @original_ColumnName to改成:

(
 ([ColumnName] IS NULL AND @original_ColumnName IS NULL)
 OR
 ([ColumnName] = @original_ColumnName)
)

  你可以在屬性窗口的UpdateQuery或DeleteQuery選項的代碼聲明里修改,或者在設置數據源向導的“指定自定義SQL語句或存儲過程”選項的“更新”和“刪除”標簽里修改。確保在UpdateCommand和DeleteCommand的WHERE字句里做相同的修改。如下:

UPDATE [Products] SET
 [ProductName] = @ProductName,
 [UnitPrice] = @UnitPrice,
 [Discontinued] = @Discontinued
WHERE
 [ProductID] = @original_ProductID AND
 [ProductName] = @original_ProductName AND
 (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
 OR ([UnitPrice] = @original_UnitPrice)) AND
 [Discontinued] = @original_Discontinued
DELETE FROM [Products]
WHERE
 [ProductID] = @original_ProductID AND
 [ProductName] = @original_ProductName AND
 (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
 OR ([UnitPrice] = @original_UnitPrice)) AND
 [Discontinued] = @original_Discontinued

第2步:為GridView控件添加編輯和刪除項

  當設置SqlDataSource控件支持開放式并發時,我們需要在頁面上添加一個數據Web控件,以便執行開放式并發控制。本章我們添加一個提供編輯和刪除功能的GridView控件。從工具箱拖一個GridView到頁面上,設置其ID為Products,并綁定到第一步添加的SqlDataSource控件ProductsDataSourceWithOptimisticConcurrency,最后啟用其“編輯”和“刪除”功能。


圖6:將GridView綁定到SqlDataSource并啟用編輯和刪除功能

  添加GridView控件后,優化其界面。將ProductID列移除;將ProductName列的HeaderText屬性設置為“Product”;同樣,UnitPrice列的設置為“Price”。另外,我們最好為ProductName添加一個RequiredFieldValidator控件;為UnitPrice添加一個CompareValidator控件(確保其為格式化的數字值)。參考教程Customizing the Data Modification Interface看如何自定義GridView界面。

  注意:必須確保激活GridView控件的view state(視圖狀態),因為GridView控件傳遞原始值時,將原始值保存在view state中。

  對GridView控件做了這些修改后,GridView控件和SqlDataSource控件的聲明代碼看起來和下面的差不多:

asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
 runat="server" ConflictDetection="CompareAllValues"
 ConnectionString="%$ ConnectionStrings:NORTHWNDConnectionString %>"
 DeleteCommand=
 "DELETE FROM [Products]
  WHERE [ProductID] = @original_ProductID
  AND [ProductName] = @original_ProductName
  AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
  OR ([UnitPrice] = @original_UnitPrice))
  AND [Discontinued] = @original_Discontinued"
 OldValuesParameterFormatString=
 "original_{0}"
 SelectCommand=
 "SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
  FROM [Products]"
 UpdateCommand=
 "UPDATE [Products]
  SET [ProductName] = @ProductName, [UnitPrice] = @UnitPrice,
  [Discontinued] = @Discontinued
  WHERE [ProductID] = @original_ProductID
  AND [ProductName] = @original_ProductName
  AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
  OR ([UnitPrice] = @original_UnitPrice))
 AND [Discontinued] = @original_Discontinued">
 DeleteParameters>
 asp:Parameter Name="original_ProductID" Type="Int32" />
 asp:Parameter Name="original_ProductName" Type="String" />
 asp:Parameter Name="original_UnitPrice" Type="Decimal" />
 asp:Parameter Name="original_Discontinued" Type="Boolean" />
 /DeleteParameters>
 UpdateParameters>
 asp:Parameter Name="ProductName" Type="String" />
 asp:Parameter Name="UnitPrice" Type="Decimal" />
 asp:Parameter Name="Discontinued" Type="Boolean" />
 asp:Parameter Name="original_ProductID" Type="Int32" />
 asp:Parameter Name="original_ProductName" Type="String" />
 asp:Parameter Name="original_UnitPrice" Type="Decimal" />
 asp:Parameter Name="original_Discontinued" Type="Boolean" />
 /UpdateParameters>
/asp:SqlDataSource>
asp:GridView ID="Products" runat="server"
 AutoGenerateColumns="False" DataKeyNames="ProductID"
 DataSourceID="ProductsDataSourceWithOptimisticConcurrency">
 Columns>
 asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
 asp:BoundField DataField="ProductName" HeaderText="Product"
  SortExpression="ProductName" />
 asp:BoundField DataField="UnitPrice" HeaderText="Price"
  SortExpression="UnitPrice" />
 asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
  SortExpression="Discontinued" />
 /Columns>
/asp:GridView>

  來實際地感受一下開放式并發控制。在2個瀏覽器里同時打開OptimisticConcurrency.aspx頁面,且都點擊第一條記錄的編輯按鈕。在第一個瀏覽器里改變產品名稱并點“編輯”。瀏覽器將發生回傳,GridView控件又回到“預編輯”狀態,顯示新的產品名稱。

  在第2個瀏覽器里,改變產品的價格(不要改產品名稱)后,點“編輯”。發生回傳,GridView控件又回到“預編輯”狀態,和第1個瀏覽器顯示的結果一樣——產品的名稱改變了但價格沒改變,第2個瀏覽器做的修改失敗了。然而,一切都發生的那么靜悄悄,沒有任何提示剛才發生了并發沖突!


圖7:第2個瀏覽器所做的修改悄悄的丟失了

  第2個瀏覽器更新失敗的原因在于:UPDATE命令中WHERE字句過濾掉了所以的記錄,沒有影響到任何一行記錄(即沒找到滿足條件的記錄)。我們再來看UPDATE 語句:

UPDATE [Products] SET
 [ProductName] = @ProductName,
 [UnitPrice] = @UnitPrice,
 [Discontinued] = @Discontinued
WHERE
 [ProductID] = @original_ProductID AND
 [ProductName] = @original_ProductName AND
 (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL) OR
 ([UnitPrice] = @original_UnitPrice)) AND
 [Discontinued] = @original_Discontinued

  當第2個瀏覽器更新記錄時,WHERE字句里的原始產品名(即Chai)與當前任意一條記錄的產品名不匹配(因為第1個瀏覽器將Chai改為了Chai Tea)。所以表達式“[ProductName] = @original_ProductName ”返回False,導致更新失敗。

  注意:刪除的原理于此相同。同時打開2個瀏覽器,第1個先對某個產品作更改,再在第2個瀏覽器刪除該產品,同樣是因為原始值與更新后的值不匹配,刪除失敗。

  在最終用戶(更新失敗的那個)看來,他點“更新”按鈕后,GridView控件返回“預編輯”狀態,但提交的修改丟失了。然而沒有任何直觀的提醒表明修改失敗。當用戶的更新因并發沖突失敗時,我們最好提醒用戶,比如將GridView控件保持在“編輯”狀態。下面我們來看如何實現這一點。

第3步:并發沖突的處理

  因為并發沖突拒絕用戶的更改,所以當發生并發沖突時最好提示用戶。在頁面上添加一個Label控件,其ID為ConcurrencyViolationMessage,設置其Text 屬性為“You have attempted to update or delete a record that was simultaneously updated by another user. Please review the other user's changes and then redo your update or delete”,設置其CssClass屬性為“Warning”,它定義在Styles.css中。最后,把Visible和EnableViewState屬性設置為“false” 。這樣Label控件將不可見,除非發生了某些回傳事件(我們在這些回傳事件里指定Label控件的Visible屬性為true)


圖8:在頁面添加一個Label控件用以顯示提醒信息

  執行更新或刪除操作時,當GridView的數據源控件完成更新或刪除后,才開始執行GridView控件的RowUpdated和RowDeleted事件處理器(event handler)。我們可以在這些事件處理器里計算影響了多少條記錄。假如影響了0條記錄,亦即操作失敗,我們希望將Label控件ConcurrencyViolationMessage顯示出來。

為RowUpdated和RowDeleted事件創建處理器,添加如下代碼:

protected void Products_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
 if (e.AffectedRows == 0)
 {
 ConcurrencyViolationMessage.Visible = true;
 e.KeepInEditMode = true;
 // Rebind the data to the GridView to show the latest changes
 Products.DataBind();
 }
}
protected void Products_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
 if (e.AffectedRows == 0)
 ConcurrencyViolationMessage.Visible = true;
}

  在這2個事件處理器中我們都要檢驗e.AffectedRows 屬性,如果為0,設置Label控件ConcurrencyViolationMessage的Visible屬性為true。特別的,在RowUpdated事件處理器中,我們通過將GridView控件的KeepInEditMode屬性設置為true,使其保持在編輯狀態。這樣的話,通過GridView的DataBind() 方法,將他人已經成功更新的數據顯示在編輯狀態。

如圖9所示,當發生并發沖突時,顯示提示信息


圖9:當發生并發沖突時,顯示提示信息:

總結:

  創建一個應用程序時,當多人同時編輯相同數據的時候,要考慮到并發沖突的問題。在默認情況下,ASP.NET數據Web控件和數據源控件沒有采取并發控制。就像我們在本章看到的一樣,對SqlDataSource控件使用開放式并發控制還是比較迅速和容易的。通過在UPDATE和DELETE語句里擴展WHERE字句,SqlDataSource能應對絕大部分情況,但就像在“正確處理NULL值”部分探討的那樣,對包含NULL值列的處理有漏洞。

  本章是對SqlDataSource考察的完結篇,接下來的教程繼續探討層次結構以及用bjectDataSource處理數據。

  祝編程快樂!

作者簡介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創始人,自1998年以來一直應用 微軟Web技術。大家可以點擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數據教程》,希望對大家的學習ASP.NET有所幫助。

您可能感興趣的文章:
  • jquery獲取ASP.NET服務器端控件dropdownlist和radiobuttonlist生成客戶端HTML標簽后的value和text值
  • ASP.NET jQuery 實例16 通過控件CustomValidator驗證RadioButtonList
  • ASP.NET服務器端控件RadioButtonList,DropDownList,CheckBoxList的取值、賦值用法
  • Asp.Net如何將多個RadioButton指定在一個組中
  • asp.net使用jQuery獲取RadioButtonList成員選中內容和值示例
  • ASP.NET單選按鈕控件RadioButton常用屬性和方法介紹
  • ASP.NET GridView中加入RadioButton不能單選的解決方案
  • ASP.NET中 RadioButtonList 單選按鈕組控件的使用方法
  • ASP.NET中RadioButtonList綁定后臺數據后觸發點擊事件
  • 在ASP.NET 2.0中操作數據之四十九:為GridView控件添加RadioButton

標簽:海西 慶陽 臨夏 中衛 平涼 清遠 甘肅 聊城

巨人網絡通訊聲明:本文標題《在ASP.NET 2.0中操作數據之四十八:對SqlDataSource控件使用開放式并發》,本文關鍵詞  在,ASP.NET,2.0,中,操作,數據,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《在ASP.NET 2.0中操作數據之四十八:對SqlDataSource控件使用開放式并發》相關的同類信息!
  • 本頁收集關于在ASP.NET 2.0中操作數據之四十八:對SqlDataSource控件使用開放式并發的相關信息資訊供網民參考!
  • 推薦文章
    亚洲wwwwww| 日韩专区第一页| 国产一区二区精品| 国产伦久视频免费观看视频| 久久国产精品只做精品| 亚洲天堂免费| 日韩在线观看视频免费| 精品国产香蕉在线播出| 亚欧视频在线| 日韩免费在线视频| 中文字幕97| 日韩字幕在线| 国产不卡在线观看视频| 国产91视频网| 国产91精品系列在线观看| 精品美女| 成人免费一级毛片在线播放视频| 国产一区二区高清视频| 青青久久精品| 免费国产在线观看不卡| 国产网站免费观看| 青青久久精品国产免费看| 高清一级淫片a级中文字幕 | 中文字幕97| 99色视频在线| 午夜在线影院| 国产精品自拍一区| 日韩一级黄色大片| 日韩一级黄色大片| 韩国毛片免费| 久久99中文字幕久久| 青青青草视频在线观看| 精品毛片视频| 99热精品在线| 国产成人欧美一区二区三区的| 99热视热频这里只有精品| 天天色成人| 国产视频在线免费观看| 999久久久免费精品国产牛牛| 国产不卡福利| 麻豆网站在线免费观看| 亚洲精品影院久久久久久| 精品国产一级毛片| 精品国产一级毛片| 日本在线不卡免费视频一区| 国产网站免费视频| 日本免费看视频| 九九免费高清在线观看视频| 九九热精品免费观看| 日本特黄特黄aaaaa大片| 欧美a级片免费看| 韩国三级视频在线观看| 高清一级片| 精品美女| 国产精品免费久久| 国产成人女人在线视频观看| 日韩在线观看网站| 国产一区免费在线观看| 91麻豆精品国产综合久久久| 日日爽天天| 欧美激情中文字幕一区二区| 国产一区免费在线观看| 香蕉视频久久| 国产综合91天堂亚洲国产| 国产a免费观看| 日本乱中文字幕系列| 精品久久久久久中文| 99热精品在线| 二级片在线观看| 国产美女在线一区二区三区| 高清一级做a爱过程不卡视频| 日韩中文字幕一区| 91麻豆精品国产高清在线| 毛片高清| 中文字幕一区二区三区精彩视频| 一级片免费在线观看视频| 欧美a级v片不卡在线观看| 成人免费观看男女羞羞视频| 日韩avdvd| 四虎影视库| 九九久久国产精品| 日本伦理黄色大片在线观看网站| 国产亚洲精品aaa大片| 国产不卡精品一区二区三区| 成人影院一区二区三区| 青青青草影院| 一级毛片看真人在线视频| 99久久精品国产国产毛片 | 免费一级生活片| 亚洲女初尝黑人巨高清在线观看| 99色视频在线| 午夜在线亚洲| 可以免费看污视频的网站| 欧美a级片视频| 久久精品免视看国产成人2021| 日韩免费在线视频| 欧美a免费| 国产91精品系列在线观看| 成人a大片高清在线观看| 欧美a级片视频| 欧美18性精品| 成人av在线播放| 国产亚洲精品aaa大片| 色综合久久手机在线| 91麻豆精品国产自产在线观看一区 | 一级毛片视频免费| 久久99爰这里有精品国产| 国产不卡在线看| 欧美a级片免费看| 国产一区二区精品| 精品毛片视频| 亚洲精品影院一区二区| 欧美激情伊人| 久久国产精品自由自在| 国产a网| 美国一区二区三区| 青青久热| 欧美一级视频免费| 国产伦精品一区二区三区无广告 | 欧美a级片视频| 精品国产亚洲人成在线| 日本免费看视频| 尤物视频网站在线| 欧美另类videosbestsex久久| 亚洲 激情| 久久99中文字幕| 可以免费看毛片的网站| 午夜家庭影院| 亚洲www美色| 亚飞与亚基在线观看| 亚洲精品影院| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 日本免费乱人伦在线观看 | 成人免费观看男女羞羞视频| 日本伦理黄色大片在线观看网站| 一本伊大人香蕉高清在线观看| 精品国产一区二区三区国产馆| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 免费国产在线视频| 精品视频在线观看一区二区三区| 欧美18性精品| 欧美另类videosbestsex视频| 麻豆系列 在线视频| 国产综合成人观看在线| 久久精品欧美一区二区| 国产成人啪精品视频免费软件| 91麻豆精品国产自产在线| 可以免费看污视频的网站| 欧美一区二区三区在线观看| 麻豆网站在线看| 美国一区二区三区| 日本特黄特色aaa大片免费| 99久久精品国产麻豆| 日本免费区| 日韩中文字幕在线观看视频| 日韩免费片| 久久99青青久久99久久| 99久久网站| 韩国毛片免费大片| 91麻豆精品国产高清在线| 国产伦久视频免费观看视频| 四虎影视库| 99热热久久| 国产韩国精品一区二区三区| 精品国产亚洲人成在线| 四虎影视久久久| 国产一区二区精品久| 一级毛片看真人在线视频| 精品国产一区二区三区久久久蜜臀 | 国产麻豆精品免费视频| 亚洲wwwwww| 欧美激情影院| 99久久精品国产国产毛片 | 日日爽天天| 人人干人人插| 999久久66久6只有精品| 成人a大片高清在线观看| 日韩免费在线视频| 高清一级毛片一本到免费观看| 成人免费观看的视频黄页| 欧美日本免费| 久久国产精品只做精品| 国产亚洲精品aaa大片| 久久精品成人一区二区三区| 国产网站在线| 国产国语对白一级毛片| 韩国毛片免费大片| 免费的黄色小视频| 久久久久久久网| 日韩欧美一及在线播放| 色综合久久手机在线| 精品在线免费播放| 99热视热频这里只有精品| 美女免费毛片| 久久久成人网| 日韩免费片| 日本久久久久久久 97久久精品一区二区三区 狠狠色噜噜狠狠狠狠97 日日干综合 五月天婷婷在线观看高清 九色福利视频 | 欧美1卡一卡二卡三新区| 亚洲精品久久久中文字| 国产91素人搭讪系列天堂|