2016-12-26 65 views
0

您能否幫我解決我的代碼問題?錯誤「發生了參照完整性約束違規」

我有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東西,但也許我做錯了什麼,但什麼都沒有改變。

+1

這可能不是問題,但我認爲在您的編輯動作中,您應該查詢Book的'Id',而不是'AuthorId':'Book bookEdit = dbBooks.Books.Include(a => a.Author)。 Where(a => a.Id == id).Single();' – Marc

回答

0

那麼,你無法修改Book的編輯器視圖中的AuthorName。您需要其他視圖供作者修改它。

book.Author - 不能是null,因爲它的導航屬性,只能像readonly模式。因此,只要刪除editormodel爲author.authorname

修改書單:

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

謝謝!但仍不明白如何實現作者姓名(來自模型作者)和書籍模型的標題,年份等editin ... – di0nise4ka

0

看看你需要做什麼,我得到了現在。您只需要所有作者的選擇列表,並且在視圖名稱中將自動選擇AuthorId書籍的字段。 結交新一種形式,組

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

也許你可以幫助這個請嗎?