I am trying to create the following models in c# but am getting this error
System.InvalidOperationException: 'Unable to determine the relationship represented by navigation 'Activity.Token' of type 'Token2'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.'
Here are my 2 models
public class Token2
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
[ForeignKey(nameof(LastActivity))]
public long? LastActivityId { get; set; }
public Activity? LastActivity { get; set; }
public ICollection<Activity>? Activity { get; set; }
}
public partial class Activity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
public string Test { get; set; }
[ForeignKey(nameof(Token2))]
public long? TokenId { get; set; }
public Token2? Token { get; set; }
}
So the idea is that a Token has many activities related to it and I also want to keep that of the last activity acted on the Token.
And activity might be related to a Token or not, this is optional
How can i define this in EFCore?
CodePudding user response:
First Tip : Avoid using annotion Because in your case your entities Will be strongly depending on EF
Your Activity Entity :
public partial class Activity
{
public long Id { get; set; }
public string Test { get; set; }
public DateTime Date { get; set; }
public long? TokenId { get; set; }
public Token? Token { get; set; }
}
the Token class
public class Token
{
public long Id { get; set; }
public Activity? LastActivity
{
get
{
return Activities .OrderByDescending(q => q.Date).FirstOrDefault();
}
}
public ICollection<Activity>? Activities { get; set; }
}
And the configuration to add your on OnModelCreating Method
public class TokenConfiguration : IEntityTypeConfiguration<Token>
{
public void Configure(EntityTypeBuilder<Token> builder)
{
builder.HasKey(a => a.Id);
builder.HasMany(q => q.Activities).WithOne(q => q.Token).HasForeignKey(q => q.TokenId);
}
}
public class ActivityConfiguration : IEntityTypeConfiguration<Activity2>
{
public void Configure(EntityTypeBuilder<Activity2> builder)
{
builder.HasKey(a => a.Id);
}
}
CodePudding user response:
ForeignKeyAttribute's documentation :
The annotation may be placed on the foreign key property and specify the associated navigation property name, or it may be placed on a navigation property and specify the associated foreign key name.
If you add ForeignKeyAttribute on the foreign key property Activity.TokenId
, then you need specify the navigation property name Activity.Token
(not the type Token2
) like :
public partial class Activity
{
...
[ForeignKey(nameof(Token))]
public long? TokenId { get; set; }
public Token2? Token { get; set; }
}
But the question example follow the navigation key/property name convention (the foreign key property name is foreign navigation property name with the suffix "Id"), then you can just remove the ForeignKeyAttribute and EF Core will automatically do the work.