如何在Controller内部的一种方法中实现HTTP Post创建/更新? .NET API

时间:2018-10-10 05:58:51

标签: c# entity-framework api post .net-core

我问自己如何在Controller中使用HTTP Post实现一种方法来创建/更新实体?尤其是如果已经存在具有给定主键的实体并且我只想更新某些实体属性该怎么办?

目前,我正在使用两种方法,一种用于创建POST,另一种用于更新的PUT。

简化的ControllerCode(省略了错误处理和模型验证):

[HttpPost]
    public IActionResult Create([FromBody] Dto[] dtos) 
    {
      foreach(DTO d in dtos){
          _repo.Create(d);
      }
      _repo.Save();
      return StatusCode(201);
    }

[HttpPut]
    public IActionResult Update([FromBody] Dto[] dtos)
    {
      foreach(d in dtos) {
        _repo.Update(d);
      }
      _repo.Save();
      return StatusCode(201);
    }

我找不到此问题的特定主题。 我不想做的是先读法,这样您总是必须在Context中检查是否已经存在用于更新属性的给定实体(相同主键)。
请参阅此Microsoft链接:https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/crud?view=aspnetcore-2.0#update-the-edit-page

在Entity Framework 5中,有一个称为AddOrUpdate的方法,但是在EF Core中不再可用。

您有一些想法或有用的链接如何实施?

非常感谢! :)

1 个答案:

答案 0 :(得分:0)

解决方案的想法来自: https://www.michaelgmccarthy.com/2016/08/24/entity-framework-addorupdate-is-a-destructive-operation/

此解决方案是使用RepositoryPattern和泛型的示例:

RepositoryBase:

public abstract class RepositoryBase<T> : IRepositoryBase<T> where T : class
{
    protected RepositoryContext RepositoryContext { get; set; }

    public RepositoryBase(RepositoryContext repositoryContext)
    {
        this.RepositoryContext = repositoryContext;
    } 

    // Implements CreateOrUpdate in one function watching the State of an entity
    public void AddOrUpdate(T entity)
    {
        var entry = this.RepositoryContext.Entry(entity);

        switch (entry.State)
        {
            case EntityState.Detached:
                this.RepositoryContext.Set<T>().Add(entity);
                break;
            case EntityState.Modified:
                this.RepositoryContext.Set<T>().Update(entity);
                break;
            case EntityState.Added:
                this.RepositoryContext.Set<T>().Add(entity);
                break;
            case EntityState.Unchanged:
                //item already in db no need to do anything  
                break;

            default:
                throw new ArgumentOutOfRangeException();
        }
    }
}

控制器:

public class SomeController : Controller
{
    private readonly RepositoryContext _repo;

    public SomeController(SomeRepository someRepo)
    {
        _repo = someRepo;
    }

    [HttpPost]
    public IActionResult CreateOrUpdate([FromBody] SomeType type)
    {
        try
        {
            // using CreateOrUpdate method makes it necessary to check for existance
            SomeType checkIfExists = _repo.GetById(type.id);

            if(checkIfExists != null)
            {
                // Do some stuff with object
                // ...
                _repo.CreateOrupdate(checkIfExists);
            }
            else 
            {
                checkIfExists = new SomeType();
                // Do some stuff
                _repo.CreateOrupdate(checkIfExists);
            }

            _repo.SaveChanges();
            return StatusCode(201);
        }
        catch(Exception ex)
        {
            return StatusCode(500, "Internal Server Error");
        }
    }
}