2013-03-09 27 views
1

我在尋求如何更好地設計以下LINQ查詢(使用WCF數據服務)的建議。要求是通過ComboBox顯示員工列表。LINQ聲明優化 - 尋求更好設計的建議

數據庫表結構如下:

僱員可以被分配給許多項目和項目可以有很多員工。這種關係通過3個表格設計:[Employees] 1--* [EmployeeProjects] *--1 [Projects]。在dot國家,這就好像我正在遍歷對象樹:Employee.EmployeeProjects.Project

以下LINQ語句返回一個EmployeeProjects的列表,但是我之後是作爲這些特定項目的一部分的Employee列表。理想情況下,執行IQueryable<Employee>是有意義的,但是我不知道如何構建我的LINQ語句,因爲鏈接(很多)是EmployeeProjects。你看到我的困境嗎?

我執行IQueryable<EmployeeProject>,因爲從以下的LINQ語句中可以看出,我從來不必處理「Many」方面,因爲Employee和Project方都是1關係。在我得到EmployeeProjects的列表後,我對其執行另一個.Select()聲明,以返回我最終的結果,即唯一的員工姓名列表,例如, .Select(results => results.Employee.Name).Distinct()

private IQueryable<EmployeeProject> GetEmployeeProjects() 
{ 
    var employeeProjects = service 
     .CustomQuery<EmployeeProject>() 
     .Where(et => ep.Project.Name == "TrackerX 43" || 
        ep.Project.Name == "AccountingX 11" || 
        ep.Project.Name == "TopX 2" || 
        ep.Project.Name == "SiteX 32" || 
        ep.Project.Name == "BuildingX 3" || 
        ep.Project.Name == "ReportX 321" || 
        ep.Project.Name == "PrototypeX 78" || 
        ep.Project.Name == ... more ...) 
     .OrderBy(ep => ep.Employee.Name) 
     .Select(ep => new EmployeeProject 
     { 
      Id = ep.Id 
      Project = new Project 
      { 
       Name = ep.Project.Name 
      }, 
      Employee = new Employee 
      { 
       Id = ep.Employee.Id, 
       Name = ep.Employeet.Name 
      } 
     }); 

    return employeeProjects; 
} 

任何關於設計這個更好的建議將不勝感激。

回答

2

您是否需要創建新的EmployeeProject或者您是否可以簡單地返回現有的?

有一兩件事你可以做的是字符串組合成一個陣列,並將它們像這樣的比較:

//Move inside the method call if you need it to be dynamic. 
private readonly string[] compareProjectNames = new[] 
{ 
    "AccountingX 11", "TopX 2", "SiteX 32", 
    "BuildingX 3", "ReportX 321", "PrototypeX 78" 
}; 
private IQueryable<EmployeeProject> GetEmployeeProjects() 
{ 
    var employeeProjects = service.CustomQuery<EmployeeProject>() 
     .Where(et => compareProjectNames.Contains(ep.Project.Name)) 
     .OrderBy(ep => ep.Employee.Name) 
     .Select(ep => new EmployeeProject 
     { 
      Id = ep.Id, 
      Project = new Project 
      { 
       Name = ep.Project.Name 
      }, 
      Employee = new Employee 
      { 
       Id = ep.Employee.Id, 
       Name = ep.Employee.Name 
      } 
     }); 
    return employeeProjects; 
} 

編輯:

多一點認真閱讀您的文章後,您也可能尋找類似的東西來找到不同的項目名稱

List<EmployeeProject> employeeProjects = new List<EmployeeProject>(); 
employeeProjects 
    .GroupBy(et => et.Project.Name) 
    .Select(grp => grp.First()); 

或者,在1聲明

List<EmployeeProject> employeeProjects = new List<EmployeeProject>(); 
employeeProjects 
     .Where(et => compareProjectNames.Contains(et.Project.Name)) 
     .GroupBy(cust => cust.Project.Name) //groups them by name, so no need to order 
     .Select(grp => grp.First()) //selects the first distinct name per group 
     .Select(ep => new EmployeeProject 
     { 
      Id = ep.Id, 
      Project = new Project 
      { 
       Name = ep.Project.Name 
      }, 
      Employee = new Employee 
      { 
       Id = ep.Employee.Id, 
       Name = ep.Employee.Name 
      } 
     }); 
+0

我認爲你應該強調邏輯是有意向後的,以便你使用約束列表和.Compares(或.Contains)這個字段。雖然你可以按照正常的方式(field.Contains(constraint_array))來執行,但是後向方法會產生更簡潔的SQL查詢。 – Tory 2013-03-09 00:20:30

+0

我修正了比較 - >包含的東西,因爲這是一個錯字。但我不確定你的意思。 'str.Contains(arrayOfStr)'不是有效的語法。 – Corylulu 2013-03-09 00:30:08

+0

對,對不起。這就是我只需要檢查某些東西而不是自己嘗試的方法。我誤解了一些東西,儘管它允許另一種方式(我真正閱讀的內容是在另一箇中調用一個LINQ to SQL查詢)。我所說的其他一切仍然存在。 – Tory 2013-03-09 00:37:49

0

如果您在服務器端使用EF,您應該能夠從客戶端完全隱藏EmployeeProject表。 EF應該能夠將你的數據庫結構變成兩個實體集(僱員和項目),它們之間具有多對多關係(詳細地說,它將創建兩個1-Many單向關係)。

因此從客戶端看起來就像一個Employees實體集合,其中每個實例都有一個屬性Projects,這是該員工參與的項目列表。同樣,一個實體設置了Projects,其中每個實例都有一個屬性Employees分配給該項目的員工名單。

接着上面的查詢可以是簡單得多(使用急促的URL表示法中,LINQ的版本是有點明顯,也簡化了項目名稱的列表):

〜/項目?$ filter =(Name eq'TopX 2')或(Name eq'SiteX 32')& $ expand = Employers

這會讓你得到具有指定名稱的所有項目,併爲每個項目分配其所有員工。

這假設中間表純粹是爲了連接另外兩個表,如果你還在其中存儲了一些關於連接的附加信息,那麼這將不起作用。

+0

Hello Vitek,感謝您的回覆,但需要EmployeeProject類/表,因爲它具有需要包含的其他屬性並提供其他詳細信息。這有幫助嗎?謝謝... – user118190 2013-03-11 10:12:33

+0

然後正如我的答案中指出的那樣,這種方法不能使用。你有什麼看起來像唯一可行的方法已經。 – 2013-03-12 10:01:12

+0

感謝Vitek的迴應。爲了確認,儘管我想返回Employees集合,但是沒有辦法,因此必須首先返回一個EmployeeProjects集合?這看起來不對,就是這樣。我試圖尋找替代品,如使用.SelectMany(),但不知道如何按摩它到我的聲明。 – user118190 2013-03-13 13:54:02