Лучший совет по реализации REST API для сущностей с дизайном модели Table Per Hierarchy (MVCCore + EF 2.2) - PullRequest
0 голосов
/ 07 февраля 2019

У меня есть пара производных классов Shippable и Downloadable, наследующих один и тот же базовый класс Product, и у каждого из них есть свои свойства:

    public abstract class Product : Entity<Guid>
    {
        public ProductType ProductType{ get; set; }

        public string Name { get; set; }
    }

    public class Downloadable : Product
    {
        public Guid DownloadId { get; set; }
    }

    public class Shippable : Product
    {
        public Guid ShippingInfo { get; set; }
    }

Я использовал EF Core TBH design дляМой DataTable, поэтому все свойства этих сущностей хранятся в таблице:

            builder.Entity<Product>(
                b =>
                {
                    b.ToTable(
                        options.TablePrefix + "Products",
                        options.Schema
                    );

                    b.HasKey(
                        x => x.Id
                    );

                    b.HasDiscriminator<ProductType>(
                         nameof(Product.ProductType)
                     )
                     .HasValue<Downloadable>(
                         ProductType.Downloadable
                     )
                     .HasValue<Shippable>(
                         ProductType.Shippable
                     );
                }

Мой проект - NLayered DDD, поэтому у меня есть прикладной уровень, который создает бизнес-логику для методов UI / REST API и содержит службы приложений и DTO.

Мой вопрос: какова лучшая практика для применения этого?Что вы думаете об этих параметрах:

1- Бизнес-сервисы на производный класс с производными DTO

2- Только одна служба, которая может обслуживать все с общим DTO (содержит обнуляемые свойства производных классов

3- Ваши предложения

Заранее спасибо.

1 Ответ

0 голосов
/ 07 февраля 2019

Я не совсем уверен, что вы ищете, но с точки зрения API, я бы использовал абстрактный контроллер продукта, а затем вывел бы контроллер для каждого конкретного типа продукта из этого:

[Route("api/[controller]")]
[ApiController]
public abstract class ProductController<TProduct, TProductDTO> : ControllerBase
    where TProduct : Product, new()
    where TProductDTO : class, new()
{
}

public class DownloadableController : ProductController<Downloadable, DownloadableDTO>
{
}

public class ShippableController : ProductController<Shippable, ShippableDTO>
{
}

Затем вы строите все конечные точки на своем абстрактном контроллере продукта, используя универсальные типы TProduct и TProductDTO.Например, у вас может быть что-то вроде:

[HttpPost("")]
public async Task<ActionResult<TProductResource>> Create(TProductDTO dto)
{
    var product = _mapper.Map<TProduct>(dto);
    _context.Add(product);
    await _context.SaveChangesAsync();
    return CreatedAt("Get", new { product.Id }, _mapper.Map<TProductDTO>(product));
}

Из-за универсальных типов этот же метод работает для всех производных контроллеров, без необходимости переопределения или даже переопределения, хотя вы можете разрешить его переопределить с помощьюдобавив ключевое слово virtual.Как правило, лучше добавлять методы-заполнители.Например, вы можете сделать что-то вроде:

private virtual Task BeforeCreateAsync(TProduct product, TProductDTO dto) =>

Task.CompletedTask;

private virtual Task AfterCreateAsync(TProduct product, TProductDTO dto) =>

Task.CompletedTask;

И затем оберните свой вызов SaveChangesAsync:

_context.Add(product);
await BeforeCreateAsync(product, dto);
await _context.SaveChangesAsync();
await AfterCreateAsync(product, dto);

Затем, в ваших производных контроллерах, вы можете переопределить их для заглушки с дополнительными функциями:

private override async Task BeforeCreateAsync(Downloadable product, DownloadableDTO dto)
{
    // do something specific to downloadable products
}

Таким образом, большая часть вашей логики остается автономной,Вы можете добавить столько методов-заполнителей, сколько имеет смысл для вашего приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...