LINQ查询有关多对多关系

时间:2018-10-12 16:40:49

标签: c# .net-core

我以这种方式建立了多对多关系

public class Produto
{
    public int ProdutoID { get; set; }
    public string Nome { get; set; }
    public double Preco { get; set; }
    public double Altura {get ; set; }
    public double Largura {get ; set; }
    public double Profundidade {get ; set; }
    public virtual ICollection<ProdutoParte> ProdutoPartes { get; set; }
}

public class Parte
{
    public int ParteID { get; set; }
    public string Nome { get; set; }
    public double Preco { get; set; }
    public double Altura {get ; set; }
    public double Largura {get ; set; }
    public double Profundidade {get ; set; }
    public virtual ICollection<ProdutoParte> ProdutoPartes { get; set; }
}

public class ProdutoParte
{
    public int ProdutoID { get; set; }
    public Produto Produto { get; set; }

    public int ParteID { get; set; }
    public Parte Parte { get; set; }
}

这是我的dbcontext

public DbSet<Produto> Produtos { get; set; }
public DbSet<Parte> Partes {get;set;}
public DbSet<ProdutoParte> ProdutoPartes { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ProdutoParte>()
        .HasKey(pp => new { pp.ProdutoID, pp.ParteID });

    modelBuilder.Entity<ProdutoParte>()
        .HasOne(pp => pp.Produto)
        .WithMany(pr => pr.ProdutoPartes)
        .HasForeignKey(bc => bc.ProdutoID);

    modelBuilder.Entity<ProdutoParte>()
        .HasOne(pp => pp.Parte)
        .WithMany(pa => pa.ProdutoPartes)
        .HasForeignKey(pp => pp.ParteID);
}

一个产品(产品)可以由许多Parte(零件)和 一个Parte(零件)可用于创建许多Produto(产品)。

我正在尝试编写以下查询:

produto/{id}/partes

这将返回产品中带有{id}的所有零件

这就是我现在拥有的

public IActionResult GetPartes([FromRoute] int id)
{
    if(!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    Produto produto = _context.Produtos.SingleOrDefault(p => p.ProdutoID == id);

    if(produto == null)
    {
        return NotFound();
    }

    var parts = _context.ProdutoPartes.Where(p => p.ProdutoID == id);

    return Ok(parts);
}

具有以下测试数据(仍使用inmemorydatabse)

if (_context.Produtos.Count() == 0)
{
    _context.Produtos.Add(new Produto() {ProdutoID=1, Nome="product1" });
    _context.Partes.Add(new Parte() {ParteID=1, Nome="part1" });
    _context.Partes.Add(new Parte() {ParteID=2, Nome="part2" });
    _context.Partes.Add(new Parte() {ParteID=3, Nome="part3" });
    _context.ProdutoPartes.Add(new ProdutoParte() {ProdutoID=1, ParteID=1 });
    _context.ProdutoPartes.Add(new ProdutoParte() {ProdutoID=1, ParteID=2 });
    _context.ProdutoPartes.Add(new ProdutoParte() {ProdutoID=1, ParteID=3 });
    _context.SaveChanges();
}

但是,通过json使用邮递员时,我得到的只是这个 获取api / produto / 1 / partes

[{"produtoID":1,"produto":{"produtoID":1,"nome":"product1","preco":0.0,"altura":0.0,"largura":0.0,"profundidade":0.0,"produtoPartes":[

应该是零件清单。

不胜感激。

2 个答案:

答案 0 :(得分:1)

  

应该是零件清单。

您不需要的是零件清单:您需要的是ProdutoPartes清单。您可以通过几种方式更改查询以获取所需的内容。一个是:

var parts = _context.Partes
    .Where(p => p.ProdutoPartes.Any(pp => pp.ProdutoID == id))
    .ToList();

其他一些建议:

  1. 创建一个DTO类,该类仅表示您真正希望作为API一部分发送回的数据。使用.Select()语句将您的实体映射到此DTO。这样一来,您发送回的信息就不会比您打算的要多。
  2. 看起来ProdutoPartes实际上只是一个中间映射表。从您的模型中删除该模型,以便在Produto和Parte之间使用many-to-many mapping。这样,您的查询将变为:

    var parts = _context.Partes
        .Where(p => p.Produtos.Any(pp => pp.ProdutoID == id))
        .ToList();
    

答案 1 :(得分:0)

此查询将为您提供指定ProdutoID的所有部分。

List<Parte> parts = _context.ProdutoPartes.Where(x => x.ProdutoID == id)
                    .Select(x = x.Parte).ToList();   

您的Parte类中的数据是否足够?是否具有客户所需的所有信息?如果是,那么您很好。

如果没有,请创建ParteDto:

public class ParteDto
{
    public Parte Parte { get; set; }

    // Put other properties here 
}

修改您的查询:

List<ParteDto> parts = _context.ProdutoPartes.Where(x => x.ProdutoID == id)
                      .Select(x = new ParteDto { Parte = x.Parte  /* , other properties */ })
                      .ToList();   

说实话,如果您直接从您的控制器与DbContext对话,则您甚至都不需要DTO,您可以仅返回如下所示的匿名类型。请注意,new关键字后没有类型:

var parts = _context.ProdutoPartes.Where(x => x.ProdutoID == id)
            .Select(x = new { Parte = x.Parte  /* , other properties */ })
            .ToList();