实体框架中的简单外键

本文关键字:简单 框架 实体 | 更新日期: 2023-09-27 18:02:55

我有一个关于实体框架中的外键和映射的简单问题。例如,我有一个类RestaurantGuest:

public interface IUser
{
    int Id { get; set; }
}    
public class RestaurantGuest : IUser
{
    public int Id { get; set; }
}

类Visit在另一个程序集中,它应该通过外键引用RestaurantGuest:

public class Visit
{
        public int Id { get; set; }
        public IUser Guest { get; set; }
        public int GuestId { get; set; }
}

RestaurantGuestclass没有也不应该有IList<Visit> Visits {get;set;}

如何在实体框架中映射它?

我期望这样的东西(但它不工作):

builder.VersionedEntity<Visit>().ToTable("Visits")
        .WithRequired(v => v.Guest).ToTable("RestaurantGuests")
        .HasForeignKey(o => o.GuestId)

但是所有的教程都会建议这样做:

builder.VersionedEntity<RestaurantGuest>()
         .HasMany(o => o.Visits)
         .WithRequired(v => v.Guest)
         .HasForeignKey(v => v.GuestId);

我不想添加一个拜访餐厅客人的列表。

实体框架中的简单外键

因为你的Guest实际上是一个接口,我猜你不能直接映射它,因为首先你甚至不能假设它总是一个RestaurantGuest。

我喜欢这样使用工厂:

public interface IUser
{
    int Id { get; set; }
}
public class RestaurantGuest : IUser
{
    public int Id { get; set; }
}
public class Visit
{
    public int Id { get; set; }
    public virtual GuestFactory Guest { get; set; }
    public int GuestId { get; set; }
}
public class GuestFactory: IUser
{
    public int Id { get; set; }
    public IUser Build()
    {
        return new RestaurantGuest { Id = this.Id };
    }
}
builder.VersionedEntity().HasMany()
       .WithRequired(v => v.Restaurant).HasForeignKey(v => v.RestaurantId);

build方法中,您应用所需的任何逻辑来实例化适当的具体类,在您的示例中是RestaurantGuest。您可以这样配置它:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<GuestFactory>().ToTable("RestaurantGuest");
        modelBuilder.Entity<Visit>()
            .HasRequired(v => v.Guest)
            .WithMany()
            .HasForeignKey(v => v.GuestId);
    }

当您运行此迁移时,输出如下:

public partial class RestaurantTest : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.RestaurantGuest",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                })
            .PrimaryKey(t => t.Id);
        CreateTable(
            "dbo.Visits",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    GuestId = c.Int(nullable: false),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.RestaurantGuest", t => t.GuestId, cascadeDelete: true)
            .Index(t => t.GuestId);
    }
    public override void Down()
    {
        DropForeignKey("dbo.Visits", "GuestId", "dbo.RestaurantGuest");
        DropIndex("dbo.Visits", new[] { "GuestId" });
        DropTable("dbo.Visits");
        DropTable("dbo.RestaurantGuest");
    }
}