Có gì mới trong EF Core 5

EF Core 5.0 hiện đã được phát triển và đây là danh sách tất cả những thay đổi thú vị được giới thiệu trong các bản xem trước cho đến nay.

Các tính năng mới trong phiên bản Review 1 của EF 5

Simple logging

Tính năng nhật ký đơn giản (simple logging) bổ sung thêm chức năng tương tự như Database.Log trong EF6. Nó cung cấp một cách đơn giản để lấy nhật ký từ EF Core mà không cần phải cấu hình bất kỳ thư viện ghi nhật ký bên ngoài nào.

Lấy câu lệnh SQL đã tạo

EF Core 5.0 giới thiệu phương thức mở rộng ToQueryString, phương thức này sẽ trả về câu lệnh SQL mà EF Core sẽ tạo ra khi thực hiện truy vấn LINQ.

Sử dụng attribute để chỉ định một thực thể không có khóa

Một kiểu thực thể hiện có thể được cấu hình là không có khóa bằng cách sử dụng attribute KeylessAttribute mới.

[Keyless]
public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public int Zip { get; set; }
}

Kết nối hoặc chuỗi kết nối có thể được thay đổi trên DbContext đã khởi tạo

Giờ đây, việc tạo một thể hiện của DbContext mà không cần bất kỳ kết nối hoặc chuỗi kết nối nào trở nên dễ dàng hơn.

Kết nối hoặc chuỗi kết nối có thể bị thay đổi trên thể hiện của DbContext.

Tính năng này cho phép cùng một thể hiện của DbContext kết nối động với các cơ sở dữ liệu khác nhau.

Proxy theo dõi thay đổi

EF Core hiện có thể tạo proxy runtime để triển khai tự động INotifyPropertyChangingINotifyPropertyChanged.

Sau đó, nó sẽ báo cáo các thay đổi giá trị trên các thuộc tính thực thể trực tiếp tới EF Core, tránh việc phải quét các thay đổi.

Tuy nhiên, proxy có những hạn chế riêng, vì vậy chúng không dành cho tất cả mọi người.

Cải tiến debug view

Debug view là một cách dễ dàng để xem xét nội bộ của EF Core khi gỡ lỗi các vấn đề. Debug view cho Model đã được triển khai cách đây một thời gian. EF Core 5.0 đã làm cho mô hình dễ đọc hơn và thêm debug view mới cho các thực thể được theo dõi trong trình quản lý trạng thái.

Cải thiện khả năng xử lý null của cơ sở dữ liệu

Cơ sở dữ liệu quan hệ thường coi NULL là một giá trị không xác định và do đó không bằng bất kỳ NULL nào khác.

Trong khi C# coi null là một giá trị được xác định, giá trị này được so sánh ngang bằng với bất kỳ giá trị null nào khác.

EF Core theo mặc định dịch các truy vấn để chúng sử dụng ngữ nghĩa null của C#. EF Core 5.0 cải thiện đáng kể hiệu quả của các bản dịch này.

Thuộc tính của Indexer

EF Core 5.0 hỗ trợ ánh xạ các thuộc tính của Indexer C#. Các thuộc tính này cho phép các thực thể hoạt động như các túi thuộc tính nơi các cột được ánh xạ tới các thuộc tính được đặt tên trong túi.

Tạo các ràng buộc kiểm tra cho ánh xạ enum

Chuyển đổi trong EF Core 5.0 hiện có thể tạo ra các ràng buộc CHECK đối với ánh xạ thuộc tính enum.

MyEnumColumn VARCHAR(10) NOT NULL CHECK (MyEnumColumn IN ('Useful', 'Useless', 'Unknown'))

IsRelational

Một mới phương thức IsRelational đã được thêm ngoài các phương thức hiện có như: IsSqlServer, IsSqliteIsInMemory. Phương thức này có thể được sử dụng để kiểm tra xem DbContext có đang sử dụng bất kỳ nhà cung cấp cơ sở dữ liệu quan hệ nào hay không.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    if (Database.IsRelational())
    {
        // Do relational-specific model configuration.
    }
}

Tối ưu Cosmos concurrency với ETags

Trình cung cấp cơ sở dữ liệu Azure Cosmos DB hiện hỗ trợ tối ưu concurrency sử dụng ETags. Sử dụng trình tạo mô hình trong OnModelCreating để cấu hình ETag.

builder.Entity<Customer>().Property(c => c.ETag).IsEtagConcurrency();

Phương thức SaveChanges sẽ tạo ra ngoại lệ DbUpdateConcurrencyException khi có xung đột đồng thời, có thể được xử lý để thực hiện thử lại, v.v.

Tạo truy vấn cho cấu trúc DateTime

Các truy vấn chứa cấu trúc DateTime mới hiện đã được dịch sang SQL. Ngoài ra, các chức năng SQL Server sau hiện đã được ánh xạ:

  • DateDiffWeek
  • DateFromParts

Ví dụ:

var count = context.Orders.Count(c => date > EF.Functions.DateFromParts(DateTime.Now.Year, 12, 25));

Tạo truy vấn cho cấu trúc mảng byte

Truy vấn sử dụng Contains, Length, SequenceEqual, vv trên thuộc tính byte[] hiện đã được dịch sang SQL.

Tạo truy vấn cho Reverse

Các truy vấn sử dụng Reverse hiện đã được dịch sang SQL.

context.Employees.OrderBy(e => e.EmployeeID).Reverse()

Tạo truy vấn cho các toán tử bitwise

Các truy vấn sử dụng toán tử bitwise hiện được dịch trong nhiều trường hợp hơn.

context.Orders.Where(o => ~o.OrderID == negatedId)

Tạo truy vấn cho các chuỗi trên Cosmos

Truy vấn sử dụng các phương thức trên chuỗi như Contains, StartsWithEndsWith hiện đã được dịch khi sử dụng trình cung cấp Azure Cosmos DB.

Các tính năng mới trong phiên bản Review 2 của EF 5

Sử dụng attribute để chỉ định trường hỗ trợ thuộc tính

Attribute BackingFieldAttribute có thể được sử dụng để chỉ định trường hỗ trợ cho một thuộc tính. Thuộc tính này cho phép EF Core vẫn ghi và đọc từ trường hỗ trợ như thường lệ, ngay cả khi không thể tự động tìm thấy trường hỗ trợ.

public class Blog
{
    private string _mainTitle;

    public int Id { get; set; }

    [BackingField(nameof(_mainTitle))]
    public string Title
    {
        get => _mainTitle;
        set => _mainTitle = value;
    }
}

Ánh xạ phân biệt đầy đủ

EF Core sử dụng cột phân biệt để ánh xạ Type Per Hierarchy (TPH) của hệ thống phân cấp kế thừa.

  • Có một số cải tiến hiệu suất miễn là EF Core biết tất cả các giá trị có thể có cho bộ phân biệt.
  • EF Core 5.0 bây giờ đã triển khai những cải tiến này.

Ví dụ: các phiên bản trước của EF Core sẽ luôn tạo SQL này cho một truy vấn trả về tất cả các kiểu trong một hệ thống phân cấp.

SELECT [a].[Id], [a].[Discriminator], [a].[Name]
FROM [Animal] AS [a]
WHERE [a].[Discriminator] IN (N'Animal', N'Cat', N'Dog', N'Human')

EF Core 5.0 bây giờ sẽ tạo ra thông tin sau khi một ánh xạ phân biệt hoàn chỉnh được cấu hình:

SELECT [a].[Id], [a].[Discriminator], [a].[Name]
FROM [Animal] AS [a]

Nó sẽ là mặc định bắt đầu từ phiên bản preview 3.

Cải tiến hiệu suất trong Microsoft.Data.Sqlite

Hai cải tiến hiệu suất sau được thực hiện cho SQLite:

  • Truy xuất dữ liệu chuỗi và nhị phân với GetBytes, GetCharsGetTextReader hiện hiệu quả hơn bằng cách sử dụng SqliteBlobstreams.
  • Việc khởi tạo SqliteConnection bây giờ là lazy.

Những cải tiến này nằm trong trình cung cấp ADO.NET Microsoft.Data.Sqlite và do đó cũng cải thiện hiệu suất bên ngoài EF Core.

Các tính năng mới trong phiên bản Preview 3 của EF 5

Phương thức Include đã hỗ trợ bộ lọc

Phương thức Include bây giờ đã hỗ trợ lọc của các thực thể được thêm vào.

var blogs = context.Blogs
    .Include(e => e.Posts.Where(p => p.Title.Contains("Cheese")))
    .ToList();

Truy vấn này sẽ trả về các blog cùng với các bài đăng được liên kết, nhưng chỉ khi tiêu đề bài đăng có chứa "Cheese".

Phương thức SkipTake cũng có thể được sử dụng để giảm số lượng các thực thể được thêm vào.

var blogs = context.Blogs
    .Include(e => e.Posts.OrderByDescending(post => post.Title).Take(5)))
    .ToList();

Truy vấn này sẽ trả về các blog và tối đa năm bài đăng trên mỗi blog.

ModelBuilder API mới cho các thuộc tính điều hướng

Thuộc tính điều hướng chủ yếu được cấu hình khi xác định mối quan hệ. Tuy nhiên, phương thức Navigation mới có thể được sử dụng trong trường hợp các thuộc tính điều hướng cần một cấu hình bổ sung. Ví dụ, để đặt trường hỗ trợ cho điều hướng khi trường sẽ không được tìm thấy theo quy ước.

modelBuilder.Entity<Blog>().Navigation(e => e.Posts).HasField("_myposts");
Lưu ý rằng API Navigation không thay thế cấu hình mối quan hệ. Thay vào đó, nó cho phép cấu hình bổ sung các thuộc tính điều hướng trong các mối quan hệ đã được phát hiện hoặc xác định.

Tham số dòng lệnh mới cho namespace và chuỗi kết nối

Chuyển đổi (migration) và scaffolding giờ đây cho phép namespace được chỉ định trên dòng lệnh. Ví dụ, để thiết kế một cơ sở dữ liệu từ các lớp ngữ cảnh và mô hình được đặt trong các namespace khác nhau.

dotnet ef dbcontext scaffold "connection string" Microsoft.EntityFrameworkCore.SqlServer --context-namespace "My.Context" --namespace "My.Model"

Ngoài ra, một chuỗi kết nối bây giờ có thể được truyền đến lệnh database-update.

dotnet ef database update --connection "connection string"

Các tham số tương đương cũng đã được thêm vào các lệnh PowerShell được sử dụng trong Bảng điều khiển trình quản lý gói VS (VS Package Manager Console).

EnableDetailedErrors đã trở lại

Vì lý do hiệu suất, EF không thực hiện kiểm tra null bổ sung khi đọc các giá trị từ cơ sở dữ liệu. Điều này có thể dẫn đến các trường hợp ngoại lệ khó tìm ra nguyên nhân khi gặp phải giá trị null không mong muốn.

Việc sử dụng EnableDetailedErrors sẽ thêm kiểm tra null bổ sung cho các truy vấn, do đó, đối với chi phí hiệu suất nhỏ, những lỗi này dễ dàng truy tìm nguyên nhân gốc rễ hơn.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .EnableDetailedErrors()
        .EnableSensitiveDataLogging() // Often also useful with EnableDetailedErrors 
        .UseSqlServer(Your.SqlServerConnectionString);

Khóa phân vùng Cosmos

Khóa phân vùng để sử dụng cho một truy vấn nhất định hiện có thể được chỉ định trong truy vấn.

await context.Set<Customer>()
             .WithPartitionKey(myPartitionKey)
             .FirstAsync();

Hỗ trợ cho hàm DATALENGTH của SQL Server

Điều này có thể được truy cập bằng cách sử dụng phương thức EF.Functions.DataLength mới.

var count = context.Orders.Count(c => 100 < EF.Functions.DataLength(c.OrderDate));

Các tính năng mới trong phiên bản Preview 4 của EF 5

Cấu hình độ chính xác

Độ chính xác cho một thuộc tính hiện có thể được chỉ định bằng cách sử dụng trình tạo mô hình.

modelBuilder
    .Entity<Blog>()
    .Property(b => b.Numeric)
    .HasPrecision(16, 4);

Độ chính xác vẫn có thể được thiết lập thông qua kiểu cơ sở dữ liệu đầy đủ, chẳng hạn như "decimal(16,4)".

Chỉ định hệ số lấp đầy index của SQL Server

Hệ số lấp đầy hiện tại có thể được chỉ định khi tạo index trên SQL Server. Ví dụ.

modelBuilder
    .Entity<Customer>()
    .HasIndex(e => e.Name)
    .HasFillFactor(90);

Các tính năng mới trong phiên bản Preview 5 của EF 5

Đối chiếu cơ sở dữ liệu

Đối chiếu mặc định cho cơ sở dữ liệu hiện có thể được chỉ định trong mô hình EF. Nó sẽ xuyên suốt các chuyển đổi (migration) được tạo để thiết lập đối chiếu khi cơ sở dữ liệu được tạo.

modelBuilder.UseCollation("German_PhoneBook_CI_AS");

Khi bạn tạo chuyển đổi thì nó sẽ tạo ra phần sau để tạo cơ sở dữ liệu trên SQL Server.

CREATE DATABASE [Test]
COLLATE German_PhoneBook_CI_AS;

Bạn cũng có thể chỉ định đối chiếu để sử dụng cho các cột cơ sở dữ liệu cụ thể.

modelBuilder
    .Entity<User>()
    .Property(e => e.Name)
    .UseCollation("German_PhoneBook_CI_AS");

Đối với những người không sử dụng chuyển đổi, các đối chiếu bây giờ được thiết kế ngược từ cơ sở dữ liệu khi scaffolding một DbContext.

Cuối cùng, EF.Functions.Collate() cho phép các truy vấn đặc biệt bằng cách sử dụng các đối chiếu khác nhau.

context.Users.Single(e => EF.Functions.Collate(e.Name, "French_CI_AS") == "Jean-Michel Jarre");

Điều này sẽ tạo ra truy vấn sau cho SQL Server:

SELECT TOP(2) [u].[Id], [u].[Name]
FROM [Users] AS [u]
WHERE [u].[Name] COLLATE French_CI_AS = N'Jean-Michel Jarre'

Các đối chiếu đặc biệt nên được sử dụng cẩn thận vì chúng có thể tác động tiêu cực đến hiệu suất cơ sở dữ liệu.

Chuyển đối số vào IDesignTimeDbContextFactory

Các đối số bây giờ có thể được chuyển từ dòng lệnh vào phương thức CreateDbContext của IDesignTimeDbContextFactory. Ví dụ, để chỉ định đây là một bản build dành cho nhà phát triển, một đối số tùy chỉnh (ví dụ dev) có thể được truyền vào dòng lệnh như sau:

dotnet ef migrations add two --verbose --dev

Đối số này sau đó sẽ được chuyển vào factory, nơi nó có thể được sử dụng để kiểm soát cách tạo và khởi tạo context.

public class MyDbContextFactory : IDesignTimeDbContextFactory<SomeDbContext>
{
    public SomeDbContext CreateDbContext(string[] args)
        => new SomeDbContext(args.Contains("--dev"));
}

Các truy vấn không theo dõi

Các truy vấn không theo dõi hiện tại có thể được cấu hình để thực hiện giải quyết định danh. Ví dụ: truy vấn sau sẽ tạo một thể hiện Blog mới cho mỗi Post, ngay cả khi các Blog có cùng một khóa chính.

context.Posts.AsNoTracking().Include(e => e.Blog).ToList();

Tuy nhiên, nó thường chậm hơn một chút và luôn sử dụng nhiều bộ nhớ hơn. Truy vấn này có thể được thay đổi để đảm bảo chỉ tạo một thể hiện Blog duy nhất được tạo.

context.Posts.AsNoTracking().PerformIdentityResolution().Include(e => e.Blog).ToList();

Nó chỉ hữu ích cho các truy vấn không theo dõi (no tracking) vì tất cả các truy vấn theo dõi đã có sẵn hành vi này. Ngoài ra, sau khi xem xét API, cú pháp PerformIdentityResolution sẽ được thay đổi.

Các cột tính toán được lưu trữ

Hầu hết các cơ sở dữ liệu cho phép các giá trị cột tính toán được lưu trữ sau khi tính toán.

  • Cột được tính toán chỉ được tính một lần trên bản cập nhật, thay vì mỗi lần giá trị của nó được truy xuất, nó sẽ chiếm dung lượng đĩa.
  • Điều này cũng cho phép cột được lập chỉ mục cho một số cơ sở dữ liệu.

EF Core 5.0 cho phép các cột được tính toán được cấu hình như được lưu trữ.

modelBuilder
    .Entity<User>()
    .Property(e => e.SomethingComputed)
    .HasComputedColumnSql("my sql", stored: true);
EF Core hiện đã hỗ trợ các cột được tính toán trong cơ sở dữ liệu SQLite.
Entity Framework Core
Bài Viết Liên Quan:
Cấu hình trong Entity Framework Core
Trung Nguyen 03/04/2021
Cấu hình trong Entity Framework Core

Trong hướng dẫn này, bạn sẽ tìm hiểu cách cấu hình sử dụng attribute, Fluent API để ghi đè các quy ước mặc đình trong Entity Framework Core.

Các quy ước trong Entity Framework Core
Trung Nguyen 03/04/2021
Các quy ước trong Entity Framework Core

Bạn sẽ tìm hiểu các quy ước được tính hợp sẵn trong Entity Framework Core để tạo khóa chính, khóa ngoại, bảng, lược đồ, cột, kiểu dữ liệu, index ...

Quản lý mối quan hệ Một - Nhiều trong Entity Framework Core
Trung Nguyen 03/04/2021
Quản lý mối quan hệ Một - Nhiều trong Entity Framework Core

Trong hướng dẫn này, bạn sẽ tìm hiểu cách tạo, sửa đổi và xóa mối quan hệ một - nhiều trong Entity Framework Core.

Giới thiệu về các mối quan hệ trong Entity Framework Core
Trung Nguyen 03/04/2021
Giới thiệu về các mối quan hệ trong Entity Framework Core

Trong hướng dẫn này, bạn sẽ tìm hiều về các mối quan hệ một - nhiều, nhiều - nhiều và một - một trong Entity Framework Core.