2016-03-06 114 views
0

我有以下代碼,並想知道是否有重構的方式,以刪除重複的邏輯。通過外鍵c訪問對象#

這會導致當前用戶急於加載。

var currentEmployee = RosterContext.Employees 
        .Where(e => e.User.Id == id) 
        .Include(e => e.Job.Department).FirstOrDefault(); 

var job = RosterContext.Employees.Where(e=>e.Job.Department.Id == currentEmployee.Job.DepartmentId).ToList(); 

我創建了的第一行代碼進行比較,結果誰在同一個部門工作的所有員工姓名另一個相同的上下文。我的問題是,因爲我使用兩個使用相同上下文(Employees)的linq表達式,我能否將兩個linq查詢合併爲一個? 它可能會變成一個long linq表達式,但它應該用於獲取當前用戶對象,然後比較用戶對象以獲取共享相同部門標識的所有員工?

回答

0

嘗試一個ORM框架,如實體框架或NHibernate是有意義的。 ORM framewok將數據庫FK關係建模爲一側的標量屬性和另一側的矢量屬性(集合)。 例如部門將有一個集合屬性Jobs,而一個Job實體將擁有一個標量Department屬性。 使用FK上的連接進行數據庫查詢就會變成相關屬性導航,例如 - 要訪問當前部門中的員工列表,您只需返回類似employee.Department.Employees的東西 - 也就是假設您的實體都已加載(這在實現中相當簡單EF,使用include語句)

+0

我認爲他已經使用EF因爲他說他使用Code First流利的API – trousyt

+0

嗨,謝謝你的迴應。我使用EF作爲Code First和Fluent API。我曾嘗試調用我的變量中的外鍵屬性,例如employee.Department.Employees,但由於某種原因返回null。 –

+0

默認情況下,導航屬性未初始化,要加載導航屬性,必須使用** include **語句明確指定此屬性,請參閱此鏈接https://msdn.microsoft.com/zh-cn/data/jj574232.aspx – ironstone13

0

EF Code First支持開箱即用的關係。您可以使用約定或顯式指定關係(例如,如果外鍵屬性被命名爲怪異的)。在這裏看到,例如:https://msdn.microsoft.com/en-us/data/hh134698.aspx

當你配置你的模型沒錯,你應該能夠訪問部門,像這樣:

var currentUser = _unitOfWork.Employee.GetEmployeeByID(loggedInUser.GetUser(user).Id); 
var job = currentUser.Job; 
var department = job.Department; 

// or 

var department = _unitOfWork.Employee.GetEmployeeByID(loggedInUser.GetUser(user).Id).Job.Department; 

要表明,在同一部門工作的所有員工:

var coworkers = department.Jobs.SelectMany(j => j.Employees); 

更新

要使用預先加載有一個倉儲類(你笑uldn't需要多個庫類在這種情況下,因此不需要使用工作單位):

public class EmployeeRepository { 
    private readonly MyContext _context = new MyContext(); // Or whatever... 

    public IList<Employee> GetCoworkers(int userId) { 
     var currentEmployee = _context.Employees 
      .Where(e => e.UserId == userId) 
      .Include(e => e.Job.Department)  // Use eager loading; this will fetch Job and Department rows for this user 
      .FirstOrDefault(); 

     var department = currentEmployee.Job.Department; 
     var coworkers = department.Jobs.SelectMany(j => j.Employees); 
     return coworkers; 
    } 
} 

,並調用它是這樣的...

var repo = new EmployeeRepository(); 
var coworkers = repo.GetCoworkers(loggedInUser.GetUser(user).Id); 

你可能會能夠通過選擇當前用戶的工作和部門(比如我已經完成),然後在相反的工作和員工回來時使存儲庫查詢更高效。我會留給你的。

+0

嗨,感謝您的有用建議。我不知道我是否做錯了,但我用流利的API來配置外鍵,但是當我試圖調用一個持有對其他表的屬性的屬性時,它將返回null,除非我實例化其他類即var job = currentUser。工作;當調試時,除了Job字段爲null之外,我發現currentUser的所有字段都可以。這也適用於工作部門,其中工作屬性對部門而言爲空值。只有這樣,我才能實現不爲null的新對象,即Department = new Department,然後傳遞這個變量。 –

+0

您可以發佈更多代碼來向我們展示您的關係的流利API配置以及您所展示關係和外鍵屬性的類的片段嗎? – trousyt

+0

modelBuilder.Entity () .HasMany(E => e.Jobs) .WithRequired(E => e.Department) .HasForeignKey(E => e.DepartmentId).WillCascadeOnDelete(假);這是我用Fluent API配置的方式。我做了一個種子,用FK ID輸出數據到表格中。 –

0

在Entity Framework中,您有使用子句來附加子項。因此,例如在純EF你可以這樣做:

var department = context.Department.Include(d => d.Jobs).First(d => d.DepartmentId == departmentId); 

https://msdn.microsoft.com/en-us/library/gg671236%28v=vs.103%29.aspx#Anchor_1

有了一個倉庫,你可能需要做這樣的事情:

EF Including Other Entities (Generic Repository pattern)

+0

嗨,還有我會無法使用急切地加載如你所說,因爲我要訪問我的數據庫集,而不是直接使用上下文開展工作的單位。即var t = unitofwork.Department.MethodsFromRepository(e-> e.propertyName) –