问题
I am missing something fundamental here I believe.
I have the following EF code-first entities: Company and Modem. A company can have a list of modems.
public class Company
{
public int ID { get; set; }
...
public virtual ICollection<Modem> Modems { get; set:}
}
public class Modem
{
public int ID { get; set; }
...
}
This generates a column Company_ID
as a foreign key, on the Modem
table.
I want to return all modems, with their company ID, if available. In SQL I would do the following :
select * from Modem m
left outer join Company c on
m.Company_ID = c.ID
I am familiar with doing a left outer join in LINQ using .DefaultIfEmpty() in DB-first rather than code-first.
Where my confusion arises is that I don't have m.Company_ID available in LINQ to do the join, as it is auto generated by EF.
How do I perform this join in LINQ?
回答1:
The real beauty of the EF is that you don't need to think of joins at all (well, most of the time). All you need is to properly define your entities and their relations via navigation properties. For instance, here is a definition of a model similar to yours:
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);
}
}
Note the Company.Modems
and Modem.Company
properties, and the fluent configuration of the relationship, including the name of the FK column.
Now, if we do the following
using (var db = new MyDbContext())
{
var query = db.Modems.Select(m => new { Modem = m, CompanyName = m.Company.Name });
var sqlQuery = query.ToString();
}
the sqlQuery
variable contains
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]
And there you go - hope you see the LEFT OUTER
join you were asking for.
来源:https://stackoverflow.com/questions/33547673/linq-outer-join-to-parent-class-in-ef-code-first