Reputation: 5456
Currently, we have this model - HostApplicationUser and it's bridging for Many-To-Many relationship between Host and ApplicationUser (extended from IdentityUser).
public class HostApplicationUser
{
public Guid HostID { get; set; }
public Host Host { get; set; }
public string Id { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public bool IsDeleted { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
An in our, ApplicationDBContext we modified the protected override void OnModelCreating(ModelBuilder builder) to include as follow:
// Many to Many relationships
builder.Entity<HostApplicationUser>()
.HasKey(bc => new { bc.HostID, bc.Id });
builder.Entity<HostApplicationUser>()
.HasOne(bc => bc.Host)
.WithMany(b => b.HostApplicationUsers)
.HasForeignKey(bc => bc.HostID);
builder.Entity<HostApplicationUser>()
.HasOne(bc => bc.ApplicationUser)
.WithMany(c => c.HostApplicationUsers)
.HasForeignKey(bc => bc.Id);
This code has been running ok. BUT now we have a new requirement to add few properties/navigation as follow:
public class HostApplicationUser
{
public Guid HostID { get; set; }
public Host Host { get; set; }
public string Id { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public DateTime CreatedUTC { get; set; }
public string CreatedBy { get; set; }
public DateTime LastModifiedUTC { get; set; }
public string LastModifiedBy { get; set; }
public DateTime? DeletedUTC { get; set; }
public string DeletedBy { get; set; }
public bool IsDeleted { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
[ForeignKey("CreatedBy")]
public ApplicationUser ApplicationCreatedUser { get; set; }
[ForeignKey("LastModifiedBy")]
public ApplicationUser ApplicationLastModifiedUser { get; set; }
}
Then we have an error when we run the add-migration:
Unable to determine the relationship represented by navigation property 'HostApplicationUser.ApplicationCreatedUser' of type 'ApplicationUser'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
Any ideas on how to adjust fix this? I believe this something to do with OnModelCreating(ModelBuilder builder) to include the other navigation but not sure how to do that.
Thanks
Upvotes: 1
Views: 67
Reputation: 25380
The reason is that there're multiple navigation properties on the dependent and principal entities pairs. Considering the following relationships between HostApplicationUser
and ApplicationUser
:
ApplicationUser
<->
HostApplicationUser.ApplicationUser
ApplicationUser
<->
HostApplicationUser.ApplicationCreatedUser
ApplicationUser
<->
HostApplicationUser.ApplicationLastModifiedUser
DeletedBy
If you have an navigation property to HostApplicationUser
on ApplicationUser
:
public class ApplicationUser{
public string Id{get;set;}
public string Name {get;set;}
public IList<HostApplicationUser> HostApplicationUsers{get;set;}
}
And if there's no extra configuration , the EF Core
cannot determine whether the Application.HostApplicationUsers
property is CreatedUsers
, LastModifiedUsers
, DeletedUsers
or something other users, i.e., the EF Core
cannot determine how the ApplicationUser.HostApplicationUsers
property is navigated to HostApplicationUser
, thus complains :
Unable to determine the relationship represented by navigation property 'HostApplicationUser.ApplicationCreatedUser' of type 'ApplicationUser'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
To fix the issue, simply decorate the ApplicationUser.HostApplicationUsers
with an InversePropertyAttribute
:
public class ApplicationUser{
public string Id{get;set;}
public string Name {get;set;}
[InverseProperty("ApplicationUser")]
public IList<HostApplicationUser> HostApplicationUsers{get;set;}
}
Or if would like to have multiple navigation properties, you need to add [InverseProperty("ApplicationCreatedUser")]
,[InverseProperty("ApplicationLastModifiedUser")]
,[InverseProperty("ApplicationDeletedUser")]
and so on for each navigation property :
public class ApplicationUser{
public string Id{get;set;}
public string Name {get;set;}
[InverseProperty("ApplicationUser")]
public IList<HostApplicationUser> HostApplicationUsers{get;set;}
[InverseProperty("ApplicationCreatedUser")]
public IList<HostApplicationUser> HostApplicationCreatedUsers{get;set;}
[InverseProperty("ApplicationLastModifiedUser")]
public IList<HostApplicationUser> HostApplicationLastModifiedUsers{get;set;}
// ...
}
Upvotes: 2