如何与 Razor/Entity Framework 建立 n:1 关系

问题描述 投票:0回答:1

我正在使用 VS 2022 for Mac 17.6。我当前的项目是使用 .NET 7.0 的 Razor Web 应用程序和使用 SQLite 的实体框架。

这就是我想要实现的目标:在我的数据模型中,我有两个表

EventInstance
Note
EventInstance
中的几行与
Note
中的一行相关。每当用户编辑一个
EventInstance
时,对链接的
Note
的更改也应该出现在与同一行相关的所有其他
EventInstances
中。

这是我现在数据模型的一部分:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // ...

    modelBuilder.Entity<EventInstance>()
                .HasOne(i => i.Note)
                .WithMany()
                .HasForeignKey(i => i.NoteId);
}
    
public class EventInstance
{
    public int Id { get; set; }

    [Required]
    [Display(Name = "Spezifikation")]
    public required string Specification { get; set; }

    // ... 

    public int? NoteId { get; set; }
    [Display(Name = "Notiz")]
    public Note? Note { get; set; }

    // ...
}

public class Note
{
    public int Id { get; set; }
    [Display(Name = "Notiz"), DataType(DataType.MultilineText)]
    public string? Content { get; set; }
}

在我的

Create.cshtml.cs
中,一切似乎都运行良好。我已经手动编码了这些行:

Note note = new Note() { Content = "" };

_context.Note.Add(note);
_context.SaveChanges();

int noteId = note.Id;

创建新的

EventInstance
后,我可以在数据库中检查
Event
中是否已添加新行并分配了
Id

这是我现有的 EditModel / PageModel for EventInstance:

public class EditModel : PageModel
{
    private readonly RazorPagesSchedule.Data.ScheduleDbContext _context;

    public EditModel(RazorPagesSchedule.Data.ScheduleDbContext context)
    {
        _context = context;
    }

    [BindProperty]
    public EventInstance EventInstance { get; set; } = default!;

    public async Task<IActionResult> OnGetAsync(int? id)
    {
        if (id == null || _context.EventInstance == null)
        {
            return NotFound();
        }

        var eventinstance = await _context.EventInstance
            .Include(i => i.EventTemplate)
            .Include(i => i.ResponsiblePerson)
            .Include(i => i.Note)
            .FirstOrDefaultAsync(m => m.Id == id);

        if (eventinstance == null)
        {
            return NotFound();
        }
        EventInstance = eventinstance;

        var list = new SelectList(_context.EventTemplate, "Id", "Description").ToList();
        list.Insert(0, new SelectListItem { Text = "--- Keine Aufgabenvorlage ---", Value = "" });
        ViewData["EventTemplateId"] = list;
        var persons = new SelectList(_context.Person.OrderBy(p => p.Sn), "Id", "Sn");
        ViewData["ResponsiblePersonId"] = persons;
        return Page();
    }

    // To protect from overposting attacks, enable the specific properties you want to bind to.
    // For more details, see https://aka.ms/RazorPagesCRUD.
    public async Task<IActionResult> OnPostAsync()
    {
        if (!ModelState.IsValid)
        {
            return Page();
        }

        _context.Attach(EventInstance).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!EventInstanceExists(EventInstance.Id))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return RedirectToPage("./Index");
    }

    private bool EventInstanceExists(int id)
    {
      return (_context.EventInstance?.Any(e => e.Id == id)).GetValueOrDefault();
    }
}

预期行为:编辑事件时,注释中不会创建新行,但应更新现有链接行。

c# entity-framework razor relationship .net-7.0
1个回答
0
投票

我觉得你应该从数据库加载实体并修改它,而不是从客户端逐字获取它,但它创建新注释的原因是你不告诉它它已修改。添加此:

_context.Attach(EventInstance.Note).State = EntityState.Modified;

您还需要表单中的注释 ID:

<input asp-for="@Model.EventInstance.Note.Id" hidden />

请注意,它必须是

Note.Id
而不是
NoteId
,因为后者会尝试保存ID为0的注释,这通常会添加新行,但当设置为
EntityState.Modified
时会崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.