我正在尝试创建一个赞成/反对系统,但在尝试创建迁移时遇到错误。 我对 .NET 有点陌生,所以我真的不知道我需要做什么来解决我的问题。
为我返回的错误消息是:
具有外键属性 {'CommentId' : string} 的从 'Vote.Comment' 到 'Comment.Votes' 的关系无法定位主键 {'PostId' : string, 'UserId' : string},因为它不兼容。为此关系配置一个主键或一组具有兼容类型的外键属性。
这是所有必要的代码
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
{...}
#region Posts
builder.Entity<Post>()
.HasKey(p => p.UserId);
builder.Entity<Post>()
.HasOne(p => p.User)
.WithMany(u => u.Posts)
.HasForeignKey(p => p.UserId)
.OnDelete(DeleteBehavior.Restrict);
builder.Entity<Post>()
.Property(p => p.Title)
.HasMaxLength(100);
builder.Entity<Post>()
.Property(p => p.Text)
.HasMaxLength(1500);
// Comments
builder.Entity<Comment>()
.HasKey(c => new { c.PostId, c.UserId });
builder.Entity<Comment>()
.HasOne(c => c.User)
.WithMany(u => u.Comments)
.HasForeignKey(c => c.UserId)
.OnDelete(DeleteBehavior.Restrict);
builder.Entity<Comment>()
.HasOne(c => c.Post)
.WithMany(p => p.Comments)
.HasForeignKey(c => c.PostId)
.OnDelete(DeleteBehavior.Restrict);
builder.Entity<Comment>()
.Property(c => c.CommentText)
.HasMaxLength(1500);
// Votes
builder.Entity<Vote>()
.HasKey(v => new { v.PostId, v.CommentId });
builder.Entity<Vote>()
.HasOne(v => v.User)
.WithMany(v => v.Votes)
.HasForeignKey(v => v.UserId);
builder.Entity<Vote>()
.HasOne(v => v.Post)
.WithMany(v => v.Votes)
.HasForeignKey(v => v.PostId);
builder.Entity<Vote>()
.HasOne(v => v.Comment)
.WithMany(c => c.Votes)
.HasForeignKey(v => v.CommentId);
#endregion
}
public class AppUser : IdentityUser
{
public AppUser()
{
Follower = new List<FollowUser>();
Following = new List<FollowUser>();
Blocker = new List<BlockUser>();
Blocking = new List<BlockUser>();
Posts = new List<Post>();
Comments = new List<Comment>();
}
public override string Id { get; set; }
public required string FullName { get; set; }
// Follow system
public ICollection<FollowUser> Follower { get; set; }
public ICollection<FollowUser> Following { get; set; }
//Block System
public ICollection<BlockUser> Blocker { get; set; }
public ICollection<BlockUser> Blocking { get; set; }
// Posting System
public ICollection<Post> Posts { get; set; }
public ICollection<Comment> Comments { get; set; }
public ICollection<Vote> Votes { get; set; }
// Account Settings
public bool IsPrivate { get; set; } = false;
}
public abstract class PostEntity
{
public Guid Id { get; set; }
public AppUser User { get; set; }
public string UserId { get; set; }
}
public class Comment : PostEntity
{
public Post Post { get; set; }
public string PostId { get; set; }
public string CommentText { get; set; }
public ICollection<Vote> Votes { get; set; }
public Comment(string userId, string postId, string commentText)
{
Id = Guid.NewGuid();
UserId = userId;
PostId = postId;
CommentText = commentText;
}
}
public class Vote
{
public AppUser User { get; set; }
public string UserId { get; set; }
public readonly Post? Post;
public readonly string? PostId;
public readonly Comment? Comment;
public readonly string? CommentId;
public bool IsUpvote { get; set; }
public Vote(string? postId, string? commentId)
{
PostId = postId;
CommentId = commentId;
}
}
可能,您在
OnModelCreating
方法中不需要这个:
builder.Entity<Comment>()
.HasKey(c => new { c.PostId, c.UserId });
此外,我注意到
Vote
类具有带有 readonly
关键字的属性。尝试摆脱它们并创建一个默认构造函数。我很好奇为什么 ID 是string
?考虑使用 GUIDs
代替。
这应该是这样的:
public class Vote
{
public AppUser User { get; set; }
public Guid UserId { get; set; }
public Post? Post;
public Guid? PostId;
public Comment? Comment;
public Guid? CommentId;
public bool IsUpvote { get; set; }
public Vote() {}
public Vote(string? postId, string? commentId)
{
PostId = postId;
CommentId = commentId;
}
}
而且我不确定重载的构造函数
public Vote(string? postId, string? commentId)
。你真的需要吗?
此外,您似乎可以删除
OnModelCreating
方法中的一些绑定,因为默认情况下它们是在您的实体中定义的。尝试删除它,例如:
builder.Entity<Vote>()
.HasOne(v => v.Comment)
.WithMany(c => c.Votes)
.HasForeignKey(v => v.CommentId);