7

EF Core có một "mã đầu tiên tâm lý" theo mặc định, tức là nó được cho là được sử dụng một cách mã đầu tiên, và mặc dù phương pháp tiếp cận cơ sở dữ liệu đầu tiên được hỗ trợ, nó được mô tả như không có gì hơn đảo ngược kỹ thuật hiện có cơ sở dữ liệu và tạo mã đại diện đầu tiên của nó. Ý tôi là, mô hình (các lớp POCO) được tạo ra trong mã "bằng tay" (mã đầu tiên), và được tạo ra từ cơ sở dữ liệu (theo lệnh Scaffold-DbContext), nên giống hệt nhau.Một cách thích hợp để viết các lớp POCO thực thể trong Entity Framework Core là gì?

Đáng ngạc nhiên, tài liệu chính thức của EF Core chứng minh sự khác biệt đáng kể. Dưới đây là một ví dụ của việc tạo ra các mô hình trong mã: https://ef.readthedocs.io/en/latest/platforms/aspnetcore/new-db.html Và đây là ví dụ về ngược-kỹ thuật từ cơ sở dữ liệu hiện có: https://ef.readthedocs.io/en/latest/platforms/aspnetcore/existing-db.html

Đây là lớp thực thể trong trường hợp đầu tiên:

public class Blog 
{ 
    public int BlogId { get; set; } 
    public string Url { get; set; } 

    public List<Post> Posts { get; set; } 
} 

public class Post 
{ 
    public int PostId { get; set; } 
    public string Title { get; set; } 
    public string Content { get; set; } 

    public int BlogId { get; set; } 
    public Blog Blog { get; set; } 
} 

và đây là lớp thực thể trong trường hợp thứ hai:

public partial class Blog 
{ 
    public Blog() 
    { 
     Post = new HashSet<Post>(); 
    } 

    public int BlogId { get; set; } 
    public string Url { get; set; } 

    public virtual ICollection<Post> Post { get; set; } 
} 

Ví dụ đầu tiên là một lớp POCO rất đơn giản, khá rõ ràng. Nó được hiển thị ở mọi nơi trong tài liệu (trừ các ví dụ được tạo ra từ cơ sở dữ liệu). Ví dụ thứ hai, mặc dù có một số bổ sung:

  • lớp được khai báo phần (mặc dù không có chỗ để được nhìn thấy một nét phần của nó).
  • Thuộc tính điều hướng có loại ICollection < T>, thay vì chỉ Danh sách < T>.
  • Thuộc tính điều hướng được khởi tạo thành mới HashSet < T>() trong hàm tạo. Không có khởi tạo như vậy trong ví dụ đầu tiên mã.
  • Thuộc tính điều hướng được khai báo virtual.
  • Thành viên DbSet trong lớp ngữ cảnh được tạo cũng là virtual.

Tôi đã cố gắng xây dựng mô hình từ cơ sở dữ liệu (công cụ mới nhất như bài viết này) và nó tạo ra các thực thể chính xác như được hiển thị, vì vậy đây không phải là vấn đề tài liệu lỗi thời. Vì vậy, các công cụ chính thức tạo ra mã khác nhau, và tài liệu chính thức cho thấy viết mã khác nhau (tầm thường) - mà không có một phần lớp, thành viên ảo, khởi tạo xây dựng, v.v.

Câu hỏi của tôi là cố gắng xây dựng mô hình trong mã Tôi viết mã của tôi? Tôi thích sử dụng ICollection thay vì Danh sách bởi vì nó là chung chung hơn, nhưng khác hơn thế, tôi không chắc liệu tôi cần phải làm theo tài liệu, hoặc các công cụ MS? Tôi có cần khai báo chúng là ảo không? Tôi có cần phải khởi tạo chúng trong một nhà xây dựng? vv ...

Tôi biết từ thời đại EF cũ rằng thuộc tính điều hướng ảo cho phép tải chậm, nhưng nó thậm chí không được hỗ trợ (chưa) trong EF Core và tôi không biết bất kỳ mục đích nào khác. Có thể nó ảnh hưởng đến hiệu suất? Có lẽ các công cụ cố gắng tạo ra mã chứng minh trong tương lai, để khi việc tải xuống lười biếng sẽ được thực hiện, các lớp và bối cảnh POCO sẽ có thể hỗ trợ nó? Nếu vậy, tôi có thể mương chúng khi tôi không cần tải chậm (tất cả các truy vấn dữ liệu được đóng gói trong một repo)?

Một thời gian ngắn, hãy giúp tôi hiểu lý do tại sao sự khác biệt và tôi nên sử dụng kiểu nào khi tạo mô hình trong mã?

+1

Về điểm 3, dựa trên kinh nghiệm của riêng tôi từ một dự án gần đây ... Tôi khuyên bạn không nên khởi tạo chúng thành bộ sưu tập trống trong trình tạo. Lý do cho điều này là logic nghiệp vụ của bạn, trong nhiều trường hợp, cần phải có khả năng xác định xem bộ sưu tập chi tiết có trống hay chưa được tải chưa. –

Trả lời

11

tôi cố gắng đưa ra một câu trả lời ngắn để mỗi điểm mà bạn đề cập

  • partial lớp học đặc biệt hữu ích đối với mã công cụ tạo ra. Giả sử bạn muốn triển khai thuộc tính có nguồn gốc từ mô hình. Đối với mã đầu tiên, bạn sẽ chỉ làm điều đó, bất cứ nơi nào bạn muốn. Đối với cơ sở dữ liệu đầu tiên, tệp lớp sẽ được viết lại nếu bạn cập nhật mô hình của mình. Vì vậy, nếu bạn muốn giữ mã mở rộng của mình, bạn muốn đặt nó trong một tệp khác ngoài mô hình được quản lý - đây là nơi mà partial giúp bạn mở rộng lớp mà không cần chỉnh sửa mã được tạo tự động bằng tay.

  • ICollection chắc chắn là lựa chọn phù hợp, ngay cả đối với mã đầu tiên. Cơ sở dữ liệu của bạn có thể sẽ không hỗ trợ một thứ tự đã định nghĩa mà không có một câu lệnh sắp xếp.

  • Khởi tạo xây dựng là một sự tiện lợi ít nhất ... giả sử bạn có bộ sưu tập cơ sở dữ liệu trống hoặc bạn không tải thuộc tính nào cả. Nếu không có hàm tạo, bạn phải xử lý các trường hợp null một cách rõ ràng tại các điểm tùy ý trong mã. Cho dù bạn nên đi với List hoặc HashSet là điều tôi không thể trả lời ngay bây giờ.

  • virtual cho phép tạo proxy cho các thực thể cơ sở dữ liệu, có thể trợ giúp với hai điều: Tải trọng lười như bạn đã đề cập và thay đổi theo dõi. Một đối tượng proxy có thể theo dõi các thay đổi đối với các thuộc tính ảo ngay lập tức với setter, trong khi các đối tượng bình thường trong ngữ cảnh cần được kiểm tra trên SaveChanges. Trong một số trường hợp, điều này có thể hiệu quả hơn (nói chung).

  • virtual IDbSet mục nhập ngữ cảnh cho phép thiết kế dễ dàng hơn các ngữ cảnh thử nghiệm mô phỏng cho các bài kiểm tra đơn vị. Các trường hợp sử dụng khác cũng có thể tồn tại.

+1

Lưu ý, EF Core không có proxy lười (hoặc thay đổi theo dõi). Tôi thành thật không chắc tại sao RevEng lại tạo ra các đạo cụ ảo. – bricelam

+0

Tôi đã gửi vấn đề [# 6326] (https://github.com/aspnet/EntityFramework/issues/6326) để thảo luận việc sử dụng 'virtual' với nhóm. – bricelam

+0

Hầu hết các bộ sưu tập bao gồm các giá trị duy nhất. Ví dụ: bạn sẽ không có hai mục giống nhau trong bộ sưu tập 'Danh sách '. Do đó, HashSet thường là sự lựa chọn đúng ngữ nghĩa để biểu diễn điều này. –

Các vấn đề liên quan