Reputation: 12647
Context: I have to change a part of a Model from a single value to a List of entries and need help defining the relationship between the two classes.
The Model (simplified) looks like this:
public class Settings {
public Guid Id { get; set; }
public Guid NodeId { get; set; }
public Guid UserId { get; set; }
public Guid TemplateId { get; set; }
// plus the respective virtual properties and a few more irrelevant things.
}
Now the relationship has changed so that I have to handle multiple Templates, plus a few new flags, to something like this:
public class Settings {
public Guid Id { get; set; }
public Guid NodeId { get; set; }
public Guid UserId { get; set; }
public ICollection<TemplateConfig> Configs { get; set; }
// ...
}
public class TemplateConfig {
public Guid NodeId { get; set; }
public Guid UserId { get; set; }
public Guid TemplateId { get; set; }
// and a few more flags
}
builder.Entity<TemplateConfig>().HasKey(t => new { t.NodeId, t.UserId, t.TemplateId });
Since many of my access will be directly on this list and based on either all entries for a Node, a User or a Template, I don't mind the redundancy in the IDs, Actually I prefer it.
I'd like to not have to add a SettingsId
just to be able to define this relationship, but rather do something like this:
builder.Entity<Settings>()
.HasMany(s => s.Configs)
.HasForeignKey(s => new {s.NodeId, s.UserId});
So based on the shared ID-pair NodeId, UserId
.
But my EF knowledge is still very limited.
I've tried it through the DbModelBuilder
and through ForeignKey
and Column
-attributes. Different errors; all boiling down to a mismatch in the number of IDs between the Principal and the Dependant in the relationship.
Thank you for any help.
Upvotes: 0
Views: 562
Reputation: 694
You Settings
class has a single column primary key public Guid Id { get; set; }
. when you define relationship, EF core tries to bind 2 column foreign key .HasForeignKey(s => new {s.NodeId, s.UserId});
to 1 column primary key of 'Settings'
which is not possible. But you can tell EF to bind a foreign key to different columns which are called "Principal Key". Try adding .WithPrincipal()
in your code like this:
builder.Entity<Settings>()
.HasMany(s => s.Configs)
.WithOne()
.HasForeignKey(c => new {c.NodeId, c.UserId})
.HasPrincipalKey(s => new {s.NodeId, s.UserId});
Since EF 6 does not have .HasPrincipalKey()
, the principal columns should be specified with .Map()
:
builder.Entity<Settings>()
.HasMany(s => s.Configs)
.WithOne()
.Map(cs =>
{
cs.MapLeftKey("NodeId", "UserId");
cs.MapRightKey("NodeId", "UserId");
});
Upvotes: 2