2017-01-23 18 views
1

我有以下的委託聲明:傳遞委託LINQ查詢在EF核心

private Func<Employee, bool> _exclude; 

然後在其他地方我的代碼並將其值設爲這樣的:

_exclude = (subject) => 
    !subject.IsDeleted && subject.Location.Department.Company.GroupId.Equals(_groupId); 

目標是重用過濾所有查詢。如果我要兌現這樣的僱員情況也能正常工作:

Employee theEmployee = db.Employees 
    .Include(e=>e.Location) 
    .ThenInclude(e => e.Department) 
    .ThenInclude(e => e.Company) 
    .Where(e => e.EmployeeId == EmployeeId && _exclude(e)) 
    .FirstOrDefault(); 

但當我只是想找回一個值,例如像失敗,僱員:

string employeeId = db.Employees 
    .Include(e=>e.Location) 
    .ThenInclude(e => e.Department) 
    .ThenInclude(e => e.Company) 
    .Where(e => e.EmployeeId == EmployeeId && _exclude(e)) 
    .Select(e => e.EmployeeId) 
    .FirstOrDefault(); 

的上面的失敗在Func委託中產生一個NullReferenceException _exclude因爲subject.Location值爲null,這意味着傳遞給委託的僱員沒有按照包含完全物化。

當需要一個完整的員工但成功投影查詢失敗時成功實現員工圖的原因是什麼,或者在這種情況下如何組成查詢?

我使用EF核心

+0

檢查數據,就看你是路過該員工的位置,我認爲正在發生的事情是,有沒有連接一個員工的位置 – Zinov

+0

@Zinov,每個員工都有一個位置,它在後端是必填字段。請記住,對於完整的員工來說,它工作得很好,如果不是,它也會失敗。 –

+0

使用'Func <...>'而不是'Expression >'的任何原因? –

回答

3

什麼可以引起,它成功地兌現是必要的,但失敗的投影查詢

在這兩種情況下,一個完全成熟的員工時,員工圖的_exclude(e)未翻譯爲SQL,但是在內存中進行了計算,並且由於Ignored includes和缺乏延遲加載支持而在第二種情況下失敗。

儘可能使用Expression<Func<...>>總是更好,因爲它們被轉換爲SQL並在數據庫端評估,所以包括無關緊要。

在你的情況下,它是很容易改變_exclude變量的類型(分配給它的lambda語法保持不變),並使用鏈接Where而不是在&&

private Expression<Func<Employee, bool>> _exclude; 

(根據過濾語義,它應該被稱爲_include_filter,但無論如何)

_exclude = (subject) => 
    !subject.IsDeleted && subject.Location.Department.Company.GroupId.Equals(_groupId); 

現在這個工程:

Employee theEmployee = db.Employees 
    .Include(e=>e.Location) 
    .ThenInclude(e => e.Department) 
    .ThenInclude(e => e.Company) 
    .Where(e => e.EmployeeId == EmployeeId) 
    .Where(_exclude) 
    .FirstOrDefault(); 

以及本:

string employeeId = db.Employees 
    // not needed, but will not hurt if used, will be ignored anyway 
    //.Include(e=> e.Location) 
    //.ThenInclude(e => e.Department) 
    //.ThenInclude(e => e.Company) 
    .Where(e => e.EmployeeId == EmployeeId) 
    .Where(_exclude) 
    .Select(e => e.EmployeeId) 
    .FirstOrDefault();