带有 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&lt;Book&gt; 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 集合映射

实体框架探查器 - 带有 EF 6 的 ASP.NET MVC4 - 无法确定提供程序名称

如何仅保存/更新父实体而不将其子实体保存在 asp.net mvc 的 EF6 中?