- vừa được xem lúc

Một số lưu ý khi sử dụng Linq trong C#

0 0 20

Người đăng: LongNguyen

Theo Viblo Asia

Hi anh em, chúc mọi người một ngày làm việc hiệu quả và đây năng lượng. Hôm nay mình sẽ nói về một số kinh nghiệm của mình khi làm việc với LINQ C#.

Không để anh em chờ lâu, cùng bắt đầu vào bài viết nào. Bài viết này mình sẽ nói các tool để theo dõi performance khi sử dụng linq và một số lưu ý về việc viết linq trong C#. Về cơ bản linq anh em có thể xem ở bài viết trước của mình: https://viblo.asia/p/linq-trong-c-6J3ZgpgxlmB

1. Source code Linq của Microsoft

Ví dụ: ta có thể xem method Count() viết như thế nào image.png

2. Một số tool để monitor performance khi sử dụng linq

  • SQL Server Profiler: Cho phép ghi lại và phân tích câu truy vấn được tạo ra từ Linq image.png

  • LINQPad: https://www.linqpad.net/ một công cụ giúp viết và test linq query, phân tích performance và thời gian execute của query.

  • Stopwatch class: Đo thời gian chạy trước và sau khi query thực thi.

  • BenchMark Dotnet: cho phép so sánh thời gian chạy giữa nhiều function. https://github.com/dotnet/BenchmarkDotNet

3. Sử dụng IQueryable thay cho IEnumerable

  • Iqueryable cho phép build query và execute query dựa trên database thay vì thực thi trên memory nếu sử dụng IEnumerable. Điều này giúp cải thiện performance khi query với data lớn.

Ví dụ:

  • Ta có list chứa 1000000 customer và ta so sánh peformance khi sử dụng IQueryable và IEnumerable
var customers = new List<Customer>();
for (int i = 0; i < 1000000; i++)
{ customers.Add(new Customer { FirstName = $"First{i}", LastName = $"Last{i}" });
}

//Sử dụng IEnumerable 
var stopwatch = new Stopwatch(); stopwatch.Start();
var results = customers.Where(c => c.LastName.StartsWith("S")).ToList();
stopwatch.Stop(); Console.WriteLine($"IEnumerable took {stopwatch.ElapsedMilliseconds}ms"); //Sử dụng IQueryable 
stopwatch.Restart();
var results2 = customers.AsQueryable().Where(c => c.LastName.StartsWith("S")).ToList();
stopwatch.Stop(); Console.WriteLine($"IQueryable took {stopwatch.ElapsedMilliseconds}ms"); 

**=> Kết quả: **

IEnumerable took 256ms
IQueryable took 24ms

4. Sử dụng method syntax thay vì query syntax

  • Sử dụng method syntax nhanh hơn query syntax bởi vì query syntax sẽ được C# compiler chuyển đổi thành method syntax trước khi nó thực thi.
  • Tuy nhiên performance giữa method syntax và query syntax không đáng kể, nhưng best practice khi làm việc với linq là sử dung method syntax đặc biệt với lượng data lớn.

Ví dụ:

  • Ta có list 1000000 orders

var orders = new List<Order>();
for (int i = 0; i < 1000000; i++)
{ orders.Add(new Order { Total = i * 0.01m });
}
var stopwatch = new Stopwatch(); //Query syntax
stopwatch.Start();
var querySyntaxResult = from o in orders where o.Total > 1000 select o;
stopwatch.Stop(); Console.WriteLine($"Query syntax took {stopwatch.ElapsedMilliseconds}ms"); //Method syntax
stopwatch.Restart();
var methodSyntaxResult = orders.Where(o => o.Total > 1000);
stopwatch.Stop(); Console.WriteLine($"Method syntax took {stopwatch.ElapsedMilliseconds}ms"); 

=> Kết quả:

Query syntax took 71ms
Method syntax took 6ms 

5. Cẩn thận khi sử dụng GroupBy

  • Group by tốn rất nhiều chi phí nên nếu ta lạm dụng có thể làm cho performance không tốt.

Ví dụ:

  • Ta có một list orders của các customers và mỗi customer có thể có ít nhất 1 order. Yêu cầu: lấy ra tổng số lượng order của mỗi customer.
  • Ta sẽ viết theo 2 cách và dùng benchMark để so sánh performance:
//Group by query
var orders = dbContext.Orders .GroupBy(o => o.Customer) .Select(g => new { Customer = g.Key, OrderCount = g.Count() });
//Target query
var customers = dbContext.Customers .Where(c => c.Orders.Any()) .Select(c => new { Customer = c, OrderCount = c.Orders.Count() });

=> Kết quả:

image.png

6. Sử dụng AsNoTracking trong Linq Entity framework

  • Sử dụng AsNoTracking, Entity framework sẽ không track lại những thay đổi của entites. Điều này giúp cải thiện performance và giảm sử dụng bộ nhớ khi get dữ liệu bởi vì get dữ liệu không cần phải track lại những thay đổi. Ví dụ:
using System;
using System.Diagnostics;
using System.Linq; namespace AsNoTrackingBenchmark
{ class Program { static void Main(string[] args) { using (var db = new MyDbContext()) { // warmup db.Customers.AsNoTracking().Where(c => c.LastName == "Smith").ToList(); db.Customers.Where(c => c.LastName == "Smith").ToList(); var stopwatch = new Stopwatch(); // AsNoTracking stopwatch.Start(); for (int i = 0; i < 1000; i++) { db.Customers.AsNoTracking().Where(c => c.LastName == "Smith").ToList(); } stopwatch.Stop(); Console.WriteLine($"AsNoTracking: {stopwatch.ElapsedMilliseconds} ms"); // tracking stopwatch.Reset(); stopwatch.Start(); for (int i = 0; i < 1000; i++) { db.Customers.Where(c => c.LastName == "Smith").ToList(); } stopwatch.Stop(); Console.WriteLine($"Tracking: {stopwatch.ElapsedMilliseconds} ms"); } } }
}

=> Kết quả:

AsNoTracking: 194 ms
Tracking: 298 ms

7. Sử dụng Parallel LINQ

  • Sử dụng Parallel LINQ có thể cải thiện performance của linq. Sau đây là 1 ví dụ:
var numbers = Enumerable.Range(1, 1000000);
var stopwatch = new Stopwatch(); // Measure time for LINQ query
stopwatch.Start();
var result1 = numbers.Where(n => n % 2 == 0).Sum();
stopwatch.Stop();
Console.WriteLine($"Time for LINQ query: {stopwatch.ElapsedMilliseconds} ms"); // Measure time for PLINQ query
stopwatch.Reset();
stopwatch.Start();
var result2 = numbers.AsParallel().Where(n => n % 2 == 0).Sum();
stopwatch.Stop();
Console.WriteLine($"Time for PLINQ query: {stopwatch.ElapsedMilliseconds} ms"); 

=>Kết quả:

Time for LINQ query: 11 ms
Time for PLINQ query: 3 ms

8. Linq performance trong .NET 7

  • Ở phần này mình sẽ dùng benchmark so sánh performance giữa .net 6 và .net 7. Ở đây mình tham khảo page: https://code-maze.com/linq-performance-dotnet7/
  • Kết quả của 1 số methods:
    • Min(), Max(), Average(), Count(), và Sum() image.png

    • First() và Last() image.png

    • Filtering Methods – Distinct() và Where() image.png

9. Tổng kết

  • Qua bài viết này hy vọng mọi người hiểu thêm về LINQ và giúp ích được anh em với một số tips.
  • Cảm ơn mọi người đã xem bài viết. Chúc anh em một ngày làm việc hiệu quả và đầy năng lượng. Nếu có thắc mắc về các phần trong bài này mọi người có thể inbox qua facebook:https://www.facebook.com/FriendsCode-108096425243996 Mình sẽ giải đáp thắc mắc trong tầm hiểu biết. Cảm ơn mọi người!
  • Hoặc liên hệ mình qua facebook cá nhân: https://www.facebook.com/Flamesofwars/

Bình luận

Bài viết tương tự

- vừa được xem lúc

Các loại tham chiếu Nullable trong C# (Phần 1)

1. Giới thiệu. C# 8.0 giới thiệu kiểu tham chiếu nullable và kiểu tham chiếu non-nullable cho phép bạn đưa ra các lựa chọn quan trọng về thuộc tính cho các biến kiểu tham chiếu:.

0 0 52

- vừa được xem lúc

Command pattern qua ví dụ !

Command pattern là gì . Command pattern khá phổ biến trong C #, đặc biệt khi chúng ta muốn trì hoãn hoặc xếp hàng đợi việc thực hiện một yêu cầu hoặc khi chúng ta muốn theo dõi các hoạt động. Hơn nữa, chúng ta có thể hoàn tác tác chúng. .

0 0 192

- vừa được xem lúc

Hiểu Liskov Substitution Principle qua ví dụ !

Liskov Substitution Principle là gì . Nguyên tắc đóng mở xác đinh rằng các instance của lớp con có thể thay thế được instance lớp cha mà vẫn đảm bảo tính đúng đắn của chương trình.

0 0 36

- vừa được xem lúc

Creating custom Controls Wpf

Introduction. Wpf/winforms provides various controls like Buttons, Textbox, TextBlock, Labels etc.

0 0 55

- vừa được xem lúc

[P1] Chọn công nghệ nào để xây dựng website?

Hiện nay nhu cầu phát triển website, app tăng rất cao do xu hướng "số hóa 4.0" trong và ngoài nước.

0 0 86

- vừa được xem lúc

Kiểu dữ liệu trong C#

Dẫn nhập. Ở bài BIẾN TRONG C# chúng ta đã tìm hiểu về biến và có một thành phần không thể thiếu khi khai báo biến – Đó là kiểu dữ liệu.

0 0 36