简体   繁体   中英

EF Insert Child to specific Parent

I have been searching all over the place, found many questions but neither of them answer my.

Thing I am trying to do is simple, let's say we have something like that:

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 takes care of creating db and via scaffolding I get controllers and views. Everything works fine, I can create Parent. I can also create Child with ParentID chosen from drop down.

What I really want to do is remove drop down and pass ParentID as parameter like that:

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

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

And in view we got this:

<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>

When submitting this I got "Cannot insert explicit value for identity column in table 'Children' when IDENTITY_INSERT is set to OFF." Now I looked all over the place and tried various attributes yet still I can't get this to work.

I will be grateful for any sort of help.


Update

Create method from controller:

    [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);
    }

Just to show more about problem. Here I am using default scaffolded version with select control in view.

    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();
    }

After talking with people in comments I start to think that problem is caused by a bug in EF Core but I think I have found 'dirty' work around.

Here is Child model:

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; }
}

Now (for some reason) this solves "Cannot insert explicit value for identity column in table 'Children' when IDENTITY_INSERT is set to OFF." issue but creates new, we don't get unique id. I fixed that by making it myself, here is create method:

    [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);
    }

Now doWhile makes sure that we don't assign the same id to two different objects. Alternatives to Random option are to use Guid (when id is string) or GetHashCode (and increment in case of collision perhaps).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM