在实体框架中修改类时更新桥接表

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

当我离开实体框架来自动管理我的映射时,我似乎无法更新我的桥接表。

课程:

public class Tool
{
     public Guid Id { get; set; }
     public string Name { get; set; } = string.Empty; 
     public List<TargetType> TargetTypes { get; } = [];
}

public class TargetType
{
    public Guid Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public List<Tool> Tools { get; } = [];
}

当我进入“编辑/工具”页面时,我希望能够更改与工具关联的

TargetTypes

代码在调试时似乎工作正常 - 我在视图中加载所有目标类型,用户可以选择它们,然后按保存按钮。但是,桥接表中没有添加任何内容。实体框架表示它会在本文中自动处理所有这些,因此我真的不想创建自定义类。

为什么我的数据库中的桥接表没有更新?

特性:

[BindProperty]
public Tool Tool { get; set; }

[BindProperty]
public List<Target> Targets { get; set; } = new List<Target>();
[BindProperty]
public List<Guid> SelectedTargetTypes { get; set; } = new List<Guid>();
[BindProperty]
public List<SelectListItem> TargetTypesList { get; set; } = new List<SelectListItem>();

OnPost
方法:

public async Task<IActionResult> OnPostAsync()
{
    // we want to update the tool options here
    if (!ModelState.IsValid)
    {
        return Page();
    }

    // Handle the target types
    foreach (var type in SelectedTargetTypes)
    {
        var target = await _context.TargetTypes.FindAsync(type);

        if (target != null)
        {
            Tool.TargetTypes.Add(target);
        }
    }

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

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

    return RedirectToPage("./Index");
}

.cshtml
我的观点:

<div class="container">
    <form method="post">

        <h3>Tool Settings</h3>
        <hr />
        <div class="container">
            <div class="form-group col-md-6">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <input type="hidden" asp-for="Tool.Id" />
                <label asp-for="Tool.Name" class="control-label"></label>
                <input asp-for="Tool.Name" class="form-control" />
                <span asp-validation-for="Tool.Name" class="text-danger"></span>
            </div>
            <div class="form-group col-md-6">
                <label asp-for="Tool.Description" class="control-label"></label>
                <input asp-for="Tool.Description" class="form-control" />
                <span asp-validation-for="Tool.Description" class="text-danger"></span>
                <label asp-for="Tool.ToolType" class="control-label"></label>
                <select id="ToolTypeSelect" class="form-control" asp-items="Html.GetEnumSelectList<AttackSurfaceReview.ASRData.Model.ToolType>()"></select>
                <span asp-validation-for="Tool.ToolType" class="text-danger"></span>
            </div>
            <div class="form-group" style="margin-bottom: 10px;">
                <div class="col-md-12">
                    <label asp-for="Tool.ImageUrl" class="control-label"></label>
                    <input asp-for="Tool.ImageUrl" class="form-control" />
                    <span asp-validation-for="Tool.ImageUrl" class="text-danger"></span>
                </div>
            </div>
            <label class="control-label">Allowed Targets</label>
            @foreach (var targetType in Model.TargetTypesList)
            {
                <div class="form-check form-switch">
                    <input name="SelectedTargetTypes" class="form-check-input" type="checkbox" value="@targetType.Value" />
                    <label class="form-check-label">@targetType.Text</label>
                </div>
            }
            <div class="form-group">
                <input style="margin-bottom: 10px;" type="submit" value="Save" class="btn col-md-4 btn-primary" />
            </div>
        </div>
    </form>
</div>
c# entity-framework asp.net-core razor
1个回答
0
投票

其实这和EF core如何处理关系实体有关。

默认情况下,

var target = await _context.TargetTypes.FindAsync(type);
它不会跟踪关系实体工具。

如果还想更新该工具,您应该从上下文已跟踪的实体的导航属性中引用新实体,然后该实体将被发现并插入到数据库中。

更多详情,可以参考以下代码:

    var target = await _context.TargetTypes.Include(b => b.Tools).FindAsync(type);

    if (target != null)
    {
        Tool.TargetTypes.Add(target);
    }

这与在添加 TargetTypes 之前放置

_context.Attach(Tool).State = EntityState.Modified;
相同。

更多详情,你可以参考这篇文章和这个文档

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