使用Ardalis规范在ef core中加载相关数据的问题:对象列表的计算结果为null



我是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
<表类>条目BookIdCategoryIdtbody><<tr>112

通过使用官方指南,我能够收集到所有需要的信息。

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);

最新更新