好的,首先我的实际书籍和作者对象定义:
public class Book
{
[Key]
public virtual int BookID { get; set; }
[Required]
[DataType(DataType.Text)]
[MaxLength(100)]
public virtual String Title { get; set; }
[DataType(DataType.MultilineText)]
public virtual String Abstract { get; set; }
[RegularExpression(@"\d{4}")]
public virtual String Year { get; set; }
[Required]
[Display(Name="Genre")]
public virtual int GenreID { get; set; }
public virtual Genre Genre { get; set; }
public virtual List<Author> Authors { get; set; }
public Book()
{
Authors = new List<Author>();
}
}
public class Genre
{
[Key]
public virtual int GenreID { get; set; }
[Required]
[DataType(DataType.Text)]
[MaxLength(30)]
public virtual String Name { get; set; }
public virtual List<Book> Books { get; set; }
}
public class Author
{
[Key]
public virtual int AuthorID { get; set; }
[Required]
[DataType(DataType.Text)]
[MaxLength(50)]
public virtual String Firstname { get; set; }
[Required]
[DataType(DataType.Text)]
[MaxLength(50)]
public virtual String Lastname { get; set; }
public virtual List<Book> Books { get; set; }
public Author()
{
Books = new List<Book>();
}
[NotMapped]
public string Fullname
{
get { return String.Format("{0}, {1}", Lastname, Firstname); }
}
public override string ToString()
{
return Fullname;
}
}
使用 EF-Migrations 我得到一个 configuration.cs 文件,我在其中输入了我的 Data-Seed,然后使用 add-migration 进行第一次迁移以初始化数据库 EF 正确创建相应的表 Authors、Books、Genres 和最后但并非最不重要的AuthorBooks 保存书籍和作者之间的多对多关系。
到目前为止,我的整个演示应用程序都在工作。我唯一的问题是实体框架似乎拒绝保存 AuthorBooks 关系。我已经设置了我的应用程序,以便在书籍创建/编辑时我可以通过 MultiSelectList-ListBox 选择相关的作者。
书控制器视图模型:
public class BookControllerViewModel
{
public Book actualBook { get; set; }
public String redirectUrl { get; set; }
public MultiSelectList Authors { get; set; }
public int[] AuthorIDs { get; set; }
public SelectList Genres { get; set; }
}
ViewModel包含受创建/编辑操作约束的书籍,这是基于本书的正确选择INFO的多电机列表,我添加了INT []权威以保留用户将在Create listbox中选择的选择IDS /编辑视图。
@model BookStoreInternet.ViewModels.BookControllerViewModel
<div class="editor-label">
@Html.LabelFor(model => model.actualBook.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.actualBook.Title)
@Html.ValidationMessageFor(model => model.actualBook.Title)
</div>
<div class="editor-label">
<label>Author@( Model.actualBook.Authors.Count > 1 ? "s" :"" )</label>
</div>
<div class="editor-field">
@Html.ListBox("AuthorIDs", Model.Authors)
@Html.ValidationMessageFor(model => model.actualBook.Authors)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.actualBook.Abstract)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.actualBook.Abstract)
@Html.ValidationMessageFor(model => model.actualBook.Abstract)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.actualBook.Year)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.actualBook.Year)
@Html.ValidationMessageFor(model => model.actualBook.Year)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.actualBook.GenreID, "Genre")
</div>
<div class="editor-field">
@Html.DropDownList("actualBook.GenreID", Model.Genres)
@Html.ValidationMessageFor(model => model.actualBook.GenreID)
</div>
这也很有效,因为发布到控制器动作的 ViewModel
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(BookControllerViewModel bookVM)
{
if (ModelState.IsValid)
{
bookVM.actualBook.Authors = db.Authors.Where(x => bookVM.AuthorIDs.Contains(x.AuthorID)).ToList();
db.Entry(bookVM.actualBook).State = EntityState.Modified;
db.SaveChanges();
return Redirect(bookVM.redirectUrl);
}
bookVM.Authors = new MultiSelectList(db.Authors, "AuthorID", "Fullname", bookVM.actualBook.Authors.Select(x => x.AuthorID));
bookVM.Genres = new SelectList(db.Genres, "GenreID", "Name", bookVM.actualBook.GenreID);
return View(bookVM);
}
正确填充了我期望的值。但不起作用的是 db.SaveChanges() 似乎“默默地”拒绝保存我添加到书中的作者。调试操作我可以看到 bookVM.ActualBook.Authors 实际上设置正确并包含选定的作者......但未创建可连接 AuthorBooks 的相应条目......
有人知道为什么这不起作用,甚至可能如何使它起作用吗?
提前致谢!
Thanks to Gerts answers I got this working by modifying the Controller-Action to
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(BookControllerViewModel bookVM)
{
if (ModelState.IsValid)
{
var book = db.Books.Find(bookVM.actualBook.BookID);
book.Update(bookVM.actualBook);
book.Authors.Clear();
foreach(var aid in bookVM.AuthorIDs)
book.Authors.Add(db.Authors.Find(aid));
db.SaveChanges();
return Redirect(bookVM.redirectUrl);
}
bookVM.Authors = new MultiSelectList(db.Authors, "AuthorID", "Fullname", bookVM.actualBook.Authors.Select(x => x.AuthorID));
bookVM.Genres = new SelectList(db.Genres, "GenreID", "Name", bookVM.actualBook.GenreID);
return View(bookVM);
}
and adding a method to the Book model
internal void Update(Book book)
{
Title = book.Title;
Abstract = book.Abstract;
Year = book.Year;
GenreID = book.GenreID;
}
Thanks again to Gert!