How to set ForeignKey and Index properties using IEntityTypeConfiguration in EF Core 2.0

c# ef-fluent-api entity-framework-core

Question

I am attempting to use the EntityConfiguration interface which is new in EF Core 2.0.

Addendum Probably helpful to see the Message class

public class Message 
{
    public int MessageId { get; set; }

    [Required]
    public string MessageForUserId { get; set; }
    public virtual ApplicationUser MessageForUser { get; set; }

    [Required]
    public string MessageFromUserId { get; set; }

    public virtual ApplicationUser MessageFromUser { get; set; }

    [Required]
    public string MessageContent { get; set; }

    public bool MessageRead { get; set; }

    [Required]
    public DateTime MessageCreatedOn { get; set; }

    public DateTime? MessageReadOn { get; set; }
}

and the AppUser class

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public Gender Gender { get; set; }
    public SubscriptionLevel SubscriptionLevel { get; set; }
    public NotificationType NotificationType { get; set; }
    public string AvatarUrl { get; set; }
    public ICollection<Message> UserMessages { get; set; }
    public ICollection<Message> SentMessages { get; set; }
    public ICollection<IdentityUserClaim<string>> Claims { get;  set; }
}

Here is how the entity is defined in my OnModelCreating method.

builder.Entity<Message>()
            .HasOne(x => x.MessageForUser)
            .WithMany(x => x.UserMessages)
            .HasForeignKey(x => x.MessageForUserId)
            .OnDelete(DeleteBehavior.Restrict);

builder.Entity<Message>()
            .HasOne(x => x.MessageFromUser)
            .WithMany(x => x.SentMessages)
            .HasForeignKey(x => x.MessageFromUserId)
            .OnDelete(DeleteBehavior.Cascade);

My IEntityTypeConfiguration

public class AppUserConfig : IEntityTypeConfiguration<ApplicationUser>
{
    public void Configure(EntityTypeBuilder<ApplicationUser> builder)
    {           
        builder.Property(u => u.FirstName).HasMaxLength(31);
        builder.Property(u => u.FirstName).IsRequired();

        builder.Property(u => u.LastName).HasMaxLength(55);
        builder.Property(u => u.LastName).IsRequired();

        builder.Property(u => u.DateOfBirth).HasColumnType("datetime");
        builder.Property(u => u.DateOfBirth).IsRequired();

        builder.Property(u => u.Gender).IsRequired();
    }
}

The EF 6 way had a HasForeignKey method off builder which is no longer available and I cant seem to find any way to add them.

Here is how the migration built the table from my OnModelCreating method. I'd like to put most of these items in my configuration class.

migrationBuilder.CreateIndex(
            name: "IX_Messages_MessageForUserId",
            schema: "AppContext",
            table: "Messages",
            column: "MessageForUserId");

migrationBuilder.CreateIndex(
            name: "IX_Messages_MessageFromUserId",
            schema: "AppContext",
            table: "Messages",
            column: "MessageFromUserId");

migrationBuilder.AddForeignKey(
            name: "FK_Messages_AspNetUsers_MessageForUserId",
            schema: "AppContext",
            table: "Messages",
            column: "MessageForUserId",
            principalSchema: "AppContext",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);

migrationBuilder.AddForeignKey(
            name: "FK_Messages_AspNetUsers_MessageFromUserId",
            schema: "AppContext",
            table: "Messages",
            column: "MessageFromUserId",
            principalSchema: "AppContext",
            principalTable: "AspNetUsers",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);

There still is a HasIndex method, but I'm not sure how to duplicate what the migration is producing in the lambda expression for HasIndex.

1
2
11/15/2017 1:20:10 PM

Accepted Answer

HasForeignKey() is still available in EF Core, just like you did in EF6. The misconception is, that it is not available on EntityTypeBuilder<T>, but on ReferenceNavigationBuilder<T,K>, which is the return type from WithMany().

public class PostConfiguration : IEntityTypeConfiguration<Post>
{
    public void Configure(EntityTypeBuilder<Post> builder)
    {
        builder.HasOne(y => y.Blog)
                .WithMany(x => x.Posts)
                .HasForeignKey(x => x.BlogForeignKey);
    }
}


public class ApplicationContext :DbContext
{
    public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.ApplyConfiguration(new PostConfiguration());
    }

    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Post> Posts { get; set; }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
    public List<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public int BlogForeignKey { get; set; }
    public Blog Blog { get; set; }
}
2
11/15/2017 1:07:41 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow