First, here's a simple example database model, which has Products assigned to Categories, where CategoryId in Products is the FK relationship to Categories.
Products:
- ProductId (PK), INT
- ProductName VARCHAR(255)
- CategoryId (FK), INT
Categories
- CategoryId (PK), INT
- CategoryName VARCHAR(255)
For the .NET application data model, only a de-normalized representation of a Product is defined as an entity class:
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public int CategoryId { get; set; }
public string CategoryName { get; set; }
}
There is no Category class defined, and for this example, none is planned.
In the code-first Entity Framework DbContext-derived class, I've setup the DbSet<Product> Products entity set:
public virtual DbSet<Product> Products { get; set; }
And in the EntityTypeConfiguration, I'm attempting to wire it up, but I'm just not able to get it working right:
public class ProductConfiguration : EntityTypeConfiguration<Product>
{
public ProductConfiguration()
{
HasKey(t => t.ProductId);
// How do I instruct EF to pull just the column 'CategoryName'
// from the FK-related Categories table?
}
}
I realize that a SQL View could be created and then I could tell EF to map to that view using ToTable("App1ProductsView"), but in this example, I'd like to avoid doing so.
In a SQL ADO.NET ORM solution, there's no issue here. I can simply write my own SQL statement to perform the INNER JOIN Categories c ON c.CategoryId = p.CategoryId join. How can I use the EF code-first Fluent API to perform this same inner join when populating the entity?
In my research, I've seen a lot of "entity split across multiple tables" topics, but this is not that. Categories and Products are two distinct entities (from a database perspective), but the .NET code is meant to stay unaware of that.
Failed Attempt 1:
This does not work, and produces a strange query (seen with SQL Server Profiler).
Fluent config:
Map(m =>
{
m.Property(t => t.CategoryName);
m.ToTable("Categories");
});
Resulting SQL:
SELECT
[Extent1].[ProductId] AS [ProductId],
[Extent2].[ProductName] AS [ProductName],
[Extent2].[CategoryId] AS [CategoryId],
[Extent1].[CategoryName] AS [CategoryName],
FROM [dbo].[Categories] AS [Extent1]
INNER JOIN [dbo].[Product1] AS [Extent2] ON [Extent1].[ProductId] = [Extent2].[ProductId]