Как реализовать HTTP Post Create / Update в одном методе внутри контроллера?.NET API - PullRequest
0 голосов
/ 10 октября 2018

Я спрашиваю себя, как реализовать один метод внутри контроллера с 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);
    }

Я не могу найти конкретные темы для этой проблемы.То, что я не хочу делать, - это чтение вначале, так что вам всегда нужно проверять в контексте, существует ли уже заданная сущность (тот же первичный ключ) для обновления свойств.
См. Эту ссылку на 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 голосов
/ 10 октября 2018

Идея решения исходит из: https://www.michaelgmccarthy.com/2016/08/24/entity-framework-addorupdate-is-a-destructive-operation/

Это решение является примером использования RepositoryPattern и Generics:

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");
        }
    }
}
...