【问题标题】:EF Insert Child to specific ParentEF将子项插入特定的父项
【发布时间】:2016-09-08 16:57:02
【问题描述】:

我一直在到处寻找,发现了很多问题,但他们都没有回答我的问题。

我想做的事情很简单,假设我们有这样的事情:

public class Parent
{
    public int ID { get; set; }

    public List<Child> Children { get; set; }
}

public class Child
{
    public int ID { get; set; }

    public int ParentID { get; set; }
    public Parent Parent { get; set; }
}

EF 负责创建数据库并通过脚手架获得控制器和视图。一切正常,我可以创建父级。我还可以使用从下拉列表中选择的 ParentID 创建 Child。

我真正想做的是删除下拉菜单并将 ParentID 作为参数传递:

    public IActionResult Create(int id)
    {
        if (id == 0)
        {
            return NotFound();
        }

        ViewData["ID"] = id; //that a ParentID
        return View();
    }

我们得到了这个:

<form asp-action="Create">
    <div class="form-horizontal">
        <h4>Child</h4>
        <hr />
        <div asp-validation-summary="ModelOnly" class="text-danger"></div>
        <input type="hidden" asp-for="ParentID" value=@ViewData["ID"] />
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
</form>

提交时,我得到“当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'Children' 中插入标识列的显式值。”现在我环顾四周并尝试了各种属性,但仍然无法正常工作。

我将不胜感激。


更新

从控制器创建方法:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("ID,ParentID")] Child child)
    {
        if (ModelState.IsValid)
        {
            _context.Add(child);
            await _context.SaveChangesAsync();
            return RedirectToAction("Index");
        }
        return View(book);
    }

只是为了展示更多关于问题的信息。这里我使用默认的脚手架版本,视图中带有选择控件。

    public IActionResult Create(int id)
    {
        if (id == 0)
        {
            return NotFound();
        }

        ViewData["ParentID"] = new SelectList(_context.Parents.Where(x => x.ID == 1), "ID", "ID"); //Works
        ViewData["ParentID"] = new SelectList(_context.Parents.Where(x => x.ID == id), "ID", "ID"); // Doesn't work
        return View();
    }

【问题讨论】:

  • 您能发布构成实际Child 对象的代码吗?该错误似乎表明您正在尝试为 EF 标记为标识列的字段显式设置值。除非它的脚手架不正确,否则ParentID 不应该是Child 中的Identity
  • @stephen.vakil 谢谢你的回复,明天我会上班,我可以发布它,但除了我展示的内容外,我没有改变任何东西。它在“await _context.SaveChangesAsync();”这一行抛出异常。
  • 将 parentID 存储为隐藏在表单内的视图中,这样它将与帖子一起返回
  • @HadiHassan 我不明白......我想我已经这样做了,参数很好地进入控制器,通过模型验证并在保存对数据库的更改时抛出异常。
  • 我没有仔细看你的问题细节,ID字段是否标记为DatabaseGenerated as Identity?

标签: c# entity-framework asp.net-core entity-framework-core identity-insert


【解决方案1】:

在与 cmets 中的人交谈后,我开始认为问题是由 EF Core 中的错误引起的,但我认为我发现了“肮脏”的解决方法。

这是子模型:

public class Child
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ID { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ParentID { get; set; }
    [ForeignKey("ParentID")]
    public Parent Parent { get; set; }
}

现在(出于某种原因)这解决了“当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'Children' 中插入标识列的显式值”。问题但创建新的,我们没有得到唯一的ID。我通过自己制作解决了这个问题,这里是创建方法:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("ID,ParentID")] Child child)
    {
        if (ModelState.IsValid)
        {
            int _id;
            do
            {
                _id = new Random().Next();
            } while (await _context.Children.Where(b => b.ID == _id).AnyAsync());

            child.ID = _id;
            _context.Add(child);
            await _context.SaveChangesAsync();
            return RedirectToAction("Index");
        }
        ViewData["ID"] = id;
        return View(child);
    }

现在 doWhile 确保我们不会将相同的 id 分配给两个不同的对象。 Random 选项的替代方案是使用 Guid(当 id 为字符串时)或 GetHashCode(可能在发生冲突时增加)。

【讨论】:

    猜你喜欢
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多