我使用 .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 => p.PizzaIngredients).ThenInclude(pi => pi.Ingredient).ToListAsync();
这个函数给我带来了所有的成分数据,但它也给我带来了重复的数据,因为“成分”具有属性,它也是一个
PizzaIngredients
的列表。
我希望一切都清楚。如果需要更多信息,我会写。
通常,如果不需要其中包含其他属性,我建议删除映射表。将价格移至披萨,因为它适用于披萨。除非你做了一个订单表。 Ypu 不需要在 FluentApi 中为多对多做任何事情
型号
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; }
//Use a collection instead of a list to be able to convert it to HashSet
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
//Use a collection instead of a list to be able to convert it to HashSet
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; };
}
服务
//Qerry
//All pizza ids you want with single query
var ids = new List<int> { 1, 4, 6, 22 };
var pizzas = await this.context.Pizzas
.Where(x => ids.Contains(x.Id)) // Pizzas by ids
.Where(x => x.Ingredients.Any(x => x.Name == name)) //Pizzas by ingredient
.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();
//Save
var pizza = new Pizza
{
Name = name,
Price = price,
IsPizzaOfTheWeek = isPizzaOfTheWeek,
Amount = amount ,
Cost = ingredients.Sum(x => x.Price),
Ingredients = ingredients, //List of ingreadients
};
await this.context.AddAsync(pizza);
await this.context.SaveChangesAsync();