7

Tôi có truy vấn LINQ NHibernate không hoạt động như thế nào.NHibernate đang tạo SQL với tham gia không hợp lệ

Sự cố dường như đến từ việc sử dụng cột int có thể vô hiệu hóa từ bảng được nối bên trái trong mệnh đề where. Điều này gây ra sự tham gia hoạt động như một sự tham gia bên trong.

var list = this.WorkflowDiaryManager.WorkflowActionRepository.All 
    .Fetch(x => x.CaseView) 
    .Fetch(x => x.WorkflowActionType) 
    .ThenFetchMany(x => x.WorkflowActionPriorityList) 
    .Where(x => x.AssignedUser.Id == userId || x.CaseView.MooseUserId == userId) 

SQL được tạo ra bởi điều này có vẻ như (từ tham gia trở đi - bạn không cần phải nhìn thấy tất cả đã lựa chọn phương)

from Kctc.WorkflowAction workflowac0_ 
left outer join Kctc.WorkflowCaseView workflowca1_ on workflowac0_.CaseId=workflowca1_.CaseId 
left outer join Kctc.WorkflowActionType workflowac2_ on workflowac0_.WorkflowActionTypeId=workflowac2_.WorkflowActionTypeId 
left outer join Kctc.WorkflowActionPriority workflowac3_ on workflowac2_.WorkflowActionTypeId=workflowac3_.WorkflowActionTypeId 
,Kctc.WorkflowCaseView workflowca4_ 
where workflowac0_.CaseId=workflowca4_.CaseId 
and ([email protected] or workflowca4_.[MooseUserId][email protected]); 
@p0 = 1087 [Type: Int32 (0)], 
@p1 = 1087 [Type: Int32 (0)] 

Vì vậy, các phần đó gây ra vấn đề là dòng 5 đoạn mã ở trên. Như bạn có thể thấy, NHibernate đang cố gắng làm một 'old-school' tham gia vào WorkflowCaseView View của tôi. Điều này làm cho truy vấn loại trừ các hành động hợp lệ khác không có một CaseId trong bảng WorkflowAction.

Ai đó có thể giải thích tại sao NHibernate đang viết câu lệnh SQL này và cách tôi có thể khuyến khích nó tạo ra một truy vấn tốt hơn?

Cảm ơn!

bit quan trọng từ WorkflowActionMap

bit
 Table("Kctc.WorkflowAction"); 
     Id(x => x.Id).GeneratedBy.Identity().Column("WorkflowActionId"); 
     References(x => x.WorkflowActionType).Column("WorkflowActionTypeId").Unique(); 
     References(x => x.CompletedBy).Column("CompletedBy"); 
     References(x => x.CaseView).Column("CaseId").Not.Update().Unique(); 
     References(x => x.AssignedUser).Column("AssignedUser"); 

quan trọng từ WorkflowCaseViewMap

 Table("Kctc.WorkflowCaseView"); 
     Id(x => x.Id).Column("CaseId"); 
     Map(x => x.MooseUserId).Nullable(); 

Nhìn này, tôi tự hỏi liệu tôi có nên có một HasMany sẽ trở lại theo cách khác ...

CHỈNH SỬA. Dường như không giúp

Trả lời

0

Tôi đã triển khai phép nối này bằng quy trình được lưu trữ. Hy vọng NHibernate sẽ sớm sửa lỗi này.

3

Tôi nghĩ rằng bạn cần phải thay đổi điều khoản Where của bạn như thế này:

.Where(x => x.AssignedUser.Id == userId || 
     (x.CaseView != null && x.CaseView.MooseUserId == userId)) 

Với Where khoản hiện tại của bạn, bạn nói với NHibernate rằng có lúc nào cũng sẽ là một CaseView, bởi vì bạn vô điều kiện truy cập của nó tính chất. Dựa trên thông tin này NHibernate tối ưu hóa truy vấn của bạn từ một số left outer join đến số inner join (liên kết "trường học cũ") là

+0

Cảm ơn câu trả lời nhanh. Tôi đã thử đề xuất của bạn (và đã tự mình nghĩ ra, chỉ sử dụng .HasValue thay vì! = Null) và nó không giúp ích gì. –

+0

@MarkWithers: Điều gì sẽ xảy ra nếu bạn loại bỏ hoàn toàn phần đó khỏi mệnh đề 'Where'? Ánh xạ của bạn giữa 'WorkflowCaseAction' và' WorkflowCaseView' như thế nào? –

+0

Nếu tôi loại bỏ "|| x.CaseView.MooseUserId == userId" khỏi mệnh đề where nó mang lại các hành động không có hồ sơ vụ án và sử dụng ba phép nối ngoài bên trái như tôi mong đợi. –

0

Thử sử dụng Fluent NHibernate. Một cái gì đó như sau sẽ giúp bạn trong quyền công viên bóng:

var List<WorkflowAction> = FluentSessionManager.GetSession().CreateCriteria<WorkflowAction>() 
     .SetFetchMode("CaseView", FetchMode.Eager) 
     .SetFetchMode("WorkflowActionType", FetchMode.Eager) 
     .SetFetchMode("WorkflowActionPriorityList", FetchMode.Eager) 
     .CreateAlias("AssignedUser", "au") 
     .CreateAlias("CaseView", "cv") 
     .Add(Expression.Or(Expression.Eq("au.Id", userId), Expression.Eq("cv.MooseUserId", userId))) 
     .List<WorkflowAction>(); 

Hãy ghi nhớ, tôi có một lớp học đặc biệt kéo dài FluentSessionManager.GetSession() nơi tôi có thể gọi nó là trực tiếp với một lớp helper đơn giản hoặc trên một từng trang. Thiết lập của bạn của FluentSessionManager có thể khác nhau đáng kể. Nhưng cuối cùng tại ".CreateCriteria() ..." mã của bạn và của tôi phải khớp. Giả sử "WorkflowAction" là bảng truy vấn đang được gọi là chống lại.

Các vấn đề liên quan