我是实体框架新手,我的个人项目需要一个相当复杂的实体数据结构。
我正在使用 .NET 8 和 Entity Framework Core v8。
我希望用户能够获取我现有的书籍/章节/页面实体的自己的副本并添加自己的数据。例如,将章节或页面标记为
IsCompleted=true
或添加用户注释。我不想在用户之间共享现有模型,每个用户都需要自己的。
我怎样才能实现这个目标?使用某种映射表?最好的程序是什么?
这是我当前的数据库上下文:
public class AppDbContext : IdentityDbContext<AppUser, IdentityRole, string>
{
public DbSet<Book> Books { get; set; }
public DbSet<Chapter> Chapters { get; set; }
public DbSet<Page> Pages { get; set; }
public AppDbContext(DbContextOptions options)
: base(options)
{
}
}
一个
Book
包含很多Chapters
,一章包含很多Pages
。
我有这些模型类:
public class Book
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
[Required]
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public decimal Price { get; set; } = decimal.Zero;
public ICollection<Chapter> Chapters { get; set; } = new List<Chapter>();
}
public class Chapter
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
[Required]
public string Title { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public ICollection<Page>? Pages { get; set; } = new List<Page>();
[ForeignKey("BookId")]
public string BookId { get; set; }
public Book Book { get; set; }
}
public class Page
{
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
public int Number { get; set; } = 0;
public string Notes { get; set; } = string.Empty;
[ForeignKey("ChapterId")]
public string ChapterId { get; set; }
public Chapter Chapter { get; set; }
}
任何指导表示赞赏!我不知道如何为每个用户(我正在使用 MS Identity
AppUser
)提供他们自己的这些书籍对象的副本。因此,如果用户 1 标记章节或页面 IsCompleted=true
,用户 2 不会受到影响。
类似的关系被称为多对多关系,您可以在其中存储该关系的特定详细信息。例如,如果您有一本书、章节和页面作为可以与用户关联的数据结构,并且您希望每个用户都可以填充每个级别上的注释字段之类的内容:
public class UserBooks
{
public virtual User User { get; set; }
public virtual Book Book { get; set; }
public string? Notes { get; set; }
public bool IsComplete { get; set; } = false;
public virtual ICollection<UserChapter> UserChapters { get; protected set; } = new List<UserChapter>();
}
public class UserChapter
{
public virtual User User { get; set; }
public virtual Chapter Chapter { get; set; }
public string? Notes { get; set; }
public bool IsComplete { get; set; } = false;
public virtual ICollection<UserPage> UserPages { get; protected set; } = new List<UserPage>();
}
public class UserPages
{
public virtual User User { get; set; }
public virtual Page Page { get; set; }
public string? Notes { get; set; }
}
因此,在您的 User 类中,您将拥有 UserBook 实体的集合,而不是 Books 的集合。如果您想将一本书关联到一个用户,而不是:
user.Books.Add(book);
你会使用:
user.UserBooks.Add(new UserBook(book));
或者更好的是,在 User 上创建一个 AddBook() 方法来处理为关系创建 UserBook。用户不会拥有书籍的集合,而是用户书籍。 UserBooks 包含与用户关联的书籍参考,还包含特定于该用户和书籍组合的任何字段,例如用户想要对书籍进行的任何注释。如果您想访问书籍的具体详细信息,您可以通过 UserBook.Book 参考来访问这些详细信息。该 Book 实体仍然保留章节和页面的基本导航属性。
处理 UserChapter 和 UserPages 可能会有点棘手。创建 UserBook 时,您可以选择为书中的每个章节和页面创建 UserChapter 和 UserPage,但很可能您只想在用户实际记录笔记或将某些内容标记为完成时才为章节或页面创建这些内容。在这种情况下,您可以使用类似
FirstOrDefault()
的内容来查找是否为给定章节或页面定义了 UserChapter 或 UserPage 记录,并在用户想要记录某些内容时创建一个记录。