如何在EF核心中选择与其他实体有关系的实体

时间:2021-07-09 20:06:33

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

如何在不包含项目的情况下获取特定项目的产品列表?类似的东西

select p.Id, p.Name 
from product p
inner join ProjectProduct j on p.Id = j.ProductId and j.ProjectId = @Id

我最接近的解决方案是

var products = await (from proj in context.Project select proj)
                    .Where(proj => proj.Id == 1)
                    .Select(proj => proj.Product)
                    .ToListAsync();

但这会返回一个 List<List<Product>> 另外我需要能够添加顺序和分页 我知道我可以通过这样的原始 sql 来做到这一点

var param1 = new SqlParameter("@Id", id);
var query = @"select * from product p
inner join ProjectProduct j
on p.Id = j.ProductId and j.ProjectId = @Id ";

var queryable = context.product.FromSqlRaw(query, param1).AsQueryable();
await HttpContext.AddPaginationToHeader(queryable);

var products = await queryable.OrderBy(x => x.Name).Paginate(paginationDTO).ToListAsync();

但我希望通过 linq to entity 来实现

public class Project
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Product> Product { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Project> Project { get; set; }
}

public class ProjectProduct
{
    public int ProjectId { get; set; }
    public int ProductId { get; set; }
}

2 个答案:

答案 0 :(得分:0)

试试这个:

var products = await  context.Project
                      .Where(proj => proj.Id == 1)
                      .Select( proj=>proj.Products)
                      .FirstOrDefaultAsync();

如果您想在此之后订购产品,您可以这样做

products= products.OrderBy(p=>p.Name).ToList();

它可以放在一行,但EF有时会生成一个非常荒谬的Sql脚本,所以最好分开做。

答案 1 :(得分:0)

感谢 Harald Coppoolse 对另一篇文章的回应 对于那些有同样问题的人

这是步骤 1- 我们将查询定义为可查询的

var queryable = context.Project
                .Where(proj => proj.Id == id)
                .SelectMany(p => p.Product).AsQueryable();

2- 现在我们可以像这样将查询传递给 SQL 服务器

var products = await queryable.OrderBy(x => 
x.Name).Skip(...).Take(...).ToListAsync();

对于 Skip and Take,我们可以为 IQueryable 创建一个通用扩展 并添加一个方法返回

return queryable
                .Skip((paginationDTO.Page - 1) * paginationDTO.PageSize)
                .Take(paginationDTO.PageSize);

当然,我们的 paginationDTO 只不过是一个具有 page 和 pageSize 2 个属性的 POCO 类