日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Code First :使用Entity. Framework编程(7) ----转发 收藏

發布時間:2023/12/18 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Code First :使用Entity. Framework编程(7) ----转发 收藏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第7章

高級概念

The Code First modeling functionality that you have seen so far should be enough to get you up and running with most applications. However, Code First also includes some more advanced functionality that you may require as your needs advance. Throughout this book you’ve seen Code First’s conventions in action, but if there are one or more conventions you don’t like, Code First allows you to remove them. You may also want to get rid of that EdmMetadata table Code First is adding to your database. Code First caches its model by default, and it’s possible to override that behavior to solve problems like targeting multiple database providers in the same application in stance. This chapter will cover these topics and more.

到目前為止你已經看到Code First的建模功能應足以讓你和運行大多數應用。然而,Code First還包括一些更高級的功能,您可能有需要。在這本書中,您已經看到Code First的默認行為,但如果有一個或多個你不喜歡的約定,Code First允許你刪除它們。您可能還希望得到擺脫EdmMetadata表添加到您的數據庫。默認情況下Code First需要緩存模型,您可以覆寫這種行為來解決類似在一個應用程序中指向多個數據庫的這種情況。本章將涵蓋更多的這些主題。

Mapping to Nontable Database Objects
映射到非表數據庫對象

So far you have used Code First to map to tables, whether you are generating a database or mapping to tables in an existing database. But databases support many other types of objects, including stored procedures and views.
As of Entity Framework 4.2, Code First only has built-in support for tables, meaning that it is only capable of generating schemas that contain tables. Therefore, if you are using Code First to generate your database, you are restricted to tables.
However, if you are mapping to an existing database, you may have views, stored procedures, and other objects in the database you are mapping to. Let’s take a look at how we can interact with those.

您已經學習了使用Code First映射到表,無論是生成一個數據庫還是映射到一個現有的數據庫中的表,都是針對有表的數據庫進行。但數據庫支持許多其他類型的對象,包括存儲過程和視圖。
對EF框架4.2而言,Code First只內置表支持,這意味著它只能生產生包含表的構架。因此,如果您
使用Code First生成數據庫,就被限制在使用表工作上面。
不過,如果你是映射到一個現有的數據庫,可能有視圖,存儲過程,并映射到數據庫中的其他對象。讓我們看看如何與這些對象進行交互。

You have the option of manually editing the database schema after Code First has created it. If you do manually edit the database to include nontable objects, you can apply the same techniques discussed in this section.
The Entity Framework team has indicated that they plan to add support for mapping to other database objects in future releases.

小貼士:你可以選擇在Code First生成數據庫構架后手工編輯數據庫來包含非表對象。在本節中你就可以使用這樣的技術。

EF框架開發團隊聲稱他們已經計劃在未來的版本技持非表數據庫對象的映射。

Mapping to Updatable Views
映射到可更新的視圖

In some cases you may want to simply map an entity to a view rather than a table. For example, you may be mapping to a database that has a very large and confusing schema.To simplify things, the database might contain a view that exposes the data for your entity with more comprehensible column names. If the view is updatable, you can use the Entity Framework to insert, update, and delete data as well as selecting it. Fortunately, most databases, including SQL Server, use the same SQL syntax for interacting with views as they do for tables. This means you can simply “lie” to Code First and tell it that the view is a table. You do this by using the same configuration you use for naming tables.

在某些情況下,你可能想簡單地將實體映射到視圖,而不是表。例如,您可能需要映射到一個數據庫,它有一個非常大的和混亂的構架。為了簡單,數據庫可能包含一個視圖,使用相比實體更容易理解的列名暴露數據。如果視圖是可更新的,您可以使用EF框架來插入,更新和刪除數據以及選擇數據。幸運的是,大多數數據庫,包括SQL Server,使用相同的SQL語法與視圖交互,就好像與表格進行交互一樣。這意味著你可以簡單地“欺騙”Code First,并告訴它那個視圖就是一個表。您可以通過使用命名表中相同的配置的方法來控制它。

小貼士:不懂可更新視圖?請到MSDN中的 SQL Server’s “CREATE VIEW (Transact-SQL)”去看看,會有所幫助。

For example, perhaps you want the Destination data to come from an updateable view called my_destination_view rather than a table. You can use the Table annotation to specify the view name:

例如,假設有一個Destination數據是來自于一個可更新的視圖,名為my_destination_view。你可以使用Table標記為其指定視圖名稱:

[Table("my_detination_view")] public class Destination

Alternatively, you can use the ToTable method from the Fluent API to map to the view:

你也可能使用Fluent API的ToTable方法來映射到視圖:

modelBuilder.Entity<Destination>().ToTable("my_detination_view");
Using Views to Populate Objects
使用視圖填充對象

Not all scenarios call for mapping an entity directly to an updateable view. You may find yourself wanting to leave a class mapped to a table but to have the ability to use a view to retrieve a set of those classes in a particular scenario. For example, let’s assume that you want to leave Destination mapped to the Destinations table, but in one area of your application you want to load all the destinations from the TopTenDestinations view. You can use the SqlQuery method on DbSet to load entities based on some SQL that you write:

并非所有的情況下都可調用實體直接映射到一個可更新的視圖。在某些特殊場景里,如果一個類已經映射到一個表,而需要視圖能夠來調用一組這樣的類。舉個例子,假設你已經讓Destination表映射到了Destinations表,而在您的應用程序的一個區域里需要從TopTenDestination視圖中加載所有的destinations。您就可以使用DbSet的SqlQuery方法來加載你寫的一些以SQL為基礎的實體:

var destinations = context.Destinations.SqlQuery("SELECT * FROM dbo.TopTenDestinations");

In the above code we are using a SQL statement that bypasses Entity Framework to get back the desired Destination objects. The good thing is that once those objects are retrieved from the database, they are treated exactly the same as objects that were loaded any other way. This means you still get change tracking, lazy loading, and other DbContext features for the Destination objects that were loaded.

在上面的代碼中,我們使用一個SQL語句,繞過實體框架取回所需的目標對象。好消息是,一旦這些對象從數據庫中檢索,它們被視為與其他方式加載的對象相同。這意味著你仍然能為加載的目標對象獲得變化跟蹤,延遲加載,和其他DbContext功能。

The SqlQuery method relies on an exact match between the column names in the result set of the query you wrote and the names of the properties in your object. Because the Destination class contains DestinationId, Name, and other properties, the view must return columns with these same names. If the view does not have the same column names as the properties on your class, you will need to alias the columns in your select statement.
For example, let’s say that your TopTenDestinations view uses Id instead of DestinationId for the primary key name. In SQL Server, you can use the AS word to? alias the Id column from the view as the DestinationId column that Entity Framework
is expecting, as you can see in Example 7-1.

SqlQuery函數的方法依賴于在查詢結果集的列名和對象屬性名的精確匹配。由于目標類包含DestinationId,Name和其他屬性,視圖必須返回與其相同名稱的列。如果視圖沒有與類屬性相同的列名,需要在SELECT語句中的為列設置別名。
例如,TopTenDestinations視圖使用Id而不是DestinationId作為主鍵的名稱。在SQL Server中,可以使用AS關鍵字為Id列指定DestinationId列的別名,滿足@EF的要求,代碼7-1對此進行了解釋:

Example 7-1. Querying a database view from a DbSet

var destinations = context.Destinations.SqlQuery(@"SELECTId AS DestinationId,Name,Country,Description,PhotoFROM dbo.TopTenDestinations");

Note that the column-to-property name matching does not take any mapping into???
account. For example, if you had mapped the DestinationId property to a column??????
called Id in the Destinations table, the SqlQuery method would not use this mapping.? The SqlQuery method always attempts the column-to-property matching based on property name. Therefore, the column in the result set would still need to be called DestinationId.

請注意,列與屬性的名稱匹配并未考慮任何到帳戶的映射。例如,如果你映射DestinationId屬性到Desintaions表中的Id列,SqlQuery方法不會使用這種映射。 sqlquery函數的方法總是嘗試其于屬性名來匹配列-屬性關系。因此,仍然需要在結果集中將此列稱為DestinationId。

Using Views to Populate Nonmodel Objects
使用視圖來填充非模型對象

The two techniques we have looked at so far allow you to use a view to populate a set of objects that are part of your model. Once these objects are created, they are tracked by the context and any changes will be written back to the database. You may find yourself wanting to get the results of a view back into a read-only set of objects. The results of the view may combine data from multiple tables and therefore can’t be mapped directly to an entity that is part of your model.
For example, you may have a view called DestinationSummaryView that combines data from the Destinations and Lodgings tables. This view may have DestinationId, Name, LodgingCount, and ResortCount columns. These columns don’t match any of the entities in the BAGA model, but it would be great to be able to get the results back into a purpose-built object that you can then use in your application.

我們已經了解了兩個技術,都可以使用視圖來填充一個對象,成為模型的一部分。一旦這些對象被創建,將會被上下文跟蹤,任何更改都會寫回數據庫。您可能會發現視圖的結果返回的是只讀的對象集。視圖的結果可能會將多個表中的數據結合起來,因此不能直接映射到一個作為模型一部分的實體中。
例如,你可能有一個視圖,命名為DestinationSummaryView,組合了Destinations和Lodgings表的數據。這個視圖可能有DestinationId,Name,LodgingCount,和ResortCount列。這些列不匹配任何在BAGA模型內的實體,但它能夠將結果返回一個專用的對象,你可以在程序中自由使用。

The DestinationSummary class might look something like Example 7-2.

DestinationSummary類類似代碼7-2所示:

Example 7-2. DestinationSummary implementation

public class DestinationSummary {public int DestinationId { get; set; }public string Name { get; set; }public int LodgingCount { get; set; }public int ResortCount { get; set; } }

Because the class isn’t part of the BAGA model, you can’t use a DbSet to query for
results. Instead, you use the SqlQuery method on DbContext.Database as follows:

由于此類不是BAGA模型的一部分,不能使用DbSet來查詢結果。相反,需要使用SqlQuery方法查詢DbContext.Database:

var summary = context.Database.SqlQuery<DestinationSummary>("SELECT * FROM dbo.DestinationSummaryView");

In response, Entity Framework will run the SQL that you supplied to access the DestinationSummaryView view. It will then take these results and try to match the column names up with the property names of the DestinationSummary class that you specified in the generic argument of SqlQuery. Because the column and property names match, we will get the results of the query in a collection of DestinationSummary objects.
Because we didn’t go through a DbSet as we did in Example 7-1, the DestinationSummary objects that are created are not tracked by the context. Therefore, if you change any of the properties, Entity Framework will not pay any attention to those changes any time SaveChanges is called.

作為回應,EF框架將運行由您提供的SQL訪問DestinationSummaryView視圖。然后將這些結果嘗試使用DestinationSummary類的屬性名匹配您在SqlQuery方法的范型參數指定的列名。因為列名和屬性名相匹配,我們可以從DestinationSummary對象的集合中得到的查詢結果。
在例7-1中,我們并沒有通過DbSet創建DestinationSummary對象,因此不會被上下文跟蹤到。因此,如果你改變任何屬性,EF框架將不會關注任何在調用SaveChanges時發生的任何變化。

Working with Stored Procedures
使用存儲過程

Code First does not have any support for mapping Insert, Update, and Delete statements for your classes directly to stored procedures, as you are able to do in the designer.

Code First并不支持直接通過存儲過程來映射插入,更新和刪除命令,但是你可以在設計器中使用這些命令。

小貼士:EF框架開發團隊已經接到了大量的用戶要求支持此功能,聲明在后續版本中可能會加入支持。

Using the same techniques you just saw for working with views, you can also use stored procedures to fetch results from the database. For example, let’s say you have a Get TopTenDestinations stored procedure that takes a single parameter to specify in which country to look for destinations. You can use the SqlQuery method on DbSet to execute this procedure:

使用你剛剛在視圖中同樣的技術,也可使用存儲過程從數據庫中生成結果。例如,有一個名為TopTenDestinations 的存儲過程通過一個單一的參數來指定在哪個國家內查找目的地。你可以使用DbSet的SqlQuery方法來生成這個過程:

var country = "Australia"; var destinations = context.Destinations.SqlQuery("dbo.GetTopTenDestinations @p0", country);

Notice that SqlQuery accepts parameters. See the sidebar “SqlQuery Parameters to
Prevent SQL Injection” on page 157 for more information.

注意到SqlQuery接受一個參數,見后面“使用SqlQuery參數避免SQL注入”獲取更多信息。

As you saw above with views, you can also use the DbContext.Database.SqlQuery method to get back results from stored procedures that don’t match an entity in your model. Let’s assume you have a GetDestinationSummary stored procedure and you want to get the results in a collection of the DestinationSummary class you saw back in Example 7-2. Let’s also say this stored procedure takes two parameters—one for the country and the other for some keywords:

與視圖類似,你可以使用DbContext.Database.SqlQuery方法獲得存儲過程返回的數據,這些存儲過程并不與模型中的實體相匹配。假設有一個GetDestinationSummary存儲過程,想要獲取的結果是DestinationSummary類的集合(代碼7-2)。現在給存儲過程提供兩個參數,一個為country,另一個為某個關鍵詞:

var country = "Australia"; var keyWords = "Beach, Sun"; var destinations = context.Database.SqlQuery<DestinationSummary>("dbo.GetDestinationSummary @p0, @p1", country, keyWords);

In the above code, you can see that we’re using index-based naming for parameters. As noted in the sidebar, Entity Framework will wrap these parameters up as DbParameter objects for you to avoid any SQL injection issues. The column names in the result returned by the stored procedure will be matched with the property names on DestinationSummary. Because DestinationSummary isn’t part of the BAGA model, the results are not tracked and any changes will not be pushed back to the database.

在上述代碼中,我們為參數使用了索引名。@EF將會封裝這些參數為DbParameter對象以避免任何SQL注入問題。由存儲過程返回的列名將會匹配DestinationSummary的屬性名。由于DestinationSummary并不是BAGA模型的一部分,結果不會被跟蹤,任何更改也不會返回到數據庫中。

SqlQuery Parameters to Prevent SQL Injection
The SqlQuery method allows you to specify parameters. Entity Framework will take????
care of wrapping these into DbParameter objects to help prevent against SQL injection attacks. You use a @p prefix for parameters followed by an integer index. Entity Framework will then match these indexes up with the list of parameters you provide after the query string. As with the view-based example you saw earlier, the results of the query are tracked by the context and behave the same as results of any other query.

小貼士:使用SqlQuery參數防止SQL注入

SqlQuery方法允許指定參數。EF框架將封裝參數為DbParameter對象以防止SQL注入式攻擊。使用對參數@p前綴后附一個整數索引號來表達。EF框架將以這些索引號匹配在查詢字符串中提供的參數值。正如你在前面看到的基于視圖的案例,查詢結果可以被上下文所跟蹤,像其他查詢結果一樣使用。

Removing Conventions
刪除默認規則

In previous chapters you have seen that Code First includes a set of conventions that help build your model. You’ve seen how you can supplement or override what the conventions do using Data Annotations or the Fluent API. One other option you have is to switch off one or more of the default conventions.
Each Code First convention is implemented as a class in the System.Data.Entity.ModelConfiguration.Conventions namespace. Code First currently only allows you to remove one or more of the included conventions.
從前面的章節中可以看到,Code First包含了一系列的約定幫助你創建模型。你也看到如何設置或覆寫默認規則,可以使用Data Annoations,也可使用@FA。還有一個選項可以關閉一個或多個默認約定。

每個Code First的默認約定都被配置為一個類,這個類位于System.Data.Entity.ModelConfiguration.Conventions 名稱空間。Code First目前只允許移除一個多個包含的默認規則。

The ability to write your own conventions was included in a preview of Code First. However, the Entity Framework team removed this functionality because they felt that they didn’t have time to polish the design and get to the appropriate quality level without holding up the muchawaited release of Code First. It’s likely this feature will become available again in a future release.

小貼士:Code First的預覽版本支持編寫自己的“約定”代碼。但是,EF框架團隊在正式版取消了此功能,因為他們認為他們沒有時間去完善并不是太過令信期待的功能。很可能在未來的版本會再次提供此功能。

A full list of the Code First conventions that can be removed and a description of what each convention does is available at http://msdn.microsoft.com/en-us/library/
gg696316(v=VS.103).aspx. The complete list of conventions is also shown in
Figure 7-1

有關類列表取自微軟網站,http://msdn.microsoft.com/zh-cn/library/gg696316(v=VS.103).aspx,目前尚無中文版本。

While you can remove any of the conventions listed in Figure 7-1, we’ll use just one
OneToManyCascadeDelete—to demonstrate how to go about this process. This convention adds a cascade delete rule to all required relationships.

我們可以移除上述列表中的任何一個默認規則。這里我們只嘗試對OneToManyCascadeDelete進行移除作為展示。這個默認規則對所有必須的關系創建級聯刪除。

While you could just override the cascade behavior for every required relationship, if? you have a lot of relationships, it may make more sense just to disable the convention altogether.
Switching off conventions is done in the OnModelCreating method on your context via the DbModelBuilder.Conventions.Remove method. Add the following line of code to OnModelCreating in your BreakAwayContext class:

當然可以覆寫每個必須關系的級聯行為。但是如有很多關系,可能需要同時禁用默認規則。

關閉默認規則在context的OnModelCreating方法內進行,通過調用DbModelBuilder.Conventions.Remove方法就可以實現。在BreakAwayContext類中的OnmodelCrating方法加入如下代碼:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

The model contains a required relationship between Lodging and Destination. Up until now, Code First has been automatically adding a cascade delete rule to this relationship.With the new code in place, run the application so that the database gets recreated and this cascade delete will be removed from this relationship in the model and in the database (Figure 7-2). It will also disappear from any other required relationships that may exist.

在模型中有一個必須的關系:Lodging與Destination.當前,Code First自動為這個關系添加了一個級聯刪除。使用新代碼后,運行程序,級聯刪除就從模型和數據庫中被移除了(見圖7-2)。任何其他必須關系的級聯刪除都被去除了。

After switching off the conventions, you may decide that you want to reintroduce cas
cade delete behavior on some of the relationships. You can do this using the Fluent API as described back in Chapter 4.

In the BAGA model, it makes sense for us to have cascade delete enabled on required relationships, so go ahead and re-enable the OneToManyCascadeDeleteConvention convention by removing the modelBuilder.Conventions.Remove call we just added.

關閉默認約定后,你可能還想在許多關系中重新引入級聯刪除行為。你可以使用Fluent API來進行設置。(見第4章)

在BAGA模型中,需要在必須的關系中具有級聯刪除功能,請刪除上述代碼,恢復
OneToManyCascadeDeleteConvention默認規則。

Taking Control of Model Caching
控制模型緩存

Throughout this book you have seen how Code First takes care of a lot of things for you, but that you can take control of them and change the behavior when needed. Model caching is no exception; in fact, you likely had no idea that Code First was caching a model for you up to this point. After scanning your classes and applying conventions and configuration, Code First keeps an in-memory version of your model around so that it can be reused in the application instance. This is the reason that the OnModelCreating method is only hit once for each DbContext in an application instance. In this section, you will learn more about what model caching is, when you might need to override the conventions, and how you go about doing that.

在這本書中,你已經看到Code First管理了很多東西,但是,你可以在需要控制它,改變它的行為。模型緩存也不例外,事實上,你可能沒想到,Code First為你進行了模型的緩存。在掃描類并使用默認約定與配置后,Code First就會使模型的一個版本保持在內存中,以便可以被應用程序的實例重用。這是因為應用程序實例的每一個Dbcontext只調用一次OnModelCreating方法。在本節中,您將學習模型緩存是什么,如果需要重寫約定,應如何去做。

Understanding Model Caching
理解模型緩存

In earlier chapters, you have seen that Code First will automatically discover and build a model based on the DbSet properties that you expose on your context. The model? creation process involves taking that set of entity types, running the Code First conventions on them, and then applying any additional configuration that you specified via Data Annotations or the Fluent API. This process isn’t cheap on resources and can take some time, especially if your model is large and/or complex. To avoid incurring this cost every time you create an instance of your context, Code First runs this process once and then caches the final model for your context type. Model caching occurs at the AppDomain level.
You can see model caching in action by monitoring when the OnModelCreating method is called on your context. Add a line to the OnModelCreating method that will write to the console whenever it is called:

在前面的章節中,你已經看到,Code First會自動發現和建立一個模型,這個模型基于你在context中暴露的DbSet屬性而創建。模型創建過程中涉及到提取實體類型設置,配置Code First約定以及啟用任何由@DA或@FA實施的附加配置。這個過程很耗費資源,可能會需要一些時間,尤其是在模型很大和/或復雜的時候。為了避免每次創建上下文的一個實例所需的開銷過大,Code First每運行一次這個過程,就會緩存上下文類型的最后一個模型。模型緩存發生在AppDomain級別。
通過在context中調用OnModelCreating方法可以看到模型緩存行為,在OnModelCreating方法中添加一行如下的代碼,只要被調用就會寫入控制臺:
Console.WriteLine("OnModelCreating called!");
Modify the Main method to call the InsertDestination method a number of times?
(Example 7-3). You added the InsertDestination method itself back in Chapter 2.?

? 修改Main方法調用InsertDestination方法一定次數(代碼7-3)。InsertDestination方法見第2章。

Example 7-3. Main updated to use the context multiple times

static void Main() {Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BreakAwayContext>());InsertDestination();InsertDestination();InsertDestination(); }

After running the application again, you will see that although the code constructs and uses three separate instances of BreakAwayContext, the OnModelCreating method is only called once. This is because Code First only calls OnModelCreating while creating the model for the first context instance; after that, the final model is cached and is reused for the following uses of BreakAwayContext.

運行程序,你會發現盡管代碼構造和使用了三個BreakAwayContext實例,OnModelCrating方法只被調用了一次。這是因為Code First只有當第一次context實例創建模型時和進行調用;在那以后,最后一個模型就被加入緩存,在后面的BreakAwayContext需要時被重用。

Overriding Default Model Caching
覆寫默認的模型緩存

There aren’t many situations where you need to take control of model caching. Provided that the model for a given context type stays the same for every instance of that context with an AppDomain, the default behavior is going to work as expected. Using the default behavior is also going to give you the best performance, because model creation will only occur one time.
There are some situations where the model for a given context type may vary between instances in the same AppDomain. One example would be using a multitenant database. A multitenant database involves having the same model replicated multiple times in the same physical database. For example, you may have a model that is used to store blog posts and a website that displays them. Your website might contain a personal and a work blog that both use the same model. In the database you could have the tables used to store the data for this model replicated in two separate schemas. The tables for your work blog may live in the work schema (work.Posts, work.Comments, etc.) and the tables for your personal blog might live in the personal schema (personal.Posts, personal.Comments, etc.). Each of these sets of tables is known as a tenant. Database schemas are just one way to distinguish between tenants; there are many other patterns, such as table prefixes.
If your application needs to access multiple tenants from the same AppDomain, the mapping between classes and tables is going to be different depending on what tenant you are targeting. Different mapping means a different model, which in turn means the default model caching won’t work for you.

有許多情況需要控制模式緩存。只要AppDomain中的每一個實例中上下文類型的模型保持相同,默認行為就會按預期方式工作。使用默認行為,可以獲得最好的性能,因為模型的創建將只發生一次。
有某些情況下,給定的上下文類型的模型,在同一AppDomain中實例之間可能會有所不同。一個例子是使用多租賃數據庫。多租賃數據庫會涉及到在同一物理數據庫具有相同的模式的實例會復制多閃。例如,可能有一個模型用于存存儲blog文章,同時也用于在網站上予以顯示。您的網站可能包含個人和工作博客,都使用相同的模型。在數據庫中你可能將這一模型復制存付兩個單獨構架中的表中。工作博客使用的表可能位于work構架中(如work.Posts,work.Comments等),而個人博客可能位于personal構架中(如personal.Posts,personal.Comments等)。這些表被稱為租客。數據庫模式只是一種區分租戶的方法;還有許多其他的模式,如表前綴,。
如果您的應用程序需要訪問相同的AppDomain多個租戶,類和表之間的映射將是不同的,取決于你的目標租戶。不同的映射意味著不同的模型,這反過來又意味著默認模型緩存不會為你工作。

Another example would be using the same context to target the same model on different database providers in the same AppDomain. Different database providers means different data types for the columns in the database, which in turn means a different model. Let’s take a look at this scenario and how to handle model caching.
Add the TargetMultipleProviders method shown in Example 7-4. This method uses
the same context to access a SQL Server and SQL Server Compact Edition database.

另一個例子是同一AppDomain內,使用相同的上下文指向不同數據庫引擎的相同模型。不同的數據庫引擎意味著數據庫列中有不同的數據類型,而這又意味著不同的模型。讓我們看看在這種情況下,如何處理模型緩存。
添加例7-4中所示的TargetMultipleProviders方法。此方法使用
同樣的上下文訪問SQL Server和SQL Server Compact Edition數據庫。

You will need the SQL Server Compact Edition runtime installed to complete this section. If you have completed Chapter 6, you have already installed the runtime. If not, see “Installing SQL Server Compact Edition” on page 135. You may also remember that in Chapter 6 we had to change our model to target SQL Compact. If you want to test out this code, you will need to make the same change again here. Back in Chapter 3, we configured Trip.Identifier to be a database-generated key.
Identifier is a GUID property, and SQL Server had no problem generating values for us. SQL Compact, however, isn’t able to generate values for GUID columns. If you want to run the application, remove either the Data Annotation or Fluent API call that configures Trip.Identifier as database-generated.

小貼士:

完成本節需要安裝SQL ServerCompact Edition運行時。如果您在第6章,已經安裝了運行時,請繼續。如果沒有,請參閱前述的“安裝SQL Server Compact Edition”。您可能還記得,在第6章中,我們不得不改變我們的模型,指向SQL Compact Edition。如果你想測試一下這個代碼,你需要在這里再次作出同樣的變化。早在第3章,我們配置數據庫生成的鍵Trip.Identifier標識符是一個GUID屬性,使用在SQL Server上沒有任何問題。 SQL Compact不能產生的GUID列的值。的如果你想運行應用程序,刪除數據庫生成Trip.Identifier的Data Annoations或Fluent API配置代碼。

Example 7-4. Reusing a context to target multiple providers

static void Main(string[] args) {Database.SetInitializer(newDropCreateDatabaseIfModelChanges<BreakAwayContext>());TargetMultipleProviders(); } private static void TargetMultipleProviders() {var sqlString = @"Server=.\SQLEXPRESS;Database=DataAccess.BreakAwayContext;Trusted_Connection=true";using (var connection = new SqlConnection(sqlString)){using (var context = new BreakAwayContext(connection)){context.Destinations.Add(new Destination { Name = "Hawaii" });context.SaveChanges();}}var sqlCeString =@"Data Source=|AppData|\DataAccess.BreakAwayContext.sdf";using (var connection = new SqlCeConnection(sqlCeString)){using (var context = new BreakAwayContext(connection)){context.Destinations.Add(new Destination { Name = "Hawaii" });context.SaveChanges();}} }

Run the application. You will get an exception when trying to use the context instance that targets SQL Server Compact Edition. This will be a NotSupportedException stating that, “Using the same DbCompiledModel to create contexts against different types of database servers is not supported. Instead, create a separate DbCompiledModel for each type of server being used.”
To use the same context type with different models in the same AppDomain, you need to externally build a DbCompiledModel for each model and then use these to construct the different context instances. DbContext exposes a set of constructors that allow you to supply the model to be used, along with connection information. Add a constructor to the BreakAwayContext class that allows a DbCompiledModel and a DbConnection to be supplied:

運行程序,在試圖使用上下文實例指向SQL Server Compact Edition時會得到一個異常。這是一個NotSupportedException,言明:“不支持在不同類型的數據服務中使用同一DbCompiledModel創建contexts.可以為每種服務器創建一個單獨的context類型”。

為了在同一AppDomain中使用同一context指向不同的模型,你需要為每個模型構建一個DbCompiledModel,然后使用這個模型構建不同的上下文實例。DbContext暴露了一系構造器允許你支持模型這樣使用。添加一個構造器到BreakAwayContext類中,允許支持DbCompiledModel 和DbConnection:

public BreakAwayContext(DbConnection connection,DbCompiledModel model) : base(connection, model, contextOwnsConnection: false) { }

The code in Example 7-5 shows an updated TargetMultipleProviders method that demonstrates how this constructor can now be used to target different database providers, using a different model for each.

代碼7-5顯示了一個更新的TargetMultipleProviders方法展示如何利用這個構造器來指向不同的數據庫引擎,為各自使用不同的模型:

Example 7-5. Code updated to work with multiple providers

private static void TargetMultipleProviders() {var sql_model = GetBuilder().Build(new DbProviderInfo("System.Data.SqlClient", "2008")).Compile();var ce_model = GetBuilder().Build(new DbProviderInfo("System.Data.SqlServerCe.4.0", "4.0")).Compile();var sql_cstr = @"Server=.\SQLEXPRESS;Database=DataAccess.BreakAwayContext;Trusted_Connection=true";using (var connection = new SqlConnection(sql_cstr)){using (var context =new BreakAwayContext(connection, sql_model)){context.Destinations.Add(new Destination { Name = "Hawaii" });context.SaveChanges();}}var ce_cstr = @"Data Source=|DataDirectory|\DataAccess.BreakAwayContext.sdf";using (var connection = new SqlCeConnection(ce_cstr)){using (var context = new BreakAwayContext(connection, ce_model)){context.Database.Initialize(force: true);context.Destinations.Add(new Destination { Name = "Hawaii" });context.SaveChanges();}} } private static DbModelBuilder GetBuilder() {var builder = new DbModelBuilder();builder.Entity<EdmMetadata>().ToTable("EdmMetadata");builder.Entity<Activity>();builder.Entity<Destination>();builder.Entity<Hostel>();builder.Entity<InternetSpecial>(); builder.Entity<Lodging>();builder.Entity<Person>();builder.Entity<PersonPhoto>();builder.Entity<Reservation>();builder.Entity<Resort>();builder.Entity<Trip>();builder.ComplexType<Address>();builder.ComplexType<Measurement>();builder.ComplexType<PersonalInfo>();return builder; } ?

Let’s walk through what the code in the TargetMultipleProviders method is doing. The GetBuilder method is responsible for creating a DbModelBuilder and registering all your classes with the builder. The code in the example registers each class using the DbModelBuilder.Entity and DbModelBuilder.ComplexType methods. This approach will work if you have been using Data Annotations to configure your classes. If you have been using the Fluent API, you should copy the code from your OnModelCreating method to replace this code. Note that you also need to include the EdmMetadata class and map it to the EdmMetadata table; this allows Code First to detect when the model and database go out of sync. When DbContext is responsible for building the model, it will take care of adding this class for you.
我們來看看TargetMultipleProviders方法中的代碼做了什么。 GetBuilder方法負責創建一個DbModelBuilder,使用builder注冊所有的類。示例代碼中的每個類都使用DbModelBuilder.Entity和DbModelBuilder.ComplexType方法進行了注冊。這種方法將正常工作在已經使用Data Annoations配置過的類上。如果使用Fluent API,應該從OnModelCreating方法復制的代碼來替換這部分代碼。請注意,還需要包括EdmMetadata類,并將其映射到EdmMetadata表中,這使Code First可以到檢測到模型和數據庫是否同步。當由DbContext負責創建模型時,會對此類自動維護。

The next step is to build and compile the model for the two providers that are going to be targeted. In the example, the invariant name and manifest token for the database provider are supplied to the Build method. As an alternative, there is another overload of Build that accepts a DbConnection to get the provider information from.

下一步要為兩個需要指向的數據庫引擎建立和編譯模型。在這個例子中,不變的名稱和數據庫引擎令牌都提供給Build方法。作為一種替代方法,Builder的另一個重載,接受一個DbConnection獲得數據庫引擎信息。

With the compiled models created, they can now be used to access the two different databases. Remember that database initialization only occurs once per AppDomain, so only the first database to be used will be initialized automatically. The call to Database.Initialize on the context targeting the second database ensures that the second database is also initialized.
In the end, the new Destination is added to two different databases using the same set of classes and configurations to define duplicate models. Now that we’re done using SQL Compact, go ahead and re-enable the configuration to make Trip.Identifier database-generated.

在編譯過的模型創建后,他們現在可以用來訪問兩個不同的數據庫。請記住,數據庫初始化只在每個AppDomain發生一次,所以只有第一個要使用的數據庫將自動初始化。調用Database.Initialize是針對第二個數據庫的,確保第二個數的也得到初始化。
最后,新的Destination被添加到兩個不同的數據庫中,使用的是相同的類和相同的配置設置定義了重復的模型。現在,我們使用過SQL Compact了,重新啟用以往配置,以使Trip.Identifier鍵由數據庫生成。

Remember that building and compiling the model are expensive operations. The resulting compiled model should be cached and reused for all context instances that target the same model.

小貼士:記住構建和編譯模型是高開銷的操作。結果編譯模型應被緩存并且在同一方面的所有context實例中被重用。

Working with the EdmMetadata Table
使用EdmMetadata表

Back in Chapter 2, you learned that, by default, Code First adds an EdmMetadata table to your database. There are some advantages in allowing Code First to have this table in the database, but you also have the option of removing it. In this section, you will see how to remove the EdmMetadata table from your database. You’ll also learn about the implications of removing it.
The EdmMetadata table serves a single purpose, and that is to store a snapshot of the model that was used to create the database. Having the snapshot allows Code First to check whether the current model matches the current database or not. The snapshot is stored by taking a SHA256 hash of the database portion of the model. You can see in Figure 7-3 that the EdmMetadata table always contains a single row with the hash stored in it.

早在第2章中,您就學習到,默認情況下,Code First會將EdmMetadata表添加到您的數據庫。允許Code First在數據庫中創建這個表有一定的好處,但您也可以選擇刪除它。在本節中,你會看到如何從數據庫中刪除EdmMetadata表。您還可以了解刪除它的影響。
EdmMetadata表的存在只有一個目的,那就是存儲被用來創建數據庫的模型快照。快照允許Code First檢查當前模型是否匹配當前數據庫。快照以model數據庫部分的SHA256哈希形式來存儲。你可以看到在圖7-3 EdmMetadata表總是包含一個存儲有哈希值的單列。

Coding Against EdmMetadata
使用EdmMetadata編碼

Code First uses the EdmMetadata table in the included database initializers, but you can also interact with it programmatically using the EdmMetadata class in the EntityFramework API. Modify the Main method to call a new UseEdmMetadataTable method, shown in Example 7-6, to experiment with this class:

Code First在包含的數據庫初始化器中使用EdmMetadata表,但是你也可以使用編程方式與其交互,通過在@EFAPI中EdmMetadata類來實現。修改Main方法,調用一個新的UseEdmMetadataTable方法,如代碼7-6所示:
Example 7-6. The UseEdmMetadata method

Example 7-6. The UseEdmMetadata method static void Main() {Database.SetInitializer(new DropCreateDatabaseIfModelChanges<BreakAwayContext>());UseEdmMetadataTable(); } private static void UseEdmMetadataTable() {using (var context = new BreakAwayContext()){var modelHash = EdmMetadata.TryGetModelHash(context);Console.WriteLine("Current Model Hash: {0}", modelHash);var databaseHash =context.Set<EdmMetadata>().Single().ModelHash;Console.WriteLine("Current Database Hash: {0}", databaseHash);var compatible =context.Database.CompatibleWithModel(throwIfNoMetadata: true); Console.WriteLine("Model Compatible With Database?: {0}",compatible);} }

This code starts by using the static EdmMetadata.TryGetModelHash method to find the hash for the current model. This method will always work for Code First models, but if you attempt to use it with a model created using the designer, it will return null. The EdmMetadata class is included as part of your model, so you can use your DbContext to interact with it.
The second section of code creates a DbSet for the EdmMetadata class and then asks for the single row of data so that it can read the hash value from it. Finally, there is a??? DbContext.Database.bvgt65 method that makes it simple to check if the model and database match. This is the method that the database initializers included in the Entity Framework make use of. Specifying true for the throwIfNoMetadata parameter will cause an exception to be thrown if the EdmMetadata table has been excluded from the database. Specifying false will cause the method to return false if the table is excluded. You can run the code and see that everything currently matches.

此代碼開始使用靜態的EdmMetadata.TryGetModelHash方法,找到當前模型的哈希值。此方法會始終工作在Code First模型中,但如果您嘗試與設計器創建的模型進行工作,將返回null。 EdmMetadata類作為你的模型的一部分,所以你可以用你的DbContext與它交互。
代碼的第二部分創建了為EdmMetadata類創建了DbSet,然后索取一行數據以便可以讀取哈希值。最后,還有一個DbContext.Database.bvgt65方法,它簡單地檢查模型和數據庫是否匹配。這是包含在EF框架內部的數據庫初始化器的方法。如果EdmMetadata表從數據庫中已排除,為throwIfNoMetadata參數指定true將導致拋出一個異常。如果排除表,指定false將導致該方法返回false。您可以運行代碼并看到一切當前的匹配。

Using Code First with ObjectContext
在Code First中使用ObjectContext

Up until now, you have seen Code First being used with the DbContext API, which is??? the recommended API surface for working with Code First. DbContext was? introduced in Entity Framework 4.1 as a lighter-weight and more productive wrapper over the existing Entity Framework components. The alternative to DbContext is the ObjectContext API, and while it is recommended to use DbContext with Code First, it is still possible to use ObjectContext. In this chapter, you will see how to build a Code First model and use it to construct an ObjectContext.

至此,Code First都在使用DbContext API進行工作,這是Code First的推薦API。DbContext是一個輕型工具,在EF框架4.1中引入,封裝了現有的其他EF框架組件,更具生產力。可以使用ObjectContext代替DbContext。本章,你會看到如何使用ObjcetContext來創建Code First模型。

DbContext or ObjectContext?
DbContext is simply a wrapper over ObjectContext and associated classes. If you need some of the more advanced features that are only available from ObjectContext, you can cast DbContext to the IObjectContextAdapter interface to access the underlying ObjectContext. This approach allows you to access the functionality from ObjectCon text while still being able to write most of your code against the newer DbContext. You might consider using Code First with ObjectContext if you have existing applications that are based on ObjectContext and you are swapping from Model First or Database First to Code First.

小貼士:DbContext還是ObjectContext?

DbContext封裝自ObjectContext,并對相關類進行了簡化。如果你需要一些只有ObjectContext才能提供的高級功能 ,可以強制DbContext實現 IObjectContextAdapter接口訪問底層的ObjectContext。這種方法允許您訪問ObjectCon文本的功能,同時仍然能夠對新的DbContext寫你的代碼。您可能會考慮使用ObjectContext的代碼,首先,如果您有現有的,是基于ObjectContext和你交換首先從型號的第一或數據庫代碼的應用。

Similar to using a DbContext-based context, you start by creating a derived context,?? except this time it derives from ObjectContext and exposes ObjectSet properties instead of DbSet properties. Notice in Example 7-8 that when using an ObjectContext, you need to write a bit more code than with the DbContext. You must expose a constructor that accepts an EntityConnection. The ObjectSet properties also need to be initialized using the CreateObjectSet method; this is something DbContext takes care of for you.

類似于基于DbContext的context,你可以開始于創建一個派生的context,只不過這一次我們是派生自ObjectContext,暴露ObjectSet的屬性而不是DbSet的屬性。在代碼7-8就使用了ObjectContext,相比DbContext需要多寫一點代碼。必須暴露一個構造器接受一個EntityConnection.ObjcetSet也CreaeObjectSet方法進行初始化;這些DbContext都替您完成了。

Add this new BreakAwayObjectContext class to your DataAccess project.

添加一個新的BreakAwayObjectContext類到DataAccess項目。

Example 7-8. Implementing ObjectContext

using System.Data.EntityClient; using System.Data.Objects; using Model; namespace DataAccess {public class BreakAwayObjectContext : ObjectContext{public BreakAwayObjectContext(EntityConnection connection): base(connection){this.Destinations = this.CreateObjectSet<Destination>();this.Lodgings = this.CreateObjectSet<Lodging>();this.Trips = this.CreateObjectSet<Trip>();this.People = this.CreateObjectSet<Person>();this.PersonPhotos = this.CreateObjectSet<PersonPhoto>();}public ObjectSet<Destination> Destinations { get; private set; }public ObjectSet<Lodging> Lodgings { get; private set; }public ObjectSet<Trip> Trips { get; private set; }public ObjectSet<Person> People { get; private set; }public ObjectSet<PersonPhoto> PersonPhotos { get; private set; }} }

At this point, DbContext would take care of scanning the DbSet properties and building a model based on them. But ObjectContext has no built-in support for Code First. Code First provides a method to bridge this gap—DbModelBuilder.UseObjectContext. In the following walkthrough, you’ll learn how to leverage this to create an ObjectContext from a Code First model.

DbContext能夠自動掃描DbSet屬性并創建一個基于這些屬性的模型。但是ObjectContext沒有為Code First內建支持。Code First提供了一個方法來填補這個鴻溝,這個方法就是DbModelBuilder.UseObjectContext. 下面,我們來看如何使用這個方法在Code First模型中創建ObjectContext.

Modify the Main method to make use of a new UseObjectContext method, as shown in Example 7-9.

修改Main方法使用一個新的UseObjectContext方法,如代碼7-9所示:
Example 7-9. Code updated to use BreakAwayObjectContext

static void Main() {UseObjectContext(); } private static void UseObjectContext() {var builder = GetBuilder();var cstr = @"Server=.\SQLEXPRESS;Database=BreakAwayObjectContext;Trusted_Connection=true"; using (var connection = new SqlConnection(cstr)){var model = builder.Build(connection).Compile();using (var context =model.CreateObjectContext<BreakAwayObjectContext>(connection)){if (!context.DatabaseExists()){context.CreateDatabase();}context.Destinations.AddObject(new Destination { Name = "Ayers Rock" });context.SaveChanges();}} ?

You start by creating a DbModelBuilder, using the GetBuilder method we added earlier in this chapter. You then use the model builder to create a model and compile it. Note that you must supply the connection or provider information when building the model, as the provider affects the data types, etc. in the resulting model. With the model compiled, you can then use the CreateObjectContext method to construct the ObjectContext. This method relies on the constructor you exposed that accepts a single Entity Connection parameter. ObjectContext doesn’t support database initializers, so you also need to write code to check if the database exists and create it if it does not. Note that ObjectContext does not support EdmMetadata either, so there is no way to detect if the model and database are compatible.

以往我們都是先創建DbModelBuilder,使用GetBuilder方法添加上下文。然后使用模型構建器創建模型并進行編譯。注意在創建模型時必須提供數據庫連接或引擎信息,因為數據庫引擎類型影響最終結果數據的類型。使用編譯過的模型,也可使用CreateObjectContext方法來構建ObjectContext。這個方法依賴于你暴露的構造器,這個構造器接受一個單一的實體連接參數。ObjectContext不支持數據庫初始化器,因此必須編寫代碼檢查數據庫是否存在并在不存在的時候去創建它。注意ObjectContext不支持EdmMetadata,因此無法檢測模型和數據庫是否兼容。

Summary
小結

In this chapter, you saw a variety of advanced features that Code First provides. These features are provided to make sure that you can override what Code First does by default in situations where the default behavior just doesn’t work for your scenario. Most applications won’t require you to use these features, but it’s good to have an understanding of what is available in case you ever need them.
We’ve now covered Code First from top to bottom. We started with a high-level overview of what Code First is. You then learned how Code First builds the model and how you can customize the model by using configuration. You saw how to influence which database Code First connects to and how that database is initialized. And finally in this chapter, we wrapped things up with some advanced topics.
The final chapter of this book will help prepare you for what’s coming in future releases of Code First.

本章提供了Code First提供的一些高級特征,這些特性確保在默認行為不能滿足您工作場景需要時能夠覆寫Code First的默認設置。大多數應用程序者不需要你使用這些特征,但是理解這些特征可以作為不時之需。

到目前為止我們已經全面介紹了Code First。我們開始于一個高級別的概覽。然后學習了如何使用Code First構建模型,如何使用配置定制模型。還學習了如何影響Code First連接哪一個數據庫,如何讓數據庫初始化。最后在本章中,我們討論了一些高級話題。本書的最后一章將幫您為未來的新版本發布作些準備。

轉載于:https://www.cnblogs.com/guolihao/p/3208932.html

總結

以上是生活随笔為你收集整理的Code First :使用Entity. Framework编程(7) ----转发 收藏的全部內容,希望文章能夠幫你解決所遇到的問題。

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

www.97视频| 久久亚洲精品电影 | 国产成人一区二区三区 | 国产精品欧美日韩在线观看 | 美女视频网站久久 | 高清在线一区 | 国产91丝袜在线播放动漫 | 日韩系列在线观看 | 日韩试看 | 日韩欧美国产免费播放 | 亚洲 欧美日韩 国产 中文 | av片在线观看 | 成人一区影院 | 精品黄色在线 | 在线播放 日韩专区 | 国产又粗又猛又黄又爽 | 中文av在线免费观看 | 日韩色视频在线观看 | 国产精品原创av片国产免费 | 99这里只有精品视频 | 国内综合精品午夜久久资源 | 成人欧美在线 | 国产.精品.日韩.另类.中文.在线.播放 | 三上悠亚一区二区在线观看 | www.久久久.com| 国产午夜精品免费一区二区三区视频 | 成人影片在线免费观看 | 天天干夜夜干 | 成人wwwxxx视频 | 国产精品久久99综合免费观看尤物 | 天天操天天吃 | 欧美了一区在线观看 | 午夜久久福利视频 | 色综合亚洲精品激情狠狠 | 免费h在线观看 | 四川妇女搡bbbb搡bbbb搡 | 96精品在线| 国产黄色在线观看 | 亚洲欧美日本A∨在线观看 青青河边草观看完整版高清 | 免费在线观看成人av | 久久免费视频在线观看 | 免费无遮挡动漫网站 | 久久看免费视频 | 久久一视频 | 欧美日韩精品电影 | 亚洲天堂自拍视频 | 美女精品网站 | 91成人国产| 久久久久国产精品免费网站 | 久久久久久久久久久免费av | 久久午夜视频 | 婷婷在线免费观看 | 久久精品三 | 69国产盗摄一区二区三区五区 | 91九色精品女同系列 | 日韩欧美成人网 | 欧美视频日韩视频 | 九九视频在线观看视频6 | 欧美精品久久久久a | 国产麻豆视频免费观看 | 毛片随便看| 国产一级精品视频 | 色综合久久久久综合99 | av免费看av | 国产xxxxx在线观看 | 色老板在线| 激情深爱 | 在线观看韩日电影免费 | 免费在线观看毛片网站 | 日韩免| 日韩精品一区二区三区在线播放 | 国产精品免费一区二区三区在线观看 | 久草免费色站 | 日韩精品在线免费观看 | 亚洲干| 中文字幕乱码电影 | 草久久久久久久 | 色爽网站 | 99久久综合狠狠综合久久 | 国产精品第一页在线 | 国产精品激情 | 在线播放日韩 | 美女av免费看| 久久精品一区二区三区视频 | 久久综合一本 | 人人爽人人爱 | 蜜臀一区二区三区精品免费视频 | 久久久久99精品成人片三人毛片 | 免费在线激情电影 | 免费看黄电影 | 成人a在线观看 | 99re8这里有精品热视频免费 | 九色porny真实丨国产18 | 91禁在线看| 中文在线www | 国产精品区一区 | 五月婷婷一区二区三区 | 99看视频在线观看 | 丝袜+亚洲+另类+欧美+变态 | 久久天天综合网 | 狠狠的干 | 色婷婷亚洲综合 | 最新精品视频在线 | 一区精品在线 | 国产精品久久99 | 片网站 | 成人黄色大片在线免费观看 | 999久久国产精品免费观看网站 | 精品久久久久久久久久国产 | 伊人导航| 一本到在线 | 成人久久影院 | 欧美日本国产在线观看 | 精品国产一区二区三区在线观看 | 热久久电影 | 精品亚洲欧美一区 | 91喷水 | 久久网站av | 91精品国自产在线偷拍蜜桃 | 99爱视频在线观看 | 日本黄色免费在线观看 | 青青久草在线视频 | 在线v片免费观看视频 | 国产成年免费视频 | 国产手机在线观看视频 | 成年人黄色免费网站 | 国产日本亚洲高清 | 黄色亚洲精品 | .国产精品成人自产拍在线观看6 | 在线观看国产福利片 | 亚洲精品免费在线播放 | 国产精品成人在线 | 免费日韩av片 | a级一a一级在线观看 | av片子在线观看 | 久久久国产一区二区 | 最近中文字幕在线 | 亚洲精品资源 | 在线观看一 | 日日夜夜天天久久 | 在线看国产视频 | 婷婷婷国产在线视频 | 深爱激情av | 狠狠干免费| 国产日韩精品一区二区 | 欧美精彩视频在线观看 | 一区二区三区电影在线播 | 狠狠狠色丁香综合久久天下网 | 六月丁香婷婷网 | 在线视频1卡二卡三卡 | 成人av中文字幕 | 99热在| 日韩成人黄色av | 国产精品免费成人 | 亚洲精品在线国产 | 中文字幕电影高清在线观看 | 国产精品毛片久久 | 精品视频久久久久久 | 在线视频日韩 | 日韩欧美在线影院 | www黄免费 | av视屏在线 | 91成人蝌蚪 | 在线亚洲人成电影网站色www | 丁香婷婷综合网 | 午夜视频导航 | 精品日韩av | 久久艹人人| 青草视频在线 | 欧美成亚洲 | 黄色免费高清视频 | 午夜黄网 | 国产高清不卡av | 97在线公开视频 | 久久成人毛片 | 人人dvd| 久久久精品在线观看 | 大型av综合网站 | 国产黄色免费看 | 激情婷婷综合 | 婷婷综合国产 | 中文字幕av在线电影 | 成人av视屏 | 五月综合色 | 免费影视大全推荐 | 在线观看日韩精品视频 | 97免费视频在线播放 | 久久久久亚洲精品国产 | 91在线蜜桃臀| www.日本色 | 91免费国产在线观看 | 国产成人精品综合久久久 | 97香蕉久久超级碰碰高清版 | 波多野结衣在线播放一区 | 久草av在线播放 | 91精品视频导航 | 欧美日韩伦理一区 | 在线电影日韩 | 天天天色综合 | aaa日本高清在线播放免费观看 | 亚洲成av片人久久久 | 欧美aaa大片 | 国产成人综合图片 | 国产日韩欧美精品在线观看 | 欧美成人一区二区 | 精品视频亚洲 | 黄色免费网战 | av中文字幕在线观看网站 | 99久久国产免费,99久久国产免费大片 | 婷婷综合av | 就操操久久 | 日日激情| 日韩成人xxxx | 国产精品永久免费在线 | 天天摸夜夜添 | 在线成人免费电影 | 一色屋精品视频在线观看 | 中文字幕黄色网 | 欧美日韩中文在线视频 | 久草精品电影 | 91女神的呻吟细腰翘臀美女 | 韩国av免费观看 | 久草精品在线播放 | 久久久黄视频 | 婷婷丁香狠狠爱 | 久久无码精品一区二区三区 | 久草免费在线观看 | 91欧美日韩国产 | 悠悠av资源片 | 久久视频这里有精品 | av蜜桃在线 | 欧美激情精品久久久久久 | 人人天天夜夜 | 伊人久久五月天 | 久久免费福利视频 | 9ⅰ精品久久久久久久久中文字幕 | 久久综合99| 欧美性做爰猛烈叫床潮 | 91av福利视频 | 99人成在线观看视频 | 在线观看爱爱视频 | 国产亚洲观看 | 女人18片| 日韩簧片在线观看 | 成人午夜电影在线 | 日韩精品一区二区三区中文字幕 | 国产一级黄色片免费看 | 亚洲色图22p | 在线小视频你懂得 | 激情偷乱人伦小说视频在线观看 | 97人人添人澡人人爽超碰动图 | 久草免费看 | 91成人在线观看喷潮 | 久久精选视频 | 日韩高清不卡一区二区三区 | 亚洲视频专区在线 | 成人午夜精品福利免费 | 超碰人人超 | 日韩精品一区二区三区不卡 | 午夜精品999 | 久久久久久久久久久影视 | 国产综合在线观看视频 | 深爱综合网 | 干干干操操操 | 国产一级在线观看视频 | 亚洲理论片在线观看 | 一级全黄毛片 | 青青网视频 | 久久激情视频 久久 | 亚洲成人高清在线 | 午夜日b视频 | 成人一区二区三区中文字幕 | 91黄色小网站 | a级国产毛片 | 精品一区二区三区香蕉蜜桃 | 久色小说 | 日韩专区在线 | 日韩精品一区二区三区在线播放 | 操处女逼| 中日韩男男gay无套 日韩精品一区二区三区高清免费 | 亚洲 欧美 变态 国产 另类 | 成人免费看片网址 | 在线看不卡av | 欧美性极品xxxx做受 | 国产99在线免费 | 亚洲国产一二三 | 国产午夜精品一区二区三区 | 国产成人av一区二区三区在线观看 | 伊人久久av| 韩国一区视频 | 人人爽人人爽人人片av免 | 一区在线电影 | 精品福利网站 | 在线观看视频中文字幕 | 免费视频xnxx com | 亚洲久草在线视频 | 中文字幕国内精品 | 婷婷久操| 97av影院| 特级a毛片 | 久久精品一区二区三区国产主播 | 欧美一级片在线观看视频 | 欧美日韩国产欧美 | 免费观看久久 | 午夜精品婷婷 | 深爱激情综合 | 天天操天天干天天爽 | 国产成人一区二区三区久久精品 | 97在线观看视频国产 | 97国产视频 | 久久国产精品精品国产色婷婷 | 亚洲日本va在线观看 | 国产午夜激情视频 | 精品国产_亚洲人成在线 | 久久久久久久久综合 | 激情久久小说 | 日韩1级片 | 成人在线视频你懂的 | 中文字幕亚洲高清 | 黄网站app在线观看免费视频 | 97超级碰碰碰碰久久久久 | 国产精品永久免费在线 | 日本不卡一区二区 | 亚洲国产精品成人av | 日韩av在线免费播放 | 在线a亚洲视频播放在线观看 | 国产日韩欧美在线一区 | 人人看人人草 | 亚洲午夜剧场 | 国产精品久久电影网 | 亚洲精品麻豆 | 亚洲视频 视频在线 | 日韩久久片 | 国产精品一区二区在线观看免费 | 丁香婷婷激情啪啪 | 五月天六月婷婷 | 日韩高清一二区 | 偷拍精品一区二区三区 | 麻豆首页| 精品久久久久久电影 | 国色天香永久免费 | 国产高清在线观看 | 中日韩在线视频 | 国产成人久久av免费高清密臂 | 人人爽人人| 中文字幕精品视频 | 中文日韩在线 | 成人av在线网址 | 日韩成人看片 | 毛片基地黄久久久久久天堂 | 日本久久久久久久久久 | 九九热在线观看视频 | 国产精品一区二区久久精品 | 久久男人视频 | 高清一区二区 | 国产美女精品视频 | 天天色综合天天 | 国产一二区精品 | 免费看一及片 | www视频在线免费观看 | 天天玩夜夜操 | 国产视频精品免费 | 日韩在线高清 | 亚洲免费精品一区二区 | 一二区av| 欧美日韩一区二区在线观看 | 国产成人精品久久久 | www.com黄色| 麻豆国产在线视频 | 成片免费 | 国产精品成人一区二区三区吃奶 | 久久精品在线 | 国产精品mv在线观看 | 日韩欧美精品一区二区 | 日韩电影在线一区二区 | 97超碰人人澡人人爱学生 | 美女黄频视频大全 | 国产高清视频免费在线观看 | 四虎国产精| 久久y| 久久久免费看片 | 青草视频在线 | 91精品国产一区二区三区 | av动图 | 欧美精品一区二区三区四区在线 | 天天操天天综合网 | 狠狠色2019综合网 | 一区二区三区三区在线 | 国产精品精 | 国产精品久久久久国产精品日日 | 99热都是精品 | 国产视频18 | 久久精品久久国产 | 成年人在线免费看视频 | 91精品国产乱码 | 午夜少妇一区二区三区 | 91人人射| 日韩69av | 在线观看完整版 | 日韩中文字幕免费 | 九色视频自拍 | 国产精品久久久久久久久久久免费看 | 色www精品视频在线观看 | 亚洲.www | 伊人伊成久久人综合网小说 | 亚洲精品视频大全 | 午夜.dj高清免费观看视频 | 丰满少妇久久久 | 少妇高潮流白浆在线观看 | 欧美另类高清 videos | 成人毛片a | 日韩视频免费 | 亚洲黄色激情小说 | 久久精品久久精品久久39 | 久久久精品网站 | 中文字幕高清视频 | av成人黄色 | 中文字幕在线观看你懂的 | 国产91影院 | 涩五月婷婷 | 久久人人爽人人片 | 欧美视频99 | 97人人爽人人 | а中文在线天堂 | 日韩电影精品一区 | 久久久国产一区二区三区四区小说 | 亚洲日本国产 | 黄色一级网 | 91在线操| 亚洲在线网址 | 欧美久久久久久久久中文字幕 | 黄色av电影免费观看 | 久草综合视频 | 日韩久久视频 | 国产高清一区二区 | 在线网址你懂得 | 婷婷色六月天 | 中文字幕在线观看播放 | 精品一区二区日韩 | 亚洲最新在线 | 91av社区 | 精品一区 精品二区 | 日本黄色a级大片 | 午夜精选视频 | 在线视频你懂得 | 丰满少妇在线观看网站 | 在线三级av | 日本中文字幕免费观看 | 国产精品女同一区二区三区久久夜 | 久草在线免费看视频 | 久久久国产高清 | 天天操夜夜拍 | a色视频 | 精品久久久久久久久久久久久久久久久久 | 99在线热播精品免费 | 久久久久久久国产精品视频 | 久草在线免费看视频 | 国产视频久久久 | 中文字幕在线字幕中文 | 波多野结衣电影一区二区三区 | 欧美精品你懂的 | 激情欧美xxxx | 国产精品美女久久久久久 | 欧洲精品久久久久毛片完整版 | 久久在线免费视频 | 亚洲一区网 | 奇米影视四色8888 | 久久精品国产美女 | 亚洲婷婷综合色高清在线 | 91久色蝌蚪 | 亚州国产精品 | 91精品视频在线 | 欧美91在线| 亚洲国产精久久久久久久 | 91精选在线 | 人人澡人人添人人爽一区二区 | 五月婷婷开心中文字幕 | 色视频国产直接看 | 色之综合网 | 欧美日韩亚洲精品在线 | 在线视频久 | 亚洲国产三级在线 | 欧美激情视频一二三区 | 欧美性色综合 | 国内精品久久久久影院日本资源 | 国产精选视频 | 日本少妇视频 | 欧美一级艳片视频免费观看 | 国产丝袜网站 | 91超碰在线播放 | 丰满少妇久久久 | 在线免费观看国产视频 | 欧美一级视频免费看 | 国产精品一区二区三区四区在线观看 | 天天干,天天操,天天射 | 精品在线观看一区二区 | 国产护士av| 天天插夜夜操 | 国产精品电影在线 | 日本性高潮视频 | 午夜影院一级 | 久久字幕精品一区 | 国产精品18久久久久久久久久久久 | 在线视频日韩精品 | 国产一区在线精品 | 999免费视频 | 中文国产字幕在线观看 | 精品久久久久久久久久久久久久久久 | 99久久久久久久久 | 人人狠狠综合久久亚洲 | 午夜影院三级 | 国产精品无 | 精品免费观看 | 国产黄在线播放 | av免费在线观看网站 | 免费日韩 精品中文字幕视频在线 | 精品一区二区久久久久久久网站 | 在线观看色视频 | 在线观看免费一级片 | 日本视频网 | 国产精品涩涩屋www在线观看 | 午夜av电影 | 99电影 | 免费在线一区二区三区 | 国产精品尤物 | 一区二区三区高清在线观看 | 波多野结衣久久资源 | 亚洲精品综合一区二区 | 国产一区二区观看 | 成人久久久电影 | 综合久久一本 | 99久久99久久精品国产片果冰 | 欧美日韩国产亚洲乱码字幕 | 久久久久蜜桃 | 天天干,天天操,天天射 | 91亚洲在线 | 日本大尺码专区mv | 国产成人精品av久久 | 五月天丁香综合 | 天天射夜夜爽 | 日韩v欧美v日本v亚洲v国产v | a黄色 | 国产日韩精品一区二区三区 | 91漂亮少妇露脸在线播放 | 亚洲精品午夜一区人人爽 | 久久久久久久久影院 | 久草久热| 成人97视频一区二区 | 国产一级黄色av | 婷婷六月综合亚洲 | 欧美日韩一区二区三区在线免费观看 | 日韩影视大全 | 国产专区在线视频 | 成年人免费看片 | 91视频 - 88av | 精品久久久久久国产偷窥 | 伊人久操 | 91爱看片| 五月综合| 久久精品视频国产 | 国产精品自产拍在线观看桃花 | 亚洲男男gaygay无套 | 亚洲精品久久久久58 | 99欧美视频 | 蜜臀久久99精品久久久无需会员 | 日韩啪啪小视频 | 欧美一区二区三区免费看 | 五月婷婷色丁香 | 亚州成人av在线 | 国产精品不卡 | 国产麻豆视频免费观看 | 日日碰夜夜爽 | 99草在线视频 | 国产尤物一区二区三区 | 91热在线 | 天天想夜夜操 | 国产成人精品在线观看 | 色狠狠综合天天综合综合 | 伊人久久五月天 | 亚洲国产精品va在线看黑人动漫 | av免费网站观看 | 国产日韩欧美在线免费观看 | 在线探花| 中文字幕精品三区 | 亚洲成人av片在线观看 | 超碰av在线 | 午夜国产一区 | 欧美精品一区二区蜜臀亚洲 | 黄色电影在线免费观看 | 久久精品国产精品 | 69视频网站 | 激情五月开心 | 五月婷婷综合激情网 | japanesefreesex中国少妇 | 99国产精品久久久久老师 | 最新av在线免费观看 | 欧美日韩久久久 | 色吊丝在线永久观看最新版本 | 亚洲不卡在线 | 99久久毛片 | 亚洲国产视频直播 | 四虎影视精品永久在线观看 | 五月婷婷伊人网 | 婷婷综合在线 | 国产91免费看 | 91精品国产高清自在线观看 | 九九色网| 午夜精品久久久久久久99 | 国产精品v欧美精品 | 久久成人一区二区 | 蜜臀一区二区三区精品免费视频 | 免费亚洲黄色 | 99热精品久久 | 欧洲一区二区在线观看 | 成年人在线观看视频免费 | 成人久久久久久久久久 | 91日韩精品一区 | 中国美女一级看片 | av在线免费在线观看 | 狠狠色狠狠色综合日日小说 | 亚洲精品国产精品国自产观看浪潮 | 91av亚洲 | japanesefreesex中国少妇 | 五月激情av | 久久精品国产一区二区三 | 81国产精品久久久久久久久久 | 日韩午夜一级片 | 在线电影a | 亚洲欧美视频一区二区三区 | 免费激情在线电影 | 日韩视频一 | 欧美激情视频在线免费观看 | 激情欧美日韩一区二区 | 精品美女久久久久久免费 | 色偷偷男人的天堂av | 免费黄在线观看 | 欧美日韩精品在线 | 在线影视 一区 二区 三区 | 97碰碰精品嫩模在线播放 | 97超碰人人模人人人爽人人爱 | 人人澡人摸人人添学生av | 黄色av网站在线观看免费 | 久久99久久99 | 日韩免费在线视频 | 国产成人一区二区三区免费看 | 久久高视频 | 中文在线资源 | 久久免费精品一区二区三区 | 97免费在线观看 | 国产视频2021 | 欧美精品日韩 | 亚洲精品在线观 | 91九色最新地址 | 天天做综合网 | 国产色拍拍拍拍在线精品 | 免费特级黄毛片 | 欧美日韩一区久久 | 色91av| 91影视成人 | 久久视频免费看 | 亚洲国产中文字幕在线视频综合 | 国产一级二级在线观看 | 九色porny真实丨国产18 | 天天摸天天干天天操天天射 | 99久久久国产精品免费99 | 日韩大片在线 | 99久久久国产精品免费99 | 夜又临在线观看 | 中文字幕av全部资源www中文字幕在线观看 | 亚洲精品国偷拍自产在线观看蜜桃 | 色综合色综合久久综合频道88 | 国产69精品久久99不卡的观看体验 | 欧美久久久久 | 国产精品一区二区久久国产 | 91资源在线观看 | 四虎影视成人永久免费观看亚洲欧美 | 日韩久久精品一区二区三区 | 久久毛片视频 | 欧美午夜视频在线 | 最新中文字幕在线播放 | 正在播放国产一区二区 | 热久久影视 | 亚洲精品视频在线观看网站 | 欧美日韩精品在线 | 日日夜夜人人天天 | 久久久久久久久久久精 | 久久久www免费电影网 | 中文字幕视频一区 | 中文字幕乱码视频 | 国产a国产 | 成人一区二区三区中文字幕 | 夜夜躁天天躁很躁波 | 天天干,天天射,天天操,天天摸 | 亚洲日本一区二区在线 | 亚洲一区二区高潮无套美女 | 免费观看一级特黄欧美大片 | 欧美精品乱码久久久久久 | 国产精品刺激对白麻豆99 | 91高清一区 | 国产亚洲成av片在线观看 | 久久精品久久精品久久精品 | 欧美成人在线网站 | 91久久丝袜国产露脸动漫 | 香蕉视频18 | 96国产精品 | 久久伦理 | 欧美视频在线观看免费网址 | 国产黄色片久久久 | 精品福利视频在线 | 91成人免费看片 | 亚洲欧美激情精品一区二区 | 午夜丁香网 | 日韩 在线观看 | 久草视频在线资源 | 国产精品理论片在线播放 | www.精选视频.com | 中文字幕不卡在线88 | 亚洲国产一二三 | www狠狠| 97超碰成人在线 | 亚洲精品66| 亚洲麻豆精品 | 国产小视频你懂的 | 9999激情 | 九色精品在线 | 国产女人免费看a级丨片 | 国产精品mm | 成年人视频在线免费 | 97精品国自产拍在线观看 | 超碰在线色 | 最近免费中文视频 | 日韩精品视频在线观看免费 | 国产亲近乱来精品 | 中文字幕在线看视频国产中文版 | 99热精品国产一区二区在线观看 | 超碰在线天天 | 美女视频黄免费的 | 国偷自产视频一区二区久 | 91片在线观看 | 在线免费观看涩涩 | 欧美日韩亚洲在线观看 | 久久99国产精品久久99 | 国产视频久久 | 制服丝袜一区二区 | 久久亚洲人 | 最近免费在线观看 | 精品国产伦一区二区三区观看方式 | 在线免费观看的av | 色视频成人在线观看免 | 99精品免费视频 | 日韩天天干 | 91视频在线播放视频 | 免费又黄又爽视频 | 777奇米四色| 久久免费视频这里只有精品 | 天天做日日爱夜夜爽 | 精品视频不卡 | av在线网站大全 | 九九爱免费视频 | 精品综合久久久 | 亚洲激情网站免费观看 | 视频一区二区在线观看 | 欧美在线一二区 | 日韩精品一区二区三区第95 | 欧美一级视频一区 | 欧美日在线观看 | av高清一区二区三区 | 成人午夜免费剧场 | 欧美日韩高清一区二区 国产亚洲免费看 | 一区三区在线欧 | 97视频入口免费观看 | 中文字幕视频播放 | 夜夜爽天天爽 | 欧美一区二区伦理片 | 婷婷久久国产 | 亚洲精品小视频在线观看 | 久久精品中文 | 国产精品免费不卡 | 亚洲精品美女在线观看播放 | 亚洲精品在线观看免费 | 日本久久免费视频 | 日韩大片免费在线观看 | 色 中文字幕| 天天操夜操 | 成人精品一区二区三区电影免费 | 国产精品一区在线观看你懂的 | 久久不射电影网 | 免费精品人在线二线三线 | 中文字幕日韩电影 | 亚洲无吗视频在线 | 综合久久久 | 激情文学综合丁香 | 波多野结衣精品在线 | 日韩激情网 | 国产色网| 久久精品亚洲综合专区 | 欧美性色xo影院 | 国内小视频在线观看 | 综合精品久久久 | 特黄特黄的视频 | 亚洲精品国产第一综合99久久 | 日日夜夜人人天天 | 成人一区在线观看 | 国内精品久久久久影院一蜜桃 | 中文字幕123区 | 天天综合网~永久入口 | 久久久久亚洲国产精品 | 在线看一区 | 久久精品视频18 | 人人射人人澡 | 亚洲香蕉在线观看 | 国产成人一区二区三区电影 | 国产精品久99 | 亚洲午夜剧场 | 国产一区二区久久久 | 日本公乱妇视频 | 欧美一区二区在线刺激视频 | 人人舔人人爱 | 成年人免费在线观看网站 | 久草.com| 91成人精品国产刺激国语对白 | 激情网站| 一区二区三区四区五区在线 | www.黄色片.com | 中文字幕色婷婷在线视频 | 久久久久久国产精品 | 最新极品jizzhd欧美 | 中文字幕国产在线 | 在线看国产精品 | 日韩特级毛片 | 久草在线视频网 | 97**国产露脸精品国产 | 91av成人 | 日本中文字幕视频 | 国产黄色大片 | 国产呻吟在线 | 欧美巨大 | 久久久久久久久久久免费 | 精品一二三区 | 亚洲精品在线观看视频 | 欧美日韩在线视频观看 | 色噜噜日韩精品欧美一区二区 | 欧美日韩在线播放 | 在线免费看黄色 | 国产精品视频不卡 | 欧美激情综合五月 | 99精品欧美一区二区三区 | 日韩伦理一区二区三区av在线 | 日韩黄色大片在线观看 | 9热精品 | 亚洲jizzjizz日本少妇 | www久久com| 国产小视频在线观看 | 91成人在线观看喷潮 | 天天操天| 四虎成人精品永久免费av | 欧洲精品视频一区 | 欧美性成人 | 久久视频精品在线观看 | av在线影视 | 日韩伦理片hd | 国产成人高清 | 欧美精品久久久久久久免费 | 国产粉嫩在线 | 人人插人人干 | 国产精品美女久久久久久 | 亚洲夜夜综合 | 综合伊人久久 | 中文字幕色网站 | 日韩视频中文 | 色婷婷综合成人av | 天天色天天干天天 | 波多野结衣资源 | 日韩欧美中文 | 久久久久国产一区二区三区 | 亚洲人精品午夜 | 黄色软件视频大全免费下载 | 天天射天天操天天 | 成人av在线亚洲 | 在线亚洲人成电影网站色www | 伊人婷婷色 | 99久久精品网| 日本丰满少妇免费一区 | 国产1区2| 国产精品不卡视频 | 91在线看 | av超碰在线 | 国产69久久久欧美一级 | 日韩三级av | 国产福利在线 | 国产精品丝袜在线 | 国产精品一区二区三区在线播放 | 免费久久99精品国产 | 成人久久18免费网站图片 | 91麻豆精品国产91久久久无限制版 | 狠狠色丁香九九婷婷综合五月 | 伊人伊成久久人综合网小说 | 国产精品一区免费看8c0m | 麻豆免费视频 | 国产一区欧美二区 | 国产打女人屁股调教97 | 激情动态 | 麻豆一二 | 深爱婷婷激情 | 天天激情综合网 | 91av在线免费 | 五月天视频网站 | 亚洲人成在线电影 | 日韩在线观看小视频 | 国产一区二区久久精品 | 美女网站在线观看 | 一级a毛片高清视频 | 国产精品一区二区免费在线观看 | 99久久精品国产免费看不卡 | 免费h精品视频在线播放 | 九色最新网址 | 国产精品嫩草影院99网站 | 特级西西444www大胆高清无视频 | 一区二区视频网站 | 国产视频2区 | 精品一区欧美 | 久草网在线 | 免费黄色在线播放 | 久久综合九色综合网站 | 亚洲六月丁香色婷婷综合久久 | 亚洲视频分类 | 国产亚洲一区二区三区 | 国产做a爱一级久久 | 在线观看国产区 | 国产日韩欧美综合在线 | 亚洲h在线播放在线观看h | 久久久久国产一区二区三区 | 久久久亚洲精品 | 亚洲精品麻豆 | 天天干夜夜想 | 日韩成人一级大片 | 久久免视频 | 久久手机免费观看 | 日韩二区三区 | 在线性视频日韩欧美 | 啪啪免费视频网站 | 亚洲理论在线观看电影 | 米奇影视7777 | 一区二区视频在线播放 | 天天看天天干天天操 | 久久免费毛片视频 | 97免费在线观看视频 | 成人丁香花 | 久久久久久久久爱 | 在线观看成人av | 久久精品毛片 | 久草视频播放 | 国产原创在线视频 | 国产精品毛片久久久久久 | 久久久2o19精品 | 91成人蝌蚪 | 欧美特一级 | 免费看污在线观看 | av在线成人| 97夜夜澡人人双人人人喊 | 欧美一级电影在线观看 | 在线观看av国产 | 精品久久久久国产免费第一页 | 97免费视频在线 | 麻豆久久久久久久 | 在线国产一区二区三区 | 国产v亚洲v | 人人看人人做人人澡 | 成人久久精品 | 国产免费人成xvideos视频 | 91av片| 国产精品一区二区av麻豆 | 亚洲激情校园春色 | 久人人| 国产在线a视频 | 天天艹天天干天天 | 在线a视频 | 美女黄频在线观看 | 狠狠色丁香婷婷综合 | 伊人午夜视频 | 国产香蕉av| 超碰97成人| 探花视频在线版播放免费观看 | 精品一区二区三区在线播放 | 欧美性黄网官网 | 亚洲片在线 | 精品资源在线 | 国色天香在线观看 | 狠狠色丁香婷婷综合久久片 | 亚洲精品视频播放 | 日日夜夜亚洲 | 人人爽人人澡人人添人人人人 | 国产高清av免费在线观看 | 一区二区三区日韩在线观看 | 国产美女精彩久久 | 色干综合 | 激情丁香| 91chinesexxx |