(以下适用于 Entity Framework 4.1 到 4.3.1 和 Code-First/ DbContext
。)
最接近您的想法的映射类型是Table-per-Type (TPT) 继承映射。它看起来像这样:
public abstract class EntityWithComments
{
public int Id { get; set; }
public ICollection<Comment> Comments { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string CommentText { get; set; }
public int EntityId { get; set; }
public EntityWithComments Entity { get; set; }
}
public class Car : EntityWithComments
{
public string Manufacturer { get; set; }
public string Color { get; set; }
}
public class Bicycle : EntityWithComments
{
public int Weight { get; set; }
public bool HasThreeWheels { get; set; }
}
EntityWithComments
是一个基类Car
,Bicycle
也许还有其他实体。然后你有一个派生DbContext
类:
public class MyContext : DbContext
{
public DbSet<EntityWithComments> EntitiesWithComments { get; set; }
public DbSet<Comment> Comments { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>()
.ToTable("Cars");
modelBuilder.Entity<Bicycle>()
.ToTable("Bicycles");
}
}
结果,您在数据库中有四个表:
一个Comments
看起来像您的提案但EntityId
不直接引用Cars
and表的Bicycles
表。相反,它指的是基本类型表EntitiesWithComments
。
表示抽象基类的表EntitiesWithComments
,它只有一个列,即Id
列。
在表和表Cars
之间具有一对一共享主键约束Id
的Id
表EntitiesWithComments
在表和表Bicycles
之间具有一对一共享主键约束Id
的Id
表EntitiesWithComments
然后,您可以 - 例如 - 加载所有蓝色汽车:
using (var ctx = new MyContext())
{
var blueCars = ctx.EntitiesWithComments.OfType<Car>()
.Where(c => c.Color == "Blue")
.ToList();
}
因为EntitiesWithComments
基表不包含任何列,除了Id
表之间没有必要的连接。生成的 SQL 如下所示,仅涉及派生类型的表:
SELECT
'0X0X' AS [C1],
[Extent1].[Id] AS [Id],
[Extent1].[Manufacturer] AS [Manufacturer],
[Extent1].[Color] AS [Color]
FROM [dbo].[Cars] AS [Extent1]
WHERE N'Blue' = [Extent1].[Color]
(我猜,这个查询中的奇怪0X0X
值是 EF 用来检查返回的行是否真的是汽车的类型描述符,但我不确定。)
如果您想加载所有带有三个轮子的自行车,包括他们的评论,则以下查询有效:
using (var ctx = new MyContext())
{
var bicyclesWithThreeWheelsWithComments = ctx.EntitiesWithComments
.Include(e => e.Comments)
.OfType<Bicycle>()
.Where(b => b.HasThreeWheels)
.ToList();
}