首先:我找到了this post,但我并不完全理解它,所以请不要把它锁定为副本。
我正在尝试使用ViewModel进行编辑操作。
我的问题是由于某种原因adds
一个新的行到桌子而不是editing
它。在我进行测试之前,这一切都已经过去了。
我相信这是我想念的傻事,但我不知道我做错了什么。
如果它有任何区别,我正在使用code-first
我的ViewModel:
public class CreateViewModel
{
public string Title { get; set; }
[Display(Name = "Author")]
public int AuthorId { get; set; }
public DateTime? PublicationDate { get; set; }
public float? Edition { get; set; }
public SelectList Authors { get; set; }
}
我的控制器功能:
// GET: Books/Edit/5
public ViewResult Edit(int? id)
{
if (id == null)
{
return View("Error");
}
Book book = db.Books.FirstOrDefault(a => a.Id == id);
var vm = new CreateViewModel()
{
AuthorId = book.AuthorId,
Authors = new SelectList(db.Authors, "Id", "Name"),
PublicationDate = book.PublicationDate,
Title = book.Title,
Edition = book.Edition
};
if (book == null)
{
return View("Error");
}
return View(vm);
}
// POST: Books/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see https://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CreateViewModel vm)
{
if (ModelState.IsValid)
{
var repo = new EFLibraryRepository();
repo.Save(new Book(){
AuthorId = vm.AuthorId,
PublicationDate = vm.PublicationDate,
Title = vm.Title,
Edition = vm.Edition
});
return RedirectToAction("Index");
}
return View("Edit", vm);
}
我的模拟存储库:
public class EFLibraryRepository : ILibraryRepository
{
AuthorAndBookDbModel db = new AuthorAndBookDbModel();
public IQueryable<Author> Authors { get { return db.Authors; } }
public IQueryable<Book> Books { get { return db.Books; } }
public void Delete(Book book)
{
db.Books.Remove(book);
db.SaveChanges();
}
public void Delete(Author author)
{
db.Authors.Remove(author);
db.SaveChanges();
}
public Book Save(Book book)
{
if (book.Id == 0)
{
db.Books.Add(book);
}
else
{
db.Entry(book).State = System.Data.Entity.EntityState.Modified;
}
db.SaveChanges();
return book;
}
public Author Save(Author author)
{
if (author.Id == 0)
{
db.Authors.Add(author);
}
else
{
db.Entry(author).State = System.Data.Entity.EntityState.Modified;
}
db.SaveChanges();
return author;
}
}
图书馆资料库:
public interface ILibraryRepository
{
IQueryable<Book> Books { get; }
IQueryable<Author> Authors { get; }
Book Save(Book book);
Author Save(Author author);
void Delete(Book book);
void Delete(Author author);
}
在你的POST方法中,你永远不会设置Book的Id
属性的值,所以它总是0
(int
的默认值),所以反过来,你总是执行代码来添加一个新的Book
。
首先需要在视图模型中为id
包含一个属性,以便它的值将在POST方法中绑定。
public class CreateViewModel
{
public int? Id { get; set; } // add this
....
请注意,您不需要在视图中包含隐藏输入,假设您使用默认路由(其值将从表单action
属性中的路由值绑定)。
然后在POST方法中,根据视图模型设置Id
的Book
repo.Save(new Book() {
Id = vm.Id, // add
AuthorId = vm.AuthorId,
....
但是,编辑现有记录时的正确方法是从基于Id
的存储库中获取原始数据模型并更新其属性,例如
Book book = db.Books.FirstOrDefault(a => a.Id == vm.Id);
book.AuthorId = vm.AuthorId;
....
repo.Save(book);
而不是创建一个新的Book
实例。这种方法的一些好处包括
TIMESTAMP
值,如果它们不同,您知道另一个用户在此期间修改了记录(您可能采取不同的操作过程而不是仅覆盖以前的使用更改)