我有 3 个实体以一对多关系相互映射,其中一个应该映射到它们两个,这会导致不需要的多对多关系。
以下是映射背后的逻辑:
- 用户可以有很多帖子;帖子只有一个用户。
- 用户可以有许多类别;类别只有一个用户。
- 类别可以有很多帖子;帖子只有一个类别。
这是我的代码:
用户
Table("Users")]
Public Class User
{
[Key]
public int UserId { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string UserName { get; set; }
public DateTime CreatedAt { get; set; }
public ICollection<Posts> Posts { get; set; }
public ICollection<Category> Categories { get; set; }
}
发布
[Table("Posts")]
public class Post
{
[Key]
public int PostId { get; set; }
[Required]
public string Title { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Text { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
}
类别
[Table("Categories")]
public class Category
{
[Key]
public int CategoryId { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
public DateTime CreatedAt { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public ICollection<Post> Posts { get; set; }
}
我的数据库上下文
public class BlogContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Post> Posts{ get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>(entity =>
{
entity.HasMany<Post>(s => s.Posts)
.WithOne(u => u.User)
.HasForeignKey(s => s.UserId)
.OnDelete(DeleteBehavior.Restrict);
entity.HasMany<Category>(c => c.Categories)
.WithOne(u => u.User)
.HasForeignKey(c => c.UserId)
.OnDelete(DeleteBehavior.Restrict);
entity.Property(u => u.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
.HasForeignKey(s => s.PostId);
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
.HasForeignKey(s => s.PostId);
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
modelBuilder.Entity<Category>(entity =>
{
entity.HasMany<Post>(c => c.Posts)
.WithOne(s => s.Category)
.HasForeignKey(c => c.PostId)
.OnDelete(DeleteBehavior.Restrict);
entity.Property(c => c.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
}
}
插入帖子时遇到了这个问题:
The property 'PostId' on entity type 'Post' has a temporary value
我所理解的是,我与我实现 DbContext 的方式产生了多对多关系。我该如何解决它?感谢您的帮助。
您没有正确配置外键。让我们回顾一下您的Entity<Post>(entity=>{ /* ... */ })
代码:
modelBuilder.Entity(entity =>{ 实体。HasOne (s => s.Category( .WithMany(c => c.Posts( .HasForeignKey(s => s.PostId(; A行:不正确! 实体。HasOne (s => s.User( .WithMany(u => u.Posts( .HasForeignKey(s => s.PostId(;B行:不正确! 实体。属性(s => s.CreatedAt( .HasDefaultValueSql("SYSUTCDATETIME(("(;});
请注意,行 A 和行 B 不正确。与这两种情况一样,从属实体是Post
。您的代码将生成如下外键:
CREATE TABLE [Posts] (
[PostId] int NOT NULL,
[Title] nvarchar(max) NOT NULL,
[Description] nvarchar(max) NOT NULL,
[Text] nvarchar(max) NOT NULL,
[CreatedAt] datetime2 NOT NULL DEFAULT (SYSUTCDATETIME()),
[UpdatedAt] datetime2 NULL,
[UserId] int NOT NULL,
[CategoryId] int NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([PostId]),
CONSTRAINT [FK_Posts_Categories_PostId] FOREIGN KEY ([PostId]) REFERENCES [Categories] ([CategoryId]) ON DELETE NO ACTION,
CONSTRAINT [FK_Posts_Users_PostId] FOREIGN KEY ([PostId]) REFERENCES [Users] ([UserId]) ON DELETE NO ACTION
);
因此,您需要更改代码,如下所示:
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
//.HasForeignKey(s => s.PostId);
.HasForeignKey(s => s.CategoryId);
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
//.HasForeignKey(s => s.PostId);
.HasForeignKey(s => s.UserId);
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
出于同样的原因,您还应该更改Entity<Category>(entity=>{ /* ... */ })
的部分,如下所示:
modelBuilder.Entity<Category>(entity =>
{
entity.HasMany<Post>(c => c.Posts)
.WithOne(s => s.Category)
//.HasForeignKey(c => c.PostId) // remove this line
.HasForeignKey(c => c.CategoryId) // add this line
.OnDelete(DeleteBehavior.Restrict);
entity.Property(c => c.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
你在
modelBuilder.Entity<Post>(entity =>
{
entity.HasOne<Category>(s => s.Category)
.WithMany(c => c.Posts)
.HasForeignKey(s => s.PostId);
entity.HasOne<User>(s => s.User)
.WithMany(u => u.Posts)
.HasForeignKey(s => s.PostId);
entity.Property(s => s.CreatedAt)
.HasDefaultValueSql("SYSUTCDATETIME()");
});
表类别模型没有 PostId,用户模型也没有。更正此问题。