2015-11-05 54 views
0

我錯過了一些基本的東西,我相信。LINQ - 首先在EF代碼中對父類進行外連接

我有以下EF代碼優先實體:公司和調制解調器。一家公司可以有一個調制解調器列表。

public class Company 
    { 
     public int ID { get; set; } 
     ... 
     public virtual ICollection<Modem> Modems { get; set:} 
    } 


public class Modem 
    { 
     public int ID { get; set; } 
     ... 

    } 

這產生的外鍵列Company_ID,在Modem表。

我想返回所有調制解調器及其公司ID,如果有的話。 在SQL我將做到以下幾點:

select * from Modem m 
left outer join Company c on 
m.Company_ID = c.ID 

我所熟悉的做一個左外使用.DefaultIfEmpty()在DB-第一,而不是代碼優先加入LINQ。

我的困惑出現的地方是我沒有m.Company_ID在LINQ中進行連接,因爲它是由EF自動生成的。

如何在LINQ中執行此連接?

+2

爲什麼您的調制解調器類沒有引用「公司」?像'公司公司{獲得;集;}'。 – juharr

+0

你有沒有試過類似... db.Companies.SelectMany(c => c.Modems)?其中db是你的實體 – avi

+0

@avi聽起來像一些調制解調器沒有鏈接到公司,因爲OP想要離開加入公司。 – juharr

回答

1

EF的真正之處在於,你根本不需要考慮連接(大部分情況下)。您所需要的只是通過導航屬性正確定義您的實體及其關係。舉例來說,在這裏與你相似的模型的定義:

public class Company 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual ICollection<Modem> Modems { get; set; } 
} 

public class Modem 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public virtual Company Company { get; set; } 
} 

public class MyDbContext : DbContext 
{ 
    public DbSet<Company> Companies { get; set; } 
    public DbSet<Modem> Modems { get; set; } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Company>() 
      .HasMany(company => company.Modems) 
      .WithOptional(modem => modem.Company) 
      .Map(action => action.MapKey("Company_ID")); 
     base.OnModelCreating(modelBuilder); 
    } 
} 

注意Company.ModemsModem.Company屬性和關係的流暢配置,包括FK列的名稱。

現在,如果我們做了以下

using (var db = new MyDbContext()) 
{ 
    var query = db.Modems.Select(m => new { Modem = m, CompanyName = m.Company.Name }); 
    var sqlQuery = query.ToString(); 
} 

sqlQuery變量包含

SELECT 
    [Extent1].[ID] AS [ID], 
    [Extent1].[Name] AS [Name], 
    [Extent1].[Company_ID] AS [Company_ID], 
    [Extent2].[Name] AS [Name1] 
    FROM [dbo].[Modems] AS [Extent1] 
    LEFT OUTER JOIN [dbo].[Companies] AS [Extent2] ON [Extent1].[Company_ID] = [Extent2].[ID] 

而且你去那裏 - 希望你看到LEFT OUTER加入你詢問。

+0

唯一要添加的是,當訪問'Company'屬性時,您需要小心並檢查空引用。 在C#5中: 'var query = db.Modems.Select(m => new {Modem = m,CompanyName = m.Company == null?string.Empty:m.Company.Name});' 在C#6中: 'var query = db.Modems.Select(m => new {Modem = m,CompanyName = m.Company ?.Name});' –

+0

很好的例子。導航屬性是我錯過的概念,因爲我錯誤地認爲這些是自動創建的。 –