我是ef core开发的新手,在eShopOnWeb上寻找指导。我调整了很多东西,最终得到了一个还能工作的API,只是无法加载相关数据。我已经使用Ardalis.Specification
,但最终无法解决这个问题。最初我根据Ardalis编码,然后在Java Spring
模式中进行了一些调整,并使用了Conrtoller > Service > Repository > Entity
的方法。
在这样的结构中:
.sln
- Controllers
- Core
- Infrastructure
当获取api/Book/
时,我得到这个结果:
[{
"bookId":1,
"title":"Borja On Fleek uD83DuDD25",
"description":"De jung Pirat Borja mischt die 7 Weltmeer uf",
"coverImageUrl":"https://s3.amazonaws.com/[...].png",
"chapters":null,
"bookCategories":null,
"bookTags":null
}]
这很好,因为DB中有一本书。但也有:
- DB
- 数据库中的1个图书类别
- 2 BookTag in DB
通过使用官方指南,我能够收集到所有需要的信息。
BookSpecification.cs
using Ardalis.Specification;
using Core.Entities.BookAggregate;
namespace Core.Specifications
{
public class BookSpecification : Specification<Book>
{
public BookSpecification()
{
Query.Include(b => b.BookTags);
Query.Include(b => b.BookCategories);
Query.Include(b => b.Chapters);
}
}
}
IService.cs
using Ardalis.Specification;
namespace Core.Interfaces
{
public interface IService<T> where T : class, IAggregateRoot
{
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> ListAsync();
// Adapt to use specifications
Task<IEnumerable<T>> ListAsyncWithSpec(Specification<T> spec);
Task DeleteByIdAsync(int id);
Task AddAsync(T t);
Task UpdateAsyc(T t);
}
}
GenericService.cs
using Ardalis.Specification;
using Core.Interfaces;
using Core.Specifications;
namespace Core.Services
{
public class GenericService<T> : IService<T> where T : class, IAggregateRoot
{
private readonly IRepository<T> _repository;
private readonly IAppLogger<GenericService<T>> _logger;
public GenericService(IRepository<T> repository, IAppLogger<GenericService<T>> logger)
{
_repository = repository;
_logger = logger;
}
public async Task<T> GetByIdAsync(int id)
{
return await _repository.GetByIdAsync(id);
}
// Adapt to use specifications
public async Task<IEnumerable<T>> ListAsync()
{
return await _repository.ListAsync();
}
public async Task<IEnumerable<T>> ListAsyncWithSpec(Specification<T> spec)
{
return await _repository.ListAsync(spec);
}
public async Task DeleteByIdAsync(int id)
{
var t = await _repository.GetByIdAsync(id);
if (t == null)
{
_logger.Error($"Element with id: {id} can not be found!");
throw new ArgumentException($"Element with id: {id} can not be found!");
}
await _repository.DeleteAsync(t);
}
public async Task AddAsync(T t)
{
await _repository.AddAsync(t);
}
public async Task UpdateAsyc(T t)
{
await _repository.UpdateAsync(t);
}
}
}
BaseController.cs
使GET可重写
using Core.Interfaces;
using Microsoft.AspNetCore.Mvc;
namespace API.Controllers
{
public class BaseController<T> : Controller where T : class, IAggregateRoot
{
private protected readonly IService<T> _service;
public BaseController(IService<T> service)
{
_service = service;
}
[HttpGet]
public virtual async Task<IEnumerable<T>> Get()
{
return await _service.ListAsync();
}
[HttpGet("{id}")]
public async Task<T> Get(int id)
{
return await _service.GetByIdAsync(id);
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] T t)
{
await _service.AddAsync(t);
return Ok(t);
}
[HttpPut("{id}")]
public virtual async Task<IActionResult> Put(int id, [FromBody] T t)
{
throw new NotImplementedException();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
if (await _service.GetByIdAsync(id) == null)
return NotFound();
await _service.DeleteByIdAsync(id);
return Ok();
}
}
}
BookController.cs
using Core.Entities.BookAggregate;
using Core.Interfaces;
using Core.Specifications;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace API.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class BookController : BaseController<Book>
{
public BookController(IService<Book> service) : base(service)
{
}
[HttpGet]
public override async Task<IEnumerable<Book>> Get()
{
return await _service.ListAsyncWithSpec(new BookSpecification());
}
[HttpPut("{id}")]
public override async Task<IActionResult> Put(int id, [FromBody] Book book)
{
Book entity = await _service.GetByIdAsync(id);
entity.Title = book.Title;
entity.Chapters = book.Chapters;
await _service.UpdateAsyc(entity);
return Ok(entity);
}
}
}
Program.cs
忽略圆圈
builder.Services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);