简体   繁体   中英

Problem with loading related data in ef core using Ardalis Specification: List of objects evaluates to null

["

I'm new to ef core development and this looked at eShopOnWeb<\/a> for guidance.<\/i>

.sln

 - Controllers
 - Core
 - Infrastructure

I was able to gather all the information needed by using the official guide .

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 made GET overridable

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 ignore circles

builder.Services.AddControllers().AddJsonOptions(x => x.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM