10 câu hỏi có thể gặp khi phỏng vấn
Chọn theo kỹ năng và cấp của tin (C# & .NET, ReactJS, SQL & Database). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.
01Dependency Injection trong ASP.NET Core: phân biệt Transient, Scoped và Singleton.C# & .NET
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →ASP.NET Core có DI container sẵn; lifetime quyết định khi nào tạo instance mới.
- Transient: mỗi lần resolve tạo mới. Hợp với service nhẹ, không trạng thái.
- Scoped: một instance cho mỗi request (mỗi scope).
DbContextmặc định là scoped. - Singleton: một instance cho cả vòng đời ứng dụng. Phải thread-safe.
builder.Services.AddScoped<IOrderService, OrderService>(); builder.Services.AddSingleton<IClock, SystemClock>();Hay sai: inject service scoped (như
DbContext) vào singleton, gọi là captive dependency: DbContext bị giữ mãi và dùng chung giữa nhiều thread. Môi trường Development sẽ báo lỗi khi validate scope. Nếu singleton cần dữ liệu scoped, hãy injectIServiceScopeFactoryvà tự tạo scope.02Middleware trong ASP.NET Core là gì? Thứ tự đăng ký có quan trọng không?C# & .NET
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Middleware là các bước nối thành pipeline xử lý request: mỗi bước có thể xử lý, gọi bước kế tiếp, rồi xử lý tiếp response trên đường về. Thứ tự rất quan trọng vì request đi qua đúng theo thứ tự đăng ký.
app.UseExceptionHandler("/error"); app.UseHttpsRedirection(); app.UseRouting(); app.UseCors(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers();- Exception handler phải đứng đầu để bắt lỗi của mọi bước sau.
UseAuthenticationphải trướcUseAuthorization, nếu không user luôn là ẩn danh.- Middleware có thể "short-circuit", vd. trả cache hoặc 401 mà không gọi
next.
Người phỏng vấn muốn nghe: bạn từng viết middleware riêng, vd. gắn correlation id hoặc log thời gian xử lý, và phân biệt được middleware với filter của MVC.
03Lỗi N+1 query trong Entity Framework Core là gì và xử lý thế nào?C# & .NET
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →N+1 là khi lấy danh sách N bản ghi bằng 1 query, rồi mỗi bản ghi lại phát sinh thêm 1 query để lấy dữ liệu liên quan, thường do lazy loading hoặc truy vấn trong vòng lặp.
Cách xử lý:
- Eager loading:
.Include(o => o.Items). - Tốt hơn nữa là projection chỉ lấy cột cần:
.Select(o => new OrderDto(o.Id, o.Items.Count)). - Include nhiều collection gây "cartesian explosion" thì dùng
.AsSplitQuery(). - Màn hình chỉ đọc thì thêm
.AsNoTracking()để giảm chi phí change tracking.
Để phát hiện, bật log SQL của EF Core khi phát triển, hoặc dùng công cụ APM xem số query mỗi request.
Người phỏng vấn muốn nghe: bạn kiểm tra SQL thực sự được sinh ra thay vì tin LINQ trông gọn là chạy nhanh.
- Eager loading:
04Custom hook là gì? Các quy tắc của hooks là gì và vì sao có chúng?ReactJS
Gợi ý trả lời
Ôn thêm câu hỏi ReactJS →Custom hook là hàm bắt đầu bằng
use, dùng các hook khác bên trong, để tái sử dụng logic có state giữa nhiều component (không chia sẻ state, mỗi component có bản riêng).function useDebounce(value, ms) { const [debounced, setDebounced] = useState(value); useEffect(() => { const id = setTimeout(() => setDebounced(value), ms); return () => clearTimeout(id); }, [value, ms]); return debounced; }Quy tắc: chỉ gọi hook ở cấp cao nhất của component hoặc custom hook; không gọi trong
if, vòng lặp hay saureturnsớm. Lý do: React nhận diện từng hook theo thứ tự gọi, đổi thứ tự là state bị ghép nhầm.Ngoại lệ: hook
use()của React 19 được gọi trong điều kiện.Người phỏng vấn muốn nghe: bạn bật ESLint plugin
react-hooksđể bắt các lỗi này tự động.05Bạn chọn cách quản lý state thế nào: Context, Redux Toolkit, Zustand hay TanStack Query?ReactJS
Gợi ý trả lời
Ôn thêm câu hỏi ReactJS →Trước hết phân loại state:
- Server state (dữ liệu từ API): dùng TanStack Query hoặc SWR. Chúng lo cache, loading, refetch, đồng bộ. Phần lớn "global state" trong app thực ra thuộc loại này.
- UI state cục bộ:
useState/useReducerngay trong component. - State trên URL (bộ lọc, trang): để trên query string, chia sẻ link được.
- Client state toàn cục thật sự (giỏ hàng, theme, user đang đăng nhập): Context nếu ít thay đổi; Zustand hoặc Redux Toolkit nếu thay đổi thường xuyên hoặc logic phức tạp.
Redux Toolkit hợp khi team lớn cần quy ước chặt và DevTools mạnh. Zustand gọn nhẹ hơn.
Hay sai: gom state hay thay đổi vào một Context lớn. Mọi component dùng Context đó render lại mỗi lần bất kỳ giá trị nào đổi. Hãy tách Context, hoặc dùng thư viện có selector.
06Một API chạy chậm, nghi do query. Bạn điều tra và tối ưu thế nào?SQL & Database
Gợi ý trả lời
Ôn thêm câu hỏi SQL & Database →Đo trước rồi mới sửa: tìm đúng query chậm, đọc execution plan, rồi chỉnh index hoặc cách viết query.
- Bật slow query log (MySQL) hoặc
pg_stat_statements(PostgreSQL) để biết query nào tốn thời gian nhất. - Chạy
EXPLAIN(PostgreSQL nên dùngEXPLAIN (ANALYZE, BUFFERS)) xem có full scan, ước lượng số dòng lệch nhiều so với thực tế, sort trên đĩa không. - Sửa theo nguyên nhân: thêm hoặc đổi composite index, bỏ hàm bọc cột, chỉ
SELECTcột cần, phân trang bằng keyset thay choOFFSETlớn. - Kiểm tra phía ứng dụng: lỗi N+1 query, thiếu connection pool, lock chờ lâu.
- Cập nhật thống kê (
ANALYZE) nếu planner ước lượng sai.
Người phỏng vấn muốn nghe: quy trình có số liệu trước/sau, không phải đoán rồi thêm index bừa.
- Bật slow query log (MySQL) hoặc
07Garbage Collector của .NET hoạt động thế nào? Khi nào cần IDisposable?C# & .NET
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →GC quản lý heap theo thế hệ: object mới ở Gen 0, sống sót qua lần thu gom thì lên Gen 1, Gen 2. Phần lớn object chết trẻ nên thu gom Gen 0 rất rẻ. Object lớn (khoảng từ 85 KB) vào Large Object Heap và chỉ được thu cùng Gen 2.
GC chỉ thu hồi bộ nhớ managed. Tài nguyên khác như file, socket, kết nối DB cần giải phóng chủ động qua
IDisposable:await using var conn = new NpgsqlConnection(cs); using var stream = File.OpenRead(path);- Finalizer chỉ là lưới an toàn, chạy không xác định thời điểm và tốn chi phí.
Hay sai: tạo mới
HttpClientcho mỗi request rồi dispose, dễ cạn socket. Hãy dùngIHttpClientFactoryhoặc một instance dùng chung.08Ứng dụng ASP.NET Core bị memory leak hoặc CPU cao trên production. Bạn điều tra thế nào?C# & .NET · Senior
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Thu thập số liệu trước, đoán sau: xem metrics, chụp dump hoặc trace, rồi phân tích.
- Theo dõi bằng
dotnet-counters: heap size, số lần GC từng gen, thread pool queue length, exception rate. - Leak bộ nhớ: chụp hai lần
dotnet-gcdumphoặcdotnet-dumpcách nhau một khoảng, so sánh loại object tăng và tìm ai đang giữ tham chiếu. - CPU cao hoặc treo:
dotnet-traceđể xem hot path; thread pool queue tăng thường do sync-over-async.
Nguyên nhân hay gặp: event handler không gỡ đăng ký, cache static không giới hạn kích thước, giữ
DbContextquá lâu, regex hoặc serialize lặp lại trong vòng lặp nóng.Người phỏng vấn muốn nghe: một ca thực tế bạn từng xử lý, công cụ đã dùng và kết quả trước/sau.
- Theo dõi bằng
09Xử lý concurrency khi nhiều request cùng cập nhật một bản ghi trong EF Core thế nào?C# & .NET · Senior
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Hai hướng chính: optimistic concurrency (phát hiện xung đột khi lưu) và pessimistic (khoá trước khi sửa).
Optimistic với EF Core: đánh dấu một cột làm concurrency token, EF thêm điều kiện so sánh vào
UPDATEvà némDbUpdateConcurrencyExceptionnếu không có dòng nào bị cập nhật.public class Product { public int Stock { get; set; } [Timestamp] public byte[] RowVersion { get; set; } = []; }- Bắt exception, tải lại dữ liệu, rồi retry hoặc báo người dùng.
- PostgreSQL thường dùng cột hệ thống
xminlàm token. - Trường hợp đơn giản như trừ tồn kho có thể dùng một câu
ExecuteUpdateAsyncatomic kèm điều kiệnStock >= qty.
Người phỏng vấn muốn nghe: bạn cân nhắc mức độ tranh chấp: thấp thì optimistic, cao và nghiệp vụ quan trọng thì khoá hoặc đưa vào hàng đợi.
10Điểm yếu của bạn là gì?Câu hỏi hành vi & văn hoá
Gợi ý trả lời
Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →Chọn điểm yếu thật, không chí mạng với vị trí, và cho thấy bạn đang cải thiện.
Cấu trúc: điểm yếu, ảnh hưởng đã gặp, việc bạn đang làm để khắc phục, tiến bộ đến nay.
Câu mẫu: "Trước đây em hay ngại hỏi khi bị kẹt, tự loay hoay quá lâu, có lần làm trễ task. Giờ em tự đặt giới hạn: kẹt quá một hai giờ mà không có hướng thì em hỏi đồng đội, kèm những gì đã thử. Từ khi làm vậy em xong việc đúng hạn hơn và học được nhanh hơn từ người khác."
Ví dụ khác có thể dùng: chưa quen nói trước đám đông, tiếng Anh nói chưa trôi chảy, hay ôm việc.
Hay sai: "Điểm yếu của em là quá cầu toàn" (nghe như né câu hỏi), hoặc nêu điểm yếu là kỹ năng cốt lõi của vị trí.
Bạn đã phỏng vấn ở CÔNG TY CP COWATECH MIỀN TRUNG?
Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.
Chia sẻ kinh nghiệm phỏng vấn