Đây là một trường hợp hay ho liên quan đến lazy load của entity framework.
Cơ chế lazy load là tạo ra một proxy bọc xung quanh entity, để thay đổi các behaviour của entity mà interface vẫn giữ nguyên.
Ví dụ gọi Comment.Creator
, thực chất là gọi Proxy<Comment>.Query<Creator>
... (đại loại thế, tôi không đi vào implement details).
Như vậy nghĩa là muốn lazy load hoạt động thì dbcontext phải tạo được proxy wrap entity đó.
Trường hợp add 1 new entity (không phải proxy), DbContext.Add(entity), ngay sau đó lại dùng chính instance của DbContext này, query entity ra, thì entity đó vẫn là object cũ chứ không phải proxy tương ứng, nhờ cơ chế ChangeTracking của DbContext, dẫn đến việc không load được navigation property. Issue này sẽ rất phổ biến trong các domain event handler do DbContext có lifetime là scoped, tức là dbcontext, repository đều được sử dụng lại per http request.
Cách giải quyết có thể là:
- tạo instance DbContext mới, hoặc đặt DbContext có lifetime là transient
- tự reload entity khi cần
Problem và solution được minh họa băng unit test bên dưới