Tôi đã có đồ thị đối tượng này:LINQ to NHibernate ThenFetch nhiều thuộc tính
// Lots of stuff omitted for brevity; these are all virtual properties and there
// are other properties which aren't shown on all classes.
class A {
B b;
C c;
DateTime timestamp;
}
class B {
X x;
Y y;
}
class X {
int id;
}
class C { }
class Y { }
or to put it more simply,
a = {
b: {
x { id: int },
y: { }
},
c: { },
timestamp: DateTime
}
Bây giờ tôi đang thực hiện một truy vấn mà tôi sẽ trả về một danh sách các A
s và tôi cần tất cả B
s của họ , C
s, X
s và Y
s. Tôi cũng sẽ nhóm chúng bằng B thành tra cứu.
ILookup<B, A> GetData(List<int> ids) {
using (ISession session = OpenSession()) {
var query = from a in session.Query<A>()
where ids.Contains(a.b.x.id)
orderby A.timestamp descending
select a;
query = query
.Fetch(a => a.b)
.ThenFetch(b => b.x)
.Fetch(a => a.b)
.ThenFetch(b => b.y)
.Fetch(a => a.c);
return query.ToLookup(a => a.b);
}
}
Một số điều cần lưu ý:
- Đây là một báo cáo trong đó tất cả dữ liệu cần phải được trả lại - kết quả vô biên không phải là một vấn đề.
- Tôi đang tạo nhóm bằng cách sử dụng
ToLookup
vì sử dụnggroup by
có vẻ phức tạp hơn khi bạn cần tất cả giá trị thực - bạn cần phải truy vấn cơ sở dữ liệu cho nhóm và sau đó cho giá trị thực của chúng.
Câu hỏi của tôi là cách chỉ định chiến lược tìm nạp đúng cách. Con đường tôi đã thực hiện nó là cách duy nhất tôi tìm thấy cho này để chạy (có lấy tất cả các bx và giá trị) - nhưng nó tạo ra SQL mà dường như sai:
select /* snipped - every mapped field from a0, b1, x2, b3, y4, c5 - but not b6 */
from [A] a0
left outer join [B] b1
on a0.B_id = b1.BId
left outer join [X] x2
on b1.X_id = x2.XId
left outer join [B] b3
on a0.B_id = b3.BId
left outer join [Y] y4
on b3.Y_id = y4.YId
left outer join [C] c5
on a0.C_id = c5.CId,
[B] b6
where a0.B_id = b6.BId
and (b6.X_id in (1, 2, 3, 4, 5))
order by a0.timestamp desc
Như bạn có thể thấy nó nhận được giá trị cho a.b
3 lần - b1
và b3
để tìm nạp và b6
cho mệnh đề where.
- Tôi cho rằng điều này có tác động tiêu cực đến hiệu suất DB - tôi có đúng không?
- Có cách nào để sửa đổi các cuộc gọi
.Fetch
của tôi để chỉ tìm nạpa.b
một lần không? - Đây có phải là cách tiếp cận tốt cho vấn đề của tôi không?
Trước hết, đây là tất cả-một có thể được nhìn thấy từ ánh xạ (chỉ có một B trong A và không phải danh sách), do đó, toàn bộ truy vấn sẽ chỉ tải 4 thực thể. Thứ hai, những gì bạn đang đề xuất là hoàn toàn trái ngược với những gì tôi muốn - thay vì giảm sự phức tạp của truy vấn bạn đã tăng nó bằng cách chia nó thành nhiều truy vấn. Truy vấn lý tưởng sẽ có các tham gia sau đây: 'từ [A] bên ngoài bên trái tham gia [B] trên ...bên ngoài bên trái tham gia [X] trên ... bên ngoài bên trái tham gia [Y] trên ... '. – configurator
Nhận xét trước đó của tôi có vẻ khó chịu; Tôi không có ý định ngăn cản bạn cố gắng giúp đỡ. Tôi _do_ đánh giá cao nỗ lực của bạn, ngay cả khi nó không có vẻ như nó từ bình luận trước đây của tôi. – configurator
Tôi đã kiểm tra hành vi được đề xuất về các thực thể có liên quan trước khi tải. Sử dụng NHibernate Profiler Tôi có thể thấy rằng chúng chỉ được lấy một lần, vì vậy có thể xác nhận rằng những gì bdrajer nói là đúng về bộ nhớ đệm dữ liệu trong phiên. –