sách gpt4 ăn đã đi

.net Chủ đề đặc biệt của EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu?

In lại Tác giả: qq735679552 Thời gian cập nhật: 27-09-2022 22:32:09 29 4
mua khóa gpt4 giày nike

CFSDN nhấn mạnh vào giá trị tạo ra nguồn mở và chúng tôi cam kết xây dựng nền tảng chia sẻ tài nguyên để mọi nhân viên CNTT có thể tìm thấy thế giới tuyệt vời của bạn tại đây.

Bài viết trên blog CFSDN này.net Chủ đề EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu? Được tác giả sưu tầm và biên soạn. Nếu các bạn quan tâm tới bài viết này thì nhớ like nhé.

Văn bản gốc: https://bit.ly/2umidlb Tác giả: jon p smith Người dịch: Wang Liang Tuyên bố từ chối trách nhiệm: Tôi không dịch các bài viết kỹ thuật từng câu mà diễn đạt dựa trên sự hiểu biết của riêng tôi. Một số câu tôi thực sự không biết cách tổ chức nhưng không ảnh hưởng đến sự hiểu biết có thể bị loại bỏ.

Bài viết này sẽ cung cấp cho bạn mô tả chi tiết về chế độ xem "hậu trường" của việc đọc dữ liệu lõi ef từ cơ sở dữ liệu. Tôi sẽ trình bày hai cách đọc cơ sở dữ liệu: truy vấn thông thường và truy vấn không theo dõi bằng phương pháp không theo dõi. Tôi cũng sẽ chạy thử nghiệm để chứng minh cách tôi giải quyết vấn đề về hiệu suất mà một trong những khách hàng của tôi đang gặp phải.

Tôi cho rằng bạn đã có một số kiến ​​thức về ef core, nhưng trước khi đi sâu vào, hãy xem cách sử dụng ef core để đảm bảo chúng ta có một số kiến ​​thức cơ bản. Đây là một chủ đề "đi sâu", vì vậy tôi sẽ đi sâu vào nhiều chi tiết kỹ thuật và tôi hy vọng tôi mô tả nó theo cách mà bạn có thể hiểu được.

Bài viết này là bài đầu tiên trong loạt bài “Tìm hiểu chuyên sâu về lõi ef”. Sau đây là danh sách các bài viết trong loạt bài này:

  • Điều gì xảy ra khi lõi ef đọc dữ liệu từ cơ sở dữ liệu? (Bài viết này)
  • Điều gì xảy ra khi lõi ef ghi dữ liệu vào cơ sở dữ liệu? (Hãy theo dõi)

Tổng quan .

  • EF Core có hai cách để đọc dữ liệu từ cơ sở dữ liệu (còn gọi là truy vấn): truy vấn LINQ thông thường và truy vấn LINQ không theo dõi bao gồm phương pháp asnotracking.
  • Lớp được trả về (được gọi là lớp thực thể) được truy vấn bởi hai phương thức này và các lớp thực thể khác mà nó được kết nối (được gọi là thuộc tính điều hướng) cũng được tải cùng lúc, nhưng hai phương thức được kết nối như thế nào và nội dung của kết nối là khác nhau.
  • Các truy vấn thông thường chấp nhận một bản sao của tất cả dữ liệu trong dbcontext khi quá trình đọc được thực hiện - lớp thực thể tại thời điểm này được cho là đã được theo dõi. Điều này cho phép các lớp thực thể được tải tham gia vào các hoạt động cập nhật cơ sở dữ liệu.
  • Các truy vấn thông thường cũng sẽ có một số triển khai cơ bản phức tạp khác, được gọi là sửa chữa mối quan hệ (sửa lỗi), được sử dụng để mô tả mối quan hệ kết nối giữa lớp thực thể đọc và các thực thể được theo dõi khác.
  • asnotracked Truy vấn không được theo dõi không có bản sao nên không được theo dõi - nghĩa là truy vấn này nhanh hơn truy vấn thông thường. Điều này cũng có nghĩa là nó sẽ không được sử dụng để ghi cơ sở dữ liệu.
  • Cuối cùng, tôi sẽ chỉ cho bạn một tính năng ít được biết đến của các truy vấn phổ biến của EF Core như một ví dụ về mức độ thông minh của việc kết nối mối quan hệ giữa các lớp thực thể thông qua các thuộc tính điều hướng.

Cách lõi ef đọc dữ liệu cơ sở dữ liệu.

Mẹo: Nếu bạn đã có hiểu biết nhất định về lõi ef, bạn có thể bỏ qua phần này. Phần này chỉ là một ví dụ về cách đọc cơ sở dữ liệu.

Để giúp bạn hiểu rõ hơn, trước tiên tôi sẽ mô tả cấu trúc cơ sở dữ liệu và sau đó đưa ra một ví dụ đọc cơ sở dữ liệu đơn giản. Dưới đây là một số cấu trúc bảng cơ bản và mối quan hệ giữa chúng.

.net Chủ đề đặc biệt của EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu?

Các bảng được ánh xạ tới các lớp có tên tương tự, chẳng hạn như sách, tác giả sách, tác giả, có tên thuộc tính giống với tên trường của bảng. Do không gian hạn chế, tôi sẽ không mở rộng các lớp này, nhưng bạn có thể xem các lớp này trong kho lưu trữ github của tôi [1].

lõi ef yêu cầu năm phần sau để đọc cơ sở dữ liệu:

  1. Máy chủ cơ sở dữ liệu, chẳng hạn như máy chủ sql, sqlite, postgresql, v.v.
  2. Một cơ sở dữ liệu với dữ liệu.
  3. Các lớp được ánh xạ tới các bảng dữ liệu (được gọi là các lớp thực thể).
  4. Một lớp kế thừa dbcontext và chứa cấu hình của lõi ef.
  5. Cuối cùng là lệnh đọc dữ liệu từ cơ sở dữ liệu.

Mã kiểm tra đơn vị bên dưới là từ kho lưu trữ github của tôi [2] và hiển thị một ví dụ đơn giản về việc đọc 4 thực thể sách và các thực thể tác giả và tác giả sách liên quan của chúng từ cơ sở dữ liệu hiện có.

Địa chỉ kho: https://bit.ly/2yza7qq.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[sự thật]
công cộng vô hiệu testbookcountauthorsok()
{
   //cài đặt
   var options = sqliteinmemory.createoptions();
   //mã để thiết lập cơ sở dữ liệu với bốn cuốn sách, hai cuốn có cùng tác giả
   sử dụng (trong đó bối cảnh = mới efcorecontext(tùy chọn))
   {
     //nỗ lực
     var books = ngữ cảnh.books
       .include(r => r.authorslink)
       .theninclude(r => r.tác giả)
       .tolist();
 
     //xác minh
     books.count.shouldequal(4);
     sách.selectmany(x => x.authorslink.select(y => y.author))
       .distinct().count().shouldequal(3);
   }
}

Bây giờ, nếu chúng ta ánh xạ mã kiểm thử đơn vị tới 5 phần trên thì kết quả sẽ như sau:

  1. máy chủ cơ sở dữ liệu--Dòng 5: Tôi đã chọn máy chủ cơ sở dữ liệu sqlite, trong trường hợp này sqliteinmemory.createoptions phương thức này tạo cơ sở dữ liệu trong bộ nhớ bằng cách sử dụng một trong các gói nuget của tôi, efcore.testsupport (cơ sở dữ liệu trong bộ nhớ rất hữu ích cho việc kiểm tra đơn vị vì bạn có thể thiết lập cơ sở dữ liệu trống mới để kiểm tra).
  2. cơ sở dữ liệu với dữ liệu---Dòng 6: Tôi sẽ giới thiệu cách ghi dữ liệu vào cơ sở dữ liệu trong bài viết tiếp theo. Bây giờ giả sử rằng có một cơ sở dữ liệu chứa thông tin về 4 cuốn sách, hai trong số đó được viết bởi cùng một người.
  3. Lớp thực thể- Mã không được hiển thị ở đây, nhưng bạn có thể xem các lớp ở đây [1]. Có một lớp thực thể sách, có liên quan nhiều-nhiều với lớp thực thể tác giả thông qua một lớp thực thể có tên là bookauhor.
  4. Một lớp kế thừa dbcontext--Dòng 7: Lớp efcorecontext kế thừa lớp dbcontext và định cấu hình mối quan hệ ánh xạ từ lớp đến cơ sở dữ liệu (bạn có thể xem lớp này trong kho github của tôi [3]).
  5. Lệnh đọc dữ liệu từ cơ sở dữ liệu---Dòng 10 đến 13, đây là một truy vấn:
  • Dòng 10 - bối cảnh là phiên bản của efcorecontext mà qua đó cơ sở dữ liệu của bạn được truy cập,.sách Cho biết rằng bạn muốn truy cập vào bảng sách.
  • Dòng 11 - include được gọi là tải tham lam và cho lõi ef biết rằng khi tải sách, nó cũng sẽ tải tất cả các lớp thực thể tác giả sách liên quan.
  • Dòng 12 - theninclude tiếp tục tải tham lam, nói với lõi ef rằng khi tải một tác giả sách, nó cũng phải tải lớp thực thể tác giả được liên kết với tác giả sách đó.

Tất cả truy vấn này dẫn đến một tập kết quả, chứa các thuộc tính thông thường, chẳng hạn như thuộc tính tiêu đề của sách và thuộc tính điều hướng của các lớp thực thể liên quan, chẳng hạn như thuộc tính liên kết tác giả của sách.

Ví dụ này được gọi là truy vấn hoặc đọc và là một trong bốn loại truy cập cơ sở dữ liệu, crud (thêm, đọc, cập nhật và xóa). Tôi sẽ đề cập đến những bổ sung và cập nhật mới trong bài viết tiếp theo của mình.

Cách lõi ef thể hiện dữ liệu đã đọc.

Khi bạn truy vấn cơ sở dữ liệu, lõi ef sẽ chuyển đổi dữ liệu được cơ sở dữ liệu trả về thành các lớp thực thể và điền các giá trị của thuộc tính điều hướng. Trong phần này, chúng ta sẽ xem xét hai loại bước truy vấn - truy vấn thông thường (tức là không có phương pháp không theo dõi, còn được gọi là truy vấn đọc-ghi) và truy vấn không theo dõi có thêm phương pháp không theo dõi (được gọi là truy vấn chỉ đọc).

Trước tiên chúng ta hãy xem câu lệnh linq ban đầu được chuyển đổi thành lệnh truy vấn tương ứng của cơ sở dữ liệu như thế nào và sau đó trả về dữ liệu. Đây là một thao tác rất phổ biến cho cả hai loại truy vấn mà chúng ta sẽ xem xét. Xem hình ảnh bên dưới để biết phần đầu tiên của truy vấn.

.net Chủ đề đặc biệt của EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu?

Có một số mã rất phức tạp để chuyển linq của bạn thành các lệnh truy vấn cơ sở dữ liệu, nhưng chúng ta không cần phải lo lắng về những chi tiết nội bộ này. Nếu linq của bạn không thể dịch được, bạn sẽ nhận được một thông báo ngoại lệ từ lõi ef chứa các từ mô tả như "không thể dịch được". Ngoài ra, các tính năng như trình chuyển đổi giá trị[4] có thể điều chỉnh dữ liệu khi dữ liệu được trả về.

Phần này hiển thị phần đầu tiên của truy vấn, trong đó linq được dịch thành lệnh cơ sở dữ liệu và tất cả các giá trị đúng sẽ được trả về. Bây giờ chúng ta hãy xem phần thứ hai của truy vấn, trong đó lõi ef lấy các giá trị trả về và chuyển đổi chúng thành các phiên bản của lớp thực thể và điền vào các thuộc tính điều hướng. Chúng ta sẽ xem xét cả hai loại truy vấn riêng biệt.

1. Truy vấn thông thường (truy vấn đọc-ghi).

Cách một truy vấn thông thường đọc dữ liệu, nó có thể sửa đổi dữ liệu và cập nhật nó vào cơ sở dữ liệu, đó là lý do tại sao tôi gọi nó là truy vấn đọc-ghi. Nó không tự động cập nhật dữ liệu (xem bài tiếp theo về cách ghi vào cơ sở dữ liệu). Nếu bạn muốn cập nhật dữ liệu, truy vấn của bạn phải là truy vấn đọc-ghi.

Ví dụ tôi đưa ra trong phần giới thiệu thực hiện một truy vấn đọc-ghi thông thường, đọc các ví dụ với phiên bản liên kết tác giả. Đây là mã cho phần truy vấn của ví dụ:

?
1
2
3
4
var books = ngữ cảnh.books
   .include(r => r.authorslink)
   .theninclude(r => r.tác giả)
   .tolist();

Sau đó, lõi ef sẽ chuyển đổi các giá trị này và điền vào lớp thực thể chứa các thuộc tính điều hướng theo ba bước. Hình ảnh bên dưới hiển thị ba bước này cùng với lớp thực thể kết quả và các thuộc tính điều hướng của nó.

.net Chủ đề đặc biệt của EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu?

Hãy phân tích ba bước sau:

  1. Tạo lớp và điền dữ liệu. Nó chấp nhận các giá trị được trả về từ cơ sở dữ liệu và điền vào các thuộc tính, trường không điều hướng (được gọi là vô hướng), v.v. Trong lớp thực thể sách, có các thuộc tính như bookid (khóa chính) và tiêu đề - xem hình chữ nhật màu xanh nhạt ở góc dưới bên trái của hình trên.
  2. Sửa chữa các mối quan hệ. Bước đầu tiên là điền thông tin cho khóa chính và khóa ngoài, xác định cách dữ liệu có liên quan với nhau. EF Core sau đó sử dụng các phím này để đặt thuộc tính điều hướng giữa các lớp thực thể (được hiển thị dưới dạng đường đậm màu xanh lam trong hình). Thông tin cần thiết để vá mối quan hệ này không chỉ để truy vấn các lớp thực thể mà nó đọc mà còn xem xét từng thực thể được theo dõi trong dbcontext và điền các thuộc tính điều hướng. Đây là một tính năng mạnh mẽ, nhưng bạn càng theo dõi nhiều thực thể thì càng mất nhiều thời gian - đó là lý do tại sao cần có tính năng không theo dõi để truy vấn nhanh hơn.
  3. Tạo ảnh chụp nhanh theo dõi. Ảnh chụp nhanh theo dõi là bản sao của lớp thực thể được trả về cho người dùng, cộng với liên kết ẩn của nó với từng lớp thực thể - nếu một thực thể được theo dõi, điều này có nghĩa là nó sẽ được sửa đổi và ghi vào cơ sở dữ liệu.

2. Truy vấn không theo dõi (truy vấn chỉ đọc).

Truy vấn không theo dõi, tức là truy vấn sử dụng phương pháp không theo dõi, là truy vấn chỉ đọc. Điều này có nghĩa là khi phương thức savechanges được gọi, không có gì bạn đọc sẽ được ghi vào cơ sở dữ liệu. Các truy vấn không theo dõi hiệu quả hơn Trong phần tiếp theo, tôi sẽ giới thiệu các truy vấn không theo dõi và những điểm khác biệt so với các truy vấn thông thường.

Theo ví dụ trước, tôi đã sửa đổi mã truy vấn và thêm phương thức không theo dõi sau (xem dòng 2):

?
1
2
3
4
5
var books = ngữ cảnh.books
   .asnotracking()
   .include(r => r.authorslink)
   .theninclude(r => r.tác giả)
   .tolist();

Truy vấn linq ở đây chỉ có hai bước đầu tiên của truy vấn thông thường ở trên (không có bước thứ ba). Hình dưới đây thể hiện các bước của truy vấn không theo dõi.

.net Chủ đề đặc biệt của EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu?

Các bước thực hiện như sau:

  1. Tạo lớp và điền dữ liệu vào đó. Nó chấp nhận các giá trị được trả về từ cơ sở dữ liệu và điền vào các thuộc tính, trường không điều hướng (được gọi là vô hướng), v.v. Trong lớp thực thể sách, có các thuộc tính như bookid (khóa chính) và tiêu đề - xem hình chữ nhật màu xanh nhạt ở góc dưới bên trái của hình trên.
  2. Sửa chữa các mối quan hệ. Bước đầu tiên là điền thông tin cho khóa chính và khóa ngoài, xác định cách dữ liệu có liên quan với nhau. EF Core sau đó sử dụng các phím này để đặt thuộc tính điều hướng giữa các lớp thực thể (được hiển thị dưới dạng đường đậm màu xanh lam trong hình). Thông tin cần thiết để vá mối quan hệ này không chỉ để truy vấn các lớp thực thể mà nó đọc mà còn xem xét từng thực thể được theo dõi trong dbcontext và điền các thuộc tính điều hướng. Đây là một tính năng mạnh mẽ, nhưng bạn càng theo dõi nhiều thực thể thì càng mất nhiều thời gian - đó là lý do tại sao cần có tính năng không theo dõi để truy vấn nhanh hơn.

Sự khác biệt giữa truy vấn thông thường và truy vấn không theo dõi.

Bây giờ hãy so sánh sự khác biệt rõ ràng giữa hai truy vấn này.

  1. Hiệu suất truy vấn tốt hơn đối với các truy vấn không theo dõi. Lý do chính để sử dụng truy vấn không theo dõi là hiệu suất. Hiệu suất truy vấn không theo dõi là:
  • Nhanh hơn một chút và sử dụng ít bộ nhớ hơn một chút vì nó không yêu cầu tạo ảnh chụp nhanh theo dõi.
  • Việc tránh các ảnh chụp nhanh theo dõi không cần thiết sẽ cải thiện hiệu suất của các thay đổi lưu vì nó không phải kiểm tra các ảnh chụp nhanh theo dõi để biết các thay đổi.
  • Nhanh hơn một chút vì không có cái gọi là giải pháp nhận dạng khi vá các mối quan hệ. Đó là lý do tại sao bạn nhận được hai phiên bản tác giả có cùng dữ liệu.
  1. Truy vấn không theo dõi chỉ liên kết các thực thể trong truy vấn khi vá các mối quan hệ. Trong các truy vấn thông thường, tôi đã nói rằng việc vá các mối quan hệ sẽ kết nối các thực thể trong truy vấn và các thực thể hiện đang được theo dõi, nhưng các truy vấn không theo dõi chỉ vá các mối quan hệ giữa các thực thể trong truy vấn.
  2. Các truy vấn không theo dõi không phải lúc nào cũng thể hiện mối quan hệ cơ sở dữ liệu. Một điểm khác biệt trong việc vá mối quan hệ giữa hai loại truy vấn này là việc vá mối quan hệ sẽ nhanh hơn đối với các truy vấn không theo dõi và không yêu cầu phân giải danh tính. Điều này có thể tạo ra nhiều phiên bản của cùng một hàng trong cơ sở dữ liệu - xem thực thể tác giả màu xanh lam và nhận xét ở góc dưới bên phải của hình ảnh trên. Sự khác biệt này không thành vấn đề nếu bạn chỉ hiển thị dữ liệu cho người dùng nhưng có thể có vấn đề nếu bạn có logic nghiệp vụ trong đó nhiều phiên bản không phản ánh chính xác cấu trúc của dữ liệu.

Các tính năng sửa chữa mối quan hệ hữu ích cho dữ liệu phân cấp.

Bước sửa chữa mối quan hệ rất thông minh, đặc biệt là trong các truy vấn thông thường. Dưới đây tôi muốn cho bạn thấy cách tôi sử dụng tính năng vá lỗi mối quan hệ để giải quyết vấn đề về hiệu suất trong dự án khách hàng.

Tôi đã làm việc cho một công ty nơi phần lớn quá trình xử lý dữ liệu được cấu trúc theo thứ bậc, nơi dữ liệu có một loạt các mối quan hệ có độ sâu không chắc chắn. Vấn đề là tôi phải phân tích toàn bộ hệ thống phân cấp trước khi có thể hiển thị dữ liệu này. Ban đầu, tôi đạt được điều này bằng cách tải hai cấp độ đầu tiên một cách tham lam và sau đó tải rõ ràng các cấp độ sâu hơn. Nó hoạt động nhưng hiệu suất rất chậm và cơ sở dữ liệu bị quá tải với nhiều lần truy cập cơ sở dữ liệu đơn lẻ.

Điều này khiến tôi phải suy nghĩ về giải pháp. Nếu việc sửa chữa mối quan hệ của các truy vấn thông thường quá thông minh, liệu nó có thể giúp tôi cải thiện hiệu suất của các truy vấn không? Nó có thể! Hãy để tôi cho bạn một ví dụ về một nhân viên công ty. Hình ảnh bên dưới hiển thị thứ bậc của các công ty mà chúng tôi muốn tải.

.net Chủ đề đặc biệt của EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu?

Bạn có thể sử dụng .include(x => x.worksforme).theninclude(x => x.worksforme)... v.v. để tải thông tin cấp độ được yêu cầu, nhưng kết quả là .include(x => x.worksforme ) là đủ. Bởi vì bản vá mối quan hệ của ef core sẽ thực hiện phần còn lại cho bạn, điều này thật đáng ngạc nhiên nhưng cũng rất hữu ích.

Ví dụ: nếu tôi muốn truy vấn tất cả nhân viên về phát triển vai trò (mỗi nhân viên có một thuộc tính tên là whattheydo và một thuộc tính tên là vai trò chứa bộ phận họ làm việc), tôi có thể viết mã như sau:

?
1
2
3
4
var devdept = ngữ cảnh.nhân viên
   .include(x => x.worksfromme)
   .nơi(x => x.whattheydo.hasflag(vai trò.phát triển))
   .tolist();

 Điều này sẽ tạo một truy vấn tải tất cả nhân viên có vai trò phát triển và vá mối quan hệ với thuộc tính điều hướng worksfome (bộ sưu tập) và thuộc tính điều hướng người quản lý (đơn) trên lớp thực thể nhân viên. Bằng cách chỉ thực hiện một truy vấn, nó vừa cải thiện thời gian thực hiện vừa giảm tải cho máy chủ cơ sở dữ liệu.

Tóm tắt.

Bạn đã thấy hai loại truy vấn mà tôi gọi là a) truy vấn đọc-ghi thông thường và b) truy vấn chỉ đọc không theo dõi. Đối với mỗi loại truy vấn, tôi sẽ chỉ cho bạn cách EF Core "hậu trường" đọc dữ liệu và hiển thị nó. Sự khác biệt trong cách họ làm việc cũng cho thấy điểm mạnh và điểm yếu của họ.

Truy vấn không theo dõi là giải pháp cho truy vấn chỉ đọc vì chúng nhanh hơn truy vấn đọc-ghi thông thường. Nhưng bạn nên nhớ cơ chế vá mối quan hệ, cơ chế này có thể tạo ra nhiều phiên bản của một lớp khi cơ sở dữ liệu chỉ có một mối quan hệ.

Truy vấn đọc-ghi thông thường là giải pháp để truy vấn các thực thể được theo dõi, nghĩa là bạn có thể sử dụng chúng khi tạo, cập nhật và xóa dữ liệu. Các truy vấn đọc và ghi thông thường chiếm nhiều thời gian và tài nguyên bộ nhớ hơn nhưng có một số tính năng hữu ích, chẳng hạn như liên kết tự động với các phiên bản lớp thực thể được theo dõi khác.

Tôi hy vọng bài viết này hữu ích cho bạn. Chúc bạn lập trình vui vẻ! .

[1]. https://bit.ly/2mxk3zy [2]. https://bit.ly/2yza7qq [3]. https://bit.ly/2y0uoro [4]. https://bit.ly/2yeyg8j 。

Liên kết gốc: https://www.cnblogs.com/willick/p/13150393.html.

Cuối cùng, bài viết này nói về chủ đề .net EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu? Bài viết này chỉ vậy thôi, nếu bạn muốn biết thêm về chủ đề .net EF Core: Điều gì xảy ra khi EF Core đọc dữ liệu? Về nội dung, vui lòng tìm kiếm các bài viết của CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .

29 4 0
qq735679552
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress