错误“发生参照完整性约束违规”

时间:2016-12-26 14:06:22

标签: c# asp.net asp.net-mvc

你能帮我解决一下我的代码吗?

我有2个型号:

public class Author
{
    public int Id { get; set; }
    public string AuthorName { get; set; }

    public IEnumerable<Book> Books { get; set; }
}

public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public int YearPublish { get; set; }
    public int Price { get; set; }

    public int? AuthorId { get; set; } //FK
    public Author Author { get; set; } //navigation property
}

尝试制作编辑功能。 控制器代码:

// GET: Books/Edit/5       
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return HttpNotFound();
    }
    Book bookEdit = dbBooks.Books.Include(a => a.Author).Where(a => a.AuthorId == id).Single();
    return View(bookEdit);
}

// POST: Books/Edit/5
[HttpPost]
public ActionResult Edit(Book book)
{
    if (ModelState.IsValid)
    {
        // TODO: Add update logic here
        //book.Author = null; //AuthorName cant be edited
        dbBooks.Entry(book).State = EntityState.Modified;
        dbBooks.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(book);
}

我的观点:

<div class="form-horizontal">
    <h4>Book</h4>
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Id)

    <div class="form-group">
        @Html.LabelFor(model => model.Author.AuthorName, "AuthorName", htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Author.AuthorName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Author.AuthorName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Title, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Title, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Title, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.YearPublish, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.YearPublish, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.YearPublish, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
        </div>
    </div>        

    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Save" class="btn btn-default" />
        </div>
    </div>
</div>

当我尝试单击“保存”按钮时(即使我没有做任何更改)发生错误: 发生参照完整性约束违规:关系一端的“Author.Id”的属性值与另一端的“Book.AuthorId”的属性值不匹配。 错误在dbBooks.Entry(book).State = EntityState.Modified;

如果我尝试添加book.Author = null;,那么它在逻辑上比我的AuthorNames`开始消失......

此外,我试图在Html.HiddenFor中添加一些内容,但也许我做错了什么,但没有任何改变。

3 个答案:

答案 0 :(得分:0)

好吧,你无法在Book的编辑器视图中修改AuthorName。您需要另一个视图供作者修改它。

book.Author - 不能是null,因为它的导航属性只能像只读模式一样。所以只需删除author.authorname

的editormodel

修改过的图书清单:

Book bookEdit = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();

答案 1 :(得分:0)

看看你需要做什么,我现在明白了。您只需要所有作者的selectList,并且在AuthorId book的字段中将自动选择视图名称。 使用

创建一个新的表单组
<div class="form-group">
    @Html.LabelFor(model => model.AuthorId, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
           @(Html.DropDownListFor(p => p.AuthorId, (SelectList)ViewBag.Authors, new { @class = "form-control" }))
        @Html.ValidationMessageFor(model => model.AuthorId, "", new { @class = "text-danger" })
    </div>
</div>

在您的修改操作中:

// GET: Books/Edit/5       
public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return HttpNotFound();
    }
    Book bookEdit = dbBooks.Books.Where(a => a.Id == id).Single();
    // UPDATED
    var list = dbBooks.Books.Select(x => new  { ID = x.Id, AuthorName = x.AuthorName });
    ViewBag.Authors = new SelectList(list, "Id", "AuthorName");
    // UPDATED
    return View(bookEdit);
}

答案 2 :(得分:0)

再次非常感谢!

但是使用DropDownList不允许我编辑作者的名字..但是这个解决方案很好。

我需要修改名称,标题,年份和价格等所有4个字段。

我尝试制作类似复合模型的东西:

public class BookAuthorCompositeModel
{
    public Author author { get; set; }
    public Book book { get; set; }
}

更改我的get方法:

// GET: Books/Edit/5       
    public ActionResult Edit(int? id)
    {
        if (id == null)
        {
            return HttpNotFound();
        }
        var compModel = new BookAuthorCompositeModel();
        compModel.book = dbBooks.Books.ToList().Where(a => a.Id == id).SingleOrDefault();
        compModel.author = dbBooks.Authors.ToList().Where(x => x.Id == id).SingleOrDefault();


        return View(bookEdit);
    }

它显示我需要的所有内容(我点击“编辑”并查看有关名称,标题,年份和价格的信息)。

我的观点是:

    @model BookStorage.Models.BookAuthorCompositeModel

@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Edit</h2>


@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Book</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        @Html.HiddenFor(model => model.book.Id)

        <div class="form-group">
            @Html.LabelFor(model => model.author.AuthorName, "AuthorName", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.author.AuthorName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.author.AuthorName, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.book.Title, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.book.Title, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.book.Title, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.book.YearPublish, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.book.YearPublish, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.book.YearPublish, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.book.Price, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.book.Price, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.book.Price, "", new { @class = "text-danger" })
            </div>
        </div>


        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

但在Post方法中出现了错误:

[HttpPost]
    public ActionResult Edit(Book book)
    {
        if (ModelState.IsValid)
        {
            dbBooks.Entry(BAmodel.book).State = EntityState.Modified;
            dbBooks.Entry(BAmodel.author).State = EntityState.Modified;

            dbBooks.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(book);
    }

dbBooks.SaveChanges();导致错误.. 我认为使用这种ViewModel有助于编辑所有行,但它不会将数据存储到DB ......

也许你可以帮忙吗?