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.
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.
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.
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; }
}
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.
EF Core hiện có thể tạo proxy runtime để triển khai tự động INotifyPropertyChanging
và INotifyPropertyChanged
.
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.
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ơ 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.
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.
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'))
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
, IsSqlite
và IsInMemory
. 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.
}
}
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.
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ạ:
Ví dụ:
var count = context.Orders.Count(c => date > EF.Functions.DateFromParts(DateTime.Now.Year, 12, 25));
Truy vấn sử dụng Contains
, Length
, SequenceEqual
, vv trên thuộc tính byte[]
hiện đã được dịch sang SQL.
Các truy vấn sử dụng Reverse
hiện đã được dịch sang SQL.
context.Employees.OrderBy(e => e.EmployeeID).Reverse()
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)
Truy vấn sử dụng các phương thức trên chuỗi như Contains
, StartsWith
và EndsWith
hiện đã được dịch khi sử dụng trình cung cấp Azure Cosmos DB.
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;
}
}
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.
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.
Hai cải tiến hiệu suất sau được thực hiện cho SQLite:
GetBytes
, GetChars
và GetTextReader
hiện hiệu quả hơn bằng cách sử dụng SqliteBlob và streams.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.
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 Skip
và Take
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.
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.
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).
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 để 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();
Đ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));
Độ 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)".
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);
Đố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.
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 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.
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.
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.
Bạn có thể vui lòng tắt trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi duy trì hoạt động của trang web.
Bài viết này sẽ giúp bạn tìm hiểu về bộ chuyển đổi giá trị - một trong những cải tiến mạnh mẽ của Entity Framework Core 5.
Trong bài viết này, chúng ta sẽ khám phá cách làm việc với các tính năng của Entity Framework Core 5 (EF Core) để thực thi truy vấn SQL thô.
Với EF Core 5, chúng ta có thể thêm view vào trong DbContext và tạo view trong database bằng cách sử dụng cơ chế chuyển đổi cơ sở dữ liệu tích hợp sẵn.
Bài viết này sẽ khám phá các mối quan hệ trong cơ sở dữ liệu quan hệ và cách mô hình hóa các mối quan hệ đó bằng cách tiếp cận Code First trong EF Core.