简体   繁体   中英

Simple foreign key in entity framework

I've got a simple question regarding foreign keys and mapping in Entity Framework. For example, I have a class RestaurantGuest:

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

And class Visit in another assembly, that should have reference to the RestaurantGuest by foreign key:

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

The RestaurantGuestclass does not and should not have an IList<Visit> Visits {get;set;}

How to map it in Entity Framework?

I expected something like this (but it does not work):

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

but all tutorials will suggest to do this:

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

I don't want to add a list of Visits to the RestaurantGuest. RestaurantGuest should not know anything about the visits.

Since your Guest is actually an Interface, I guess you can't map it directly, because first of all you can't even assume it'll be always a RestaurantGuest.

I like using a factory like this:

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);

Inside the build method, you apply whatever logic you need to instantiate the proper concrete class, in your case a RestaurantGuest . You configure it like this:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

        modelBuilder.Entity<GuestFactory>().ToTable("RestaurantGuest");

        modelBuilder.Entity<Visit>()
            .HasRequired(v => v.Guest)
            .WithMany()
            .HasForeignKey(v => v.GuestId);

    }

And when you ran a migration of this, this is the output:

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");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM