MVC新手求助:食谱与食材多对多数据库模型构建及联表查询问题
食谱与食材数据库设计及MVC实现方案
一、数据库表设计(4张核心表)
针对食谱与食材的多对多关系,搭配分类管理,设计以下4张表:
1. 食材分类表 (categories)
category_id(INT, 主键, 自增): 分类唯一标识category_name(VARCHAR(50), 非空): 分类名称(如蔬菜、肉类、调料)
2. 食材表 (ingredients)
ingredient_id(INT, 主键, 自增): 食材唯一标识ingredient_name(VARCHAR(100), 非空): 食材名称(如西红柿、牛腩)category_id(INT, 外键关联categories.category_id): 所属分类IDunit(VARCHAR(20)): 计量单位(如克、个、勺)
3. 食谱表 (recipes)
recipe_id(INT, 主键, 自增): 食谱唯一标识recipe_name(VARCHAR(100), 非空): 食谱名称(如西红柿炖牛腩)description(TEXT): 食谱简介cooking_steps(TEXT): 烹饪步骤
4. 食谱-食材关联表 (recipe_ingredients)
这张表用来解决食谱和食材的多对多关系:
recipe_id(INT, 外键关联recipes.recipe_id): 关联的食谱IDingredient_id(INT, 外键关联ingredients.ingredient_id): 关联的食材IDquantity(DECIMAL(10,2)): 食材用量- 联合主键:
(recipe_id, ingredient_id),避免同一个食谱重复关联同一个食材
二、MVC各层实现步骤
1. 模型层(Model)
先定义对应表的实体类(以C#为例,其他语言逻辑一致):
// 分类实体 public class Category { public int CategoryId { get; set; } public string CategoryName { get; set; } public List<Ingredient> Ingredients { get; set; } } // 食材实体 public class Ingredient { public int IngredientId { get; set; } public string IngredientName { get; set; } public int CategoryId { get; set; } public string Unit { get; set; } public Category Category { get; set; } public List<RecipeIngredient> RecipeIngredients { get; set; } } // 食谱实体 public class Recipe { public int RecipeId { get; set; } public string RecipeName { get; set; } public string Description { get; set; } public string CookingSteps { get; set; } public List<RecipeIngredient> RecipeIngredients { get; set; } } // 食谱-食材关联实体 public class RecipeIngredient { public int RecipeId { get; set; } public int IngredientId { get; set; } public decimal Quantity { get; set; } public Recipe Recipe { get; set; } public Ingredient Ingredient { get; set; } }
数据访问核心操作:
- 查询所有分类及下属食材,用于创建食谱时展示选项
- 保存流程:先存食谱得到
recipe_id,再批量保存关联表的食材记录
2. 视图层(View)
创建食谱的页面需要包含两部分:食谱基本信息、食材选择区。示例简化结构:
<form method="post" action="/Recipe/Create"> <!-- 食谱基本信息 --> <input type="text" name="RecipeName" placeholder="食谱名称" required> <textarea name="Description" placeholder="食谱简介"></textarea> <textarea name="CookingSteps" placeholder="烹饪步骤" required></textarea> <!-- 食材选择区 --> <h3>选择食材</h3> @foreach (var category in Model.Categories) { <h4>@category.CategoryName</h4> @foreach (var ingredient in category.Ingredients) { <div> <input type="checkbox" name="SelectedIngredients" value="@ingredient.IngredientId"> <label>@ingredient.IngredientName</label> <input type="number" name="Quantity_@ingredient.IngredientId" step="0.1" placeholder="用量(@ingredient.Unit)"> </div> } } <button type="submit">保存食谱</button> </form>
3. 控制器层(Controller)
处理创建请求的核心逻辑:
public class RecipeController : Controller { private readonly YourDbContext _dbContext; public RecipeController(YourDbContext dbContext) { _dbContext = dbContext; } // 展示创建页面 public IActionResult Create() { var viewModel = new CreateRecipeViewModel { // 加载所有分类及下属食材 Categories = _dbContext.Categories.Include(c => c.Ingredients).ToList() }; return View(viewModel); } // 处理提交请求 [HttpPost] public IActionResult Create(Recipe recipe, int[] SelectedIngredients, Dictionary<string, decimal> Quantity) { if (ModelState.IsValid) { // 1. 先保存食谱到数据库,生成recipe_id _dbContext.Recipes.Add(recipe); _dbContext.SaveChanges(); // 2. 批量处理选中的食材 foreach (var ingredientId in SelectedIngredients) { // 获取对应食材的用量 if (Quantity.TryGetValue($"Quantity_{ingredientId}", out var quantity)) { var recipeIngredient = new RecipeIngredient { RecipeId = recipe.RecipeId, IngredientId = ingredientId, Quantity = quantity }; _dbContext.RecipeIngredients.Add(recipeIngredient); } } _dbContext.SaveChanges(); return RedirectToAction("Index"); } // 验证失败,返回页面并保留输入内容 var viewModel = new CreateRecipeViewModel { Categories = _dbContext.Categories.Include(c => c.Ingredients).ToList(), Recipe = recipe }; return View(viewModel); } }
三、核心问题解决:创建食谱时如何选取全部食材
- 展示食材选项:视图层通过数据库关联查询,把所有食材按分类展示给用户,用户可勾选需要的食材并填写用量
- 保存关联关系:控制器接收选中的食材ID数组和对应用量,在食谱保存成功后,将食谱ID、食材ID、用量批量存入关联表
- 查询食谱食材:后续要查看某食谱的全部食材,只需通过
recipe_id关联查询recipe_ingredients和ingredients表即可
内容的提问来源于stack exchange,提问作者baba
相关产品推荐
相关产品推荐

