【问题标题】:Entity Framework core: Relation with two not primary keys实体框架核心:与两个非主键的关系
【发布时间】:2020-04-17 17:45:08
【问题描述】:

我正在处理一个无法更改数据库的旧项目,我正在使用 .net core 3 创建一个新 API。

我有两个表 pageNote 有共同的 PageIdBookId,因此每个 Note 都有一个具有相同 BookId 和 PageId 的页面

public class Note
{
   public int Id { get; set; }
   public int BookId { get; set; }
   public int PageId { get; set; }
   public string Text { get; set; }
}

public class Page
{
   [Key]
   public int MainId { get; set; } // this is the primary key
   public int BookId { get; set; }
   public int PageId { get; set; }
   public string Content { get; set; }
}

PageId 不是 Page 的主键并且具有重复值。 我想通过note id来获取页面,我是这样做的:

 [HttpGet("{id}")]
 public async Task<ActionResult> GetPageByNoteId(int noteId)
 {
        var note = await db.Notes.FindAsync(id);
        var page = await db.Pages.Where(x => x.BookId == note.BookId && x.PageId == note.PageId)
                                 .FirstOrDefaultAsync();

        return Ok(new {note,page});
 }

有没有办法通过一次数据库命中来做到这一点?


更新:

页面的主键是MainId,但它应该是PageIdBookId,但我不能对数据库进行更改,如果我可以对数据库进行更改,我将对页面表进行以下操作:

  • 删除MainId

  • PageIdBookId 设为主键

那么我可以这样做:

      modelBuilder.Entity<Note>(entity =>
       {
                   entity.HasOne(Note => Note.Page)
                         .WithOne(page => page.Note)
                         .HasForeignKey<Note>(note => new { note.PageId, note.BookId});

       });

【问题讨论】:

    标签: c# .net-core entity-framework-core


    【解决方案1】:

    也许这就是你要找的。​​p>

      public class Note
        {
            public int Id { get; set; }
            public int BookId { get; set; }
            public int PageId { get; set; }
            public string Text { get; set; }
            public Page Page { get; set; }
        }
    
        public class Page
        {
            public int Id { get; set; }
            public int BookId { get; set; }
            public int PageId { get; set; }
            public string Content { get; set; }
            public Note Note { get; set; }
        }
    

    在您的 DB Context 类中。

      protected override void OnModelCreating(ModelBuilder builder)
                {
                    base.OnModelCreating(builder);
    ...
             builder.Entity<Note>()
                .HasOne(r => r.Page)
                .WithOne(x => x.Note);
    

    现在你可以像下面那样做。

     var page = (await _context.Notes.Include(x => x.Page)
                                              .FirstOrDefaultAsync(x => x.Id == id)).Page;
    

    此解决方案适用于从注释到页面的一对一关系。如果是 1 到 5 月,您可以将 Pages 属性更改为集合。

    【讨论】:

    • 您忽略了BookId,正如我提到的,每个注释都通过两个键(BookId,PageId)与一页相关。假设我想获取 BookId = 1 和 PageId = 1 的笔记的页面,但还有另一个 BookId = 3 和 PageId = 1 的笔记,你的答案将得到所有这些,我必须得到一个BookId = 1 在客户端。 Page 表中具有相同 pageId 的记录过多。
    • 我注意到你说的是笔记和页面之间的一对一关系,所以我更新了答案
    • @timabweini 我仍然没有得到完整的上下文。让我再问你一个问题。你是如何创建模型的。从您的问题来看,您似乎使用的是数据库优先方法。这意味着这些模型是 EF 的自动脚手架。如果您在问题中列出的模型在您的项目中也完全相同。这个表在 OnModelCreating 方法中是什么关系?
    猜你喜欢
    • 2020-07-08
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    相关资源
    最近更新 更多