如何从数据库中仅选择一条记录,但还从相关表中选择其数据

时间:2019-06-04 18:44:37

标签: c# entity-framework .net-core entity-framework-core

我正在编写一个Entity Framework Command,用于从数据库中仅选择一个记录(书)。它需要通过api显示,其中用户应通过url提供ID。另外,由于表与其他表(作家,类型)有关,因此需要包括这些表中的相关记录。图书可以具有更多类型,并将其存储在BookGenres表中,然后该表与Genre表相关。此外,Book在表中有一个Writer具有相同的名称。 BookDto是仅返回最终用户相关数据的对象。命令如下:

EfGetBookCommand:IGetBookCommand

 private readonly LibraryContext _context;

    public EfGetBookCommand(LibraryContext context)
    {
        _context = context;
    }

    public BookDto Execute(int request)
    {
        //var book = _context.Books.AsQueryable();
        var book = _context.Books.AsQueryable();
        if (book == null)
        {
            throw new Exception();
        }

        var result = book
            .Include(b => b.Writer)
            .ThenInclude(w => w.Name)
            .Include(b => b.BookGenres)
            .ThenInclude(bg => bg.Genre)
            .Where(b => b.Id == request)
            .First();

        return new BookDto
        {
            Id = result.Id,
            Title = result.Title,
            Writer = result.Writer.Name,
            Description = result.Description,
            AvailableCount = result.AvailableCount,
            Count = result.Count,
            BookGenres = result.BookGenres.Select(bg => bg.Genre.Name)
        };

当我通过诸如http://localhost:55666/api/books/4这样的GET请求在邮递员中尝试此操作时,我得到404。由于无法将其与Include结合使用,因此无法使用find。我将展示相关课程。

我已经有类似的命令可以退回所有书籍,并且它可以正常工作,所以我无法找到问题所在。

BooksController(在API应用程序中)

    public class BooksController : ControllerBase
{
    private IGetBooksCommand _command;
    private IGetBookCommand _command2;

    public BooksController(IGetBooksCommand command, IGetBookCommand command2)
    {
        _command = command;
        _command2 = command2;
    }
 [HttpGet("{id}")]
    public IActionResult Get(int id)
    {
        try
        {
            var BookDto = _command2.Execute(id);
            return Ok(BookDto);
        }
        catch(Exception e)
        {
            return NotFound();
        }
    }

BookDto

public class BookDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Writer { get; set; }
    public string Description { get; set; }
    public int AvailableCount { get; set; } 
    public int Count { get; set; }
    public IEnumerable<string> BookGenres { get; set; }
}

书(实体框架代码的域类优先方法)

   public class Book : BaseEntity
{
    public string Title { get; set; }
    public int WriterId { get; set; }
    public Writer Writer { get; set; }
    public string Description { get; set; }
    public int AvailableCount { get; set; }
    public int Count { get; set; } reserved or not
    public ICollection<BookGenre> BookGenres { get; set; }
    public ICollection<BookReservation> BookReservations { get; set; }
}

BookGenre(DomainClass)

public class BookGenre
{
    public int BookId { get; set; }
    public int GenreId { get; set; }
    public Book Book { get; set; }
    public Genre Genre { get; set; }
}

类型(DomainClass)

public class Genre : BaseEntity
{
    public string Name { get; set; }
    public ICollection<BookGenre> BookGenres { get; set; }
}

Writer(DomainClass)

ICommand

    public interface ICommand<TRequest>
{
    void Execute(TRequest request);
}
public interface ICommand<TRequest, TResult>
{
    TResult Execute(TRequest request);
}

IGetBookCommand

    public interface IGetBookCommand : ICommand<int, BookDto>
{

}

我应该在json中返回一个BookDto对象,但出现404错误。

2 个答案:

答案 0 :(得分:0)

我怀疑var BookDto = _command2.Execute(id);行中有内容 当我检查您的代码库时,我可以看到一个具有相同名称的类已经存在,并且您尝试再次重新创建它。

自从您返回return NotFound();以来,请尝试确保正确完成路由,并且操作已触发。

我建议使用AttributeRouting之类的

 [Route("~/api/books/{id}")] [HttpGet]
 public IActionResult Get(int id)
{
    try
    {
        var result= _command2.Execute(id);
        return Ok(result);
    }
    catch(Exception e)
    {
        // Try returning some other exception other than 404.
    }
}

答案 1 :(得分:0)

尝试遵循以下方法。您的初始查询正在调用AsQueryable(),这将导致sql执行,并且您会松散延迟加载。您可以将所有sql逻辑组合到主查询中,并立即获取所有联接表。由于我没有所有代码,这可能会有一些语法错误。

public BookDto Execute(int request)
    {
        var book = _context.Books
            .Single(b => b.Id == request)
            .Select(s => new BookDto() {
               Id = s.Id,
               Title = s.Title,
               Writer = s.Writer.Name,
               Description = s.Description,
               AvailableCount = s.AvailableCount,
               BookGenres = s.BookGenres.ToList()
        });
    }