带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何
Posted
技术标签:
【中文标题】带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何【英文标题】:ASP.Net core Web Api with EF Core Update entity howto 【发布时间】:2017-03-17 08:41:47 【问题描述】:不是重复的:我的 Update() 方法需要两个参数:id 和修改的实体,并且为我的问题提供的答案有不同的方法,例如 CurrentValues
,现有问题中没有涉及。
我是 ASP.Net 核心开发的新手。我正在使用 mysql 作为数据库和 Book 模型构建一个简单的 API。
我的控制器如下所示:
[Route("api/[controller]")]
public class BooksController : Controller
private readonly IBookRepository _books;
public BooksController(IBookRepository books)
_books = books;
[HttpGet("")]
public IActionResult GetAllBooks()
try
List<Book> books = _books.GetAllBooks();
return Ok(books);
catch(EntityNotFoundException<Book>)
return NotFound();
[HttpGet("id")]
public IActionResult GetBook(long id)
Book book = _books.GetBook(id);
if (book == null)
return NotFound();
return Ok(book);
[HttpPost]
public IActionResult CreateBook([FromBody] Book book)
if (ModelState.IsValid == false)
return BadRequest(ModelState);
Book createdBook = _books.CreateBook(book);
if (createdBook == null)
return NotFound();
return CreatedAtAction(
nameof(GetBook), new id = createdBook.Id , createdBook);
[HttpPut("id")]
public IActionResult UpdateBook(long id, [FromBody] Book book)
if (ModelState.IsValid == false)
return BadRequest(ModelState);
try
_books.UpdateBook(id, book);
return Ok();
catch (EntityNotFoundException<Book>)
return NotFound();
[HttpDelete("id")]
public IActionResult DeleteBook(long id)
_books.DeleteBook(id);
return Ok();
和存储库如下:
public class BookRepository: IBookRepository
private readonly WebAPIDataContext _db;
public BookRepository(WebAPIDataContext db)
_db = db;
public Book CreateBook(Book book)
_db.Books.Add(book);
_db.SaveChanges();
return book;
public void DeleteBook(long id)
Book book = GetBook(id);
if (book != null)
_db.Books.Remove(book);
_db.SaveChanges();
public List<Book> GetAllBooks()
return _db.Books.AsNoTracking().ToList();
public Book GetBook(long id)
return _db.Books.FirstOrDefault(o => o.Id == id);
public void UpdateBook(long id, Book book)
public interface IBookRepository
List<Book> GetAllBooks();
Book GetBook(long id);
Book CreateBook(Book book);
void UpdateBook(long id, Book book);
void DeleteBook(long id);
我不确定如何在我的 Repo 类中编写 UpdateBook
方法。有人可以帮我吗?我看到的所有教程都是在 UpdateBook() 方法中使用单个 id 参数,我基本上是在发布一个 json 对象以及实体 id。
【问题讨论】:
How to update record using Entity Framework 6?的可能重复 它并不完全重复,因为我的 Update 方法需要两个参数 wiz id 和修改后的 Entity,我没有找到任何可以像这样更新的教程或博客文章。我认为更新整个实体比一个一个更新它的所有属性更方便 其次,它说“可能重复”,如果您查看该帖子,它清楚地显示使用 id 从数据库中获取实体,然后从您要更新的属性中设置其属性,然后保存回来进入数据库。如果您发布一个 json 对象并不重要,在 dataAccess 级别/存储库层它只是一个 POCO 对象。 【参考方案1】:试试这个
public void UpdateBook(long id, Book book)
var originalBook= _db.Books.FirstOrDefault(o => o.Id == id);
_db.Entry(originalBook).CurrentValues.SetValues(book);
_db.SaveChanges();
请注意,您必须使用 EFcore 1.1 版才能正常工作
【讨论】:
它说EntityEntry<Book> doesn't contain a definition for CurrentValues
当我鼠标悬停时也没有什么可以导入
似乎 CurrentValues 方法还没有在 .net core 中实现,如果你愿意你可以使用这个(***.com/questions/36369233/…) 扩展方法
好的,但它不会破坏任何其他依赖关系,对吧?我对 ASP.net 核心开发完全陌生,这是我的第一次尝试!
我有这样的:“Microsoft.EntityFrameworkCore”:“1.0.0”,“MySql.Data.Core”:“7.0.4-IR-191”,“MySql.Data.EntityFrameworkCore” : "7.0.6-IR31",
将其设为 "Microsoft.EntityFrameworkCore": "1.1.0" 并运行恢复包【参考方案2】:
最简单的方法是从数据库中加载书籍。更新字段并将更改保存到数据库。
Book existingBook = GetBook(id);
existingBook.Title = book.Title;
// other properties
_db.SaveChanges();
【讨论】:
有没有办法以某种方式将获取的实体根据 id 直接映射到接收到的实体?因为不一定所有字段都会更新。 您可以使用 AutoMapper 来映射字段。 这个答案有效,但是我很想知道_db.Entry(originalBook).CurrentValues.SetValues(book);
在这种情况下如何工作,因为它消除了在更新时记住和指定属性的需要
@Nitish 我相信应该有办法将您的新实体附加到更改后的上下文中,这样您就可以避免先加载对象。我会努力找到的。【参考方案3】:
我认为Update 方法应该做你想做的事。高级思想是附加实体并将其状态设置为修改,这正是 Update 方法所做的。
// Make sure that Book id is set correctly.
book.Id = id;
_db.Books.Update(book);
_db.SaveChanges();
【讨论】:
以上是关于带有 EF Core 更新实体的 ASP.Net 核心 Web Api 如何的主要内容,如果未能解决你的问题,请参考以下文章
在 ASP.NET Core Web API 中使用 Linq 避免实体重复
带有 EF Core / ASP.NET Core 的 OData - 好还是坏?
带有 EF Core 和 CosmosDB .NET 5 的 ASP.Net Core - IdentityRole 问题
带有 EF Core 的 ASP.NET Core - DTO 集合映射