C# 为实体实施RESTAPI的最佳建议,即按照层次结构模型设计表(MVCCore+EF 2.2)
我从同一个基类产品继承了两个派生类,它们都有自己的属性:C# 为实体实施RESTAPI的最佳建议,即按照层次结构模型设计表(MVCCore+EF 2.2),c#,asp.net-core,asp.net-core-webapi,dto,table-per-hierarchy,C#,Asp.net Core,Asp.net Core Webapi,Dto,Table Per Hierarchy,我从同一个基类产品继承了两个派生类,它们都有自己的属性: public abstract class Product : Entity<Guid> { public ProductType ProductType{ get; set; } public string Name { get; set; } } public class Downloadable : Product { publi
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; }
}
我对我的DataTable使用了EF Core TBH设计,因此该实体的所有属性都存储在一个表中:
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
);
}
我的项目是nlayereddd,因此我有一个应用层,它为UI/restapi方法生成业务逻辑,并包含应用程序服务和dto
我的问题是什么是应用这个的最佳实践。您对此选项的看法:
1-具有派生DTO的每个派生类的业务服务
2-只有一个服务可以为所有共享DTO服务,该服务包含派生类的可空属性
3-你的建议
提前感谢。我不完全确定您在寻找什么,但从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>
{
}
由于泛型类型,此方法适用于所有派生控制器,无需重新定义甚至重写,尽管您可以通过添加virtual关键字来允许重写。不过,通常最好添加占位符方法。例如,您可以执行以下操作:
[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));
}
private virtual Task BeforeCreateAsync(TProduct product, TProductDTO dto) =>
Task.CompletedTask
private virtual Task AfterCreateAsync(TProduct product, TProductDTO dto) =>
Task.CompletedTask
private virtual Task AfterCreateAsync(TProduct product, TProductDTO dto) =>
然后包装您的SaveChangesSync调用:
然后,在衍生控制器中,您可以覆盖这些以插入其他功能:
private override async Task BeforeCreateAsync(Downloadable product, DownloadableDTO dto)
{
// do something specific to downloadable products
}
这样,您的大部分逻辑仍然是独立的。您可以添加对应用程序有意义的尽可能多的占位符方法