I am using the Fluent API and a code-first approach for defining the schema. I wonder why the migration is generating a new column instead of using the defined foreign key. Thus, the DbSet
is not linking correctly.
I am following this example: https://learn.microsoft.com/en-us/ef/core/modeling/relationships
The relationship looks like this: server-players (parent-child)
Player.cs
public class Player
{
public int Id { get; set; }
public int PlayerId { get; set; }
public string Name { get; set; }
public int ServerId { get; set; }
public Universe Server { get; set; }
}
Universe.cs (Server)
public class Universe
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id { get; set; }
public string Name { get; set; }
public string Domain { get; set; }
public List<Planet> Players { get; set; } = new List<Player>();
}
PlayerConfiguration.cs (Fluent API)
public class PlayerConfiguration : IEntityTypeConfiguration<Player>
{
public void Configure(EntityTypeBuilder<Player> builder)
{
builder.ToTable("Player")
.HasAlternateKey(e => new { e.PlayerId, e.ServerId });
builder.HasOne<Universe>()
.WithMany()
.HasForeignKey(e => e.ServerId);
}
}
The database script generated by EF:
CREATE TABLE [dbo].[Player]
(
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (MAX) NULL,
[ServerId] INT NOT NULL,
[ServerId1] INT NULL,
CONSTRAINT [PK_Player] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [AK_Player_PlayerId_ServerId]
UNIQUE NONCLUSTERED ([PlayerId] ASC, [ServerId] ASC),
CONSTRAINT [FK_Player_Universe_ServerId1]
FOREIGN KEY ([ServerId1]) REFERENCES [dbo].[Universe] ([Id])
);
GO
CREATE NONCLUSTERED INDEX [IX_Player_ServerId]
ON [dbo].[Player]([ServerId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_Player_ServerId1]
ON [dbo].[Player]([ServerId1] ASC);
So when I call context.Universes.Players.Add(...some players...)
and context.SaveChanges()
. The ServerIds will save to ServerId1
and keeping default in ServerId
column. When I try to query the data from the database, no Players will be found.
I realized that the AK is using the ServerID
as junction while the FK is using ServerId1
when I am typing the question. However, I will need to setup a composite unique key that identifies each player has only one ID in the server. The Id
column is a system generated one. While PlayerId
is captured from different servers. The PlayerId
can be duplicated across server.
I design the system to generate a new Id
too as it is linked to the system frequently for other purposes. It will waste time to link a composite key every time it is called.
I got the sample of defining a unique key from THIS ANSWER suggesting that I can use Alternate Key. Is this actually not true? Or I actually am not defining the FK correctly?
Updated 12/01/2018
PlayerId
is in Player
class instead of Universe
class. That was just mistake while copying.
.WithMany(u => u.Players)
generates the same result as .WithMany()
as suggested in the comment. Migration file has blank Up
/Down
too.