EF Core 3.0
I have the following (simplified) entities in my domain:
class ApplicationUser {
public int Id { get; set; }
public string UserName { get; set; }
// other properties
}
[Owned]
class Stamp {
public string Username { get; set; }
public ApplicationUser User { get; set; }
DateTime DateTime { get; set; }
}
class Activity {
public Stamp Created { get; set; }
public Stamp Modified { get; set; }
// other properties
}
It's not particularly relevant, but it's worth mentioning that ApplicationUser.UserName
is a non-primary, unique key. (ApplicationUser
actually inherits from ASP.NET IdentityUser
.)
I want to enforce that Stamp.Username
is a foreign key referencing ApplicationUser.UserName
.
If Stamp
was a regular, non-owned entity, this would have set up that relationship:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Stamp.Username => ApplicationUser.UserName
modelBuilder.Entity<Stamp>(e => {
e.HasOne(s => s.User)
.WithOne()
.HasForeignKey<Stamp>(s => s.Username)
.HasPrincipalKey<ApplicationUser>(u => u.UserName);
});
...
}
When I try to create a migration (dotnet ef migrations add
) I get an InvalidOperationException
saying "The type 'Stamp' cannot be configured as non-owned because an owned entity type with the same name already exists".
How to achieve what I'm trying to do, using Fluent API or otherwise?
This is one possible solution, likely not the most ellegant one. It is based on this answer mentioned by ChW in the comments.
modelBuilder.Entity<Activity>(e => {
e.OwnsOne(a => a.Created)
.HasOne<ApplicationUser>()
.WithOne()
.HasForeignKey<Stamp>(s => s.Username)
.HasPrincipalKey<ApplicationUser>(u => u.UserName);
});
This sets up the required foreign key on a particular Stamp
occurence (Created
) for a particular owner entity (Activity
).
A similar block of code would obviously need to be repeated for every other Stamp
occurence (in this example, Modified
) and for every other owner entity (Activity
may not be the only one).
Btw, I also ended up removing the Stamp.User
navigation property because EF has been using it to automatically create another foreign key that was (unwantedly) pointing to the ApplicationUser.Id
property.