Reputation: 464
I'm using EF Core with .NET Core 3.1
I have simple example of Client-Event relationship:
public class BaseEntity
{
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime? ModifiedOn { get; set; }
}
public class Client : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class Event : BaseEntity
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public Client Client { get; set; }
}
In my context, I'm using Fluent API to specify relationships:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Event>()
.HasOne<Client>()
.WithMany()
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
}
When I create migration, the client table looks fine, but the event table looks like this:
migrationBuilder.CreateTable(
name: "Events",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
CreatedOn = table.Column<DateTime>(nullable: false),
ModifiedOn = table.Column<DateTime>(nullable: true),
Start = table.Column<DateTime>(nullable: false),
End = table.Column<DateTime>(nullable: false),
ClientId = table.Column<int>(nullable: false),
ClientId1 = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Events", x => x.Id);
table.ForeignKey(
name: "FK_Events_Clients_ClientId",
column: x => x.ClientId,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Events_Clients_ClientId1",
column: x => x.ClientId1,
principalTable: "Clients",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
Finally I end up having two columns: ClientId and ClientId1. Why is Entity Framework creating two columns for my relationship?
I wasn't using Fluent API so far and it worked perfectly with just shadow property ClientId auto-generated, but I needed to configure cascade delete form this entities, and since there is no other way to do it, I specified the relationship as pictured above. Since then, there is additional foreign key column for it.
I tried specifying a foreign key column:
modelBuilder.Entity<Event>()
.HasOne<Client>()
.WithMany()
.IsRequired()
.HasForeignKey("ClientId")
.OnDelete(DeleteBehavior.Cascade);
No effect so far. Is there any way to tell EF im using auto generated shadow properties?
Edit #1:
I also tried specyfing Foreign keys properties on my own like this:
public class Event : BaseEntity
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int ClientId { get; set; }
public Client Client { get; set; }
}
and then
modelBuilder.Entity<Event>()
.HasOne<Client>()
.WithMany()
.IsRequired()
.HasForeignKey(e => e.ClientId)
.OnDelete(DeleteBehavior.Cascade);
but there is still no effect.
Upvotes: 4
Views: 4303
Reputation: 136
You can try this:
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public int? ClientId { get; set; }
[ForeignKey("ClientId ")]
public virtual Client Client { get; set; }
}
Upvotes: 1
Reputation: 464
It turns out, relationships can be empty - leaving decision to the framework, but it doesn't really serve Your interest. I modified my code, so there is explicit pointing at the navigation property, and EF recognized the relationship and stopped creating shadow properties for the columns:
modelBuilder.Entity<Event>()
.HasOne<Client>(e => e.Client)
.WithMany()
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
Upvotes: 6