【问题标题】:How can I get data from a many-to-many relationship in .NET?如何从 .NET 中的多对多关系中获取数据?
【发布时间】:2022-12-20 03:23:03
【问题描述】:

我制作了一个用于学习使用 .NET 的 API。

这是一个简单的 API,我有披萨和配料。我想获取数据库中的所有比萨及其配料。像这样的东西:

[
  {
    "id": 2,
    "name": "Pizza XYZ",
    "price": 4.5,
    "isPizzaOfTheWeek": false,
    "amount": 15,
    "pizzaIngredients": [
      {
         id: 1,
         name: 'Onion',
         price: '2.00',
         cost: '8.00'
      }
    ]
  },
]

我的实体是这些:

public class Pizza
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; } = null!;
    [Column(TypeName = "decimal(5,2)")]
    public decimal Price { get; set; }      
    public bool IsPizzaOfTheWeek { get; set; }
    public int Amount { get; set; }
    
    public List<PizzaIngredient> PizzaIngredients { get; set; } = null!;
}

public class Ingredient
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; } = null!;
    
    [Column(TypeName = "decimal(5,2)")]
    public decimal Price { get; set; }      // Price per 100 g

    public List<PizzaIngredient> PizzaIngredients { get; set; } = null!;
}

public class PizzaIngredient
{
    [Key]
    public int PizzaId { get; set; }
    public Pizza Pizza { get; set; } = null!;
    
    [Key]
    public int IngredientId { get; set; }
    public Ingredient Ingredient { get; set; } = null!;
    
    [Column(TypeName = "decimal(5,2)")]       
    public decimal Cost { get; set; } // Total Cost of this ingredient for this pizza
}

问题是我不知道该怎么做。

我尝试使用:var pizzas = await _context.Pizza.Include(p =&gt; p.PizzaIngredients).ThenInclude(pi =&gt; pi.Ingredient).ToListAsync();

这个函数给我带来了所有的配料数据,但它也给我带来了重复的数据,因为“配料”有一个属性,它也是一个比萨配料列表。

我希望一切都清楚。如果需要更多信息,我会写下来。

【问题讨论】:

  • 答案几乎与称为“我的个人方法”here 的答案相同 - 创建一个 DTO/模型来准确表示您要在此处返回的内容并将获取的数据映射到它。
  • 我用我想要的数据创建了成分模型。现在,如何用数据库中的信息填充这个新模型?
  • 在查询中使用 Select 查看像 automapper 这样的工具。

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


【解决方案1】:

如果不需要在其中添加其他属性,通常我建议删除映射表。将价格移至比萨饼,因为它适用于它。除非你做一个订单表。

楷模

public class Pizza
{
    public Pizza()
    {
       //Initialize the collection in Hashset for fast search
       this.Ingredients = new HashSet<Ingredients>();
    }

    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    [Column(TypeName = "decimal(5,2)")]
    public decimal Price { get; set; }      
    public bool IsPizzaOfTheWeek { get; set; }
    public int Amount { get; set; }
    public decimal Cost { get; set; }
    
    public virtual ICollection<Ingredient> Ingredients { get; set; }
}

public class Ingredient
{
    public Ingredient()
    {
       //Initialize the collection in Hashset for fast search
       this.Pizzas = new HashSet<Pizza>();
    }

    [Key]
    public int Id { get; set; }
    public string Name { get; set; } = null!;
    
    [Column(TypeName = "decimal(5,2)")]
    public decimal Price { get; set; }      // Price per 100 g

    public virtual ICollection<Pizza> Pizzas { get; set; }
}

//DtoModel
public class PizzaDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }      
    public bool IsPizzaOfTheWeek { get; set; }
    public int Amount { get; set; }
    public decimal Cost { get; set; } //Total cost of ingredients prices
    
    public List<Ingredient> Ingredients { get; set; };
}

服务

//All pizza ids you want with single query
var ids = new List<int> { 1, 4, 6, 22 };

var pizzas = await context.Pizzas
    .Where(x => ids.Contains(x.Id))
    .Select(x => new PizzaDto
    {
       Id = x.Id,
       Name = x.Name,
       Price = x.Price,
       IsPizzaOfTheWeek = x.IsPizzaOfTheWeek,
       Amount = x.Amount ,
       Cost = x.Ingredients.Sum(x => x.Price),
       Ingredients = x.Ingredients,
    }).ToListAsync();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-11
    • 2019-05-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多