如何在ASP.NET MVC EF中将多行连接成一行

问题描述 投票:0回答:4

我有3张桌子:

  • 食谱
  • RecipeIngredient(fk RecipeId)
  • RecipeTag(fk RecipeId)

食谱

+-----+------------+-------------+------+
| Id  |    Name    | Ingredients | Tags |
+-----+------------+-------------+------+
|  99 | Mango Sago |             |      |
| 100 | Tuna Melt  |             |      |
+-----+------------+-------------+------+

RecipeIngredient

+-----+----------+------------+---------------------------------------------+----------+
| Id  | Quantity |    UOM     |                    Name                     | RecipeId |
+-----+----------+------------+---------------------------------------------+----------+
| 115 | 2        | Pieces     | Whole Ripe Mangoes                          |       99 |
| 116 | 1        | Pieces     | Jolly Coconut Milk, 400ml                   |       99 |
| 117 | 2        | Tablespoon | Sugar                                       |       99 |
| 118 | 1        | Cup        | Cooked Tapioca Pearls                       |       99 |
| 119 | NULL     | NULL       | Mango Cubes                                 |       99 |
| 120 | 1        | Pieces     | Doña Elena 100% Tuna Shredded 185g, drained |      100 |
| 121 | 2        | Tablespoon | White Onion, chopped                        |      100 |
| 122 | 2        | Tablespoon | Jolly Real Mayonnaise                       |      100 |
| 123 | 1        | Tablespoon | Celery or Pickle Relish, finely chopped     |      100 |
| 124 | 8        | Pieces     | White Bread                                 |      100 |
| 125 | 4        | Pieces     | Cheddar or Mozzarella Cheese                |      100 |
+-----+----------+------------+---------------------------------------------+----------+

RecipeTag

+----+-----------------+----------+
| Id |      Name       | RecipeId |
+----+-----------------+----------+
| 72 | Filipino Desert |       99 |
| 73 | Quick Recipe    |       99 |
| 74 | Quick Recipe    |      100 |
+----+-----------------+----------+

如何将所有RecipeIngredient添加到Ingredients表中的Recipe列,并将所有RecipeTag添加到控制器中Tags表中的Recipe列?

Output I want

public JsonResult GetAllRecipes()
{
    var recipes = db.Recipes.OrderBy(a => a.Name).ToList();
    return new JsonResult { Data = recipes, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
c# asp.net-mvc entity-framework
4个回答
2
投票
public JsonResult GetAllRecipes()
{
    var recipes = (from rec db.Recipes
                   join ing in db.Ingredients on rec.Id equals ing.RecipeId into subIngrs
                   from subIngr in subIngrs.DefaultIfEmpty()
                   join tag in db.RecipeTags on rec.Id equals tag.RecipeId into subTags
                   from subTag in subTags.DefaultIfEmpty()
                   order by rec.Name
                   select new 
                   {
                       rec.Id,
                       rec.Name,
                       Quantity = subIngr == null ? null : subIngr.Quantity, 
                       IngrName = subIngr == null ? null : subIngr.Name, 
                       UOM = subIngr == null ? null : subIngr.UOM, 
                       TagName = subTag == null ? null : subTag.Name 
                   }).ToList()
                   .GroupBy(x => new { x.Id, x.Name }).Select(x => new 
                   {
                       x.Key.Id,
                       x.Key.Name,
                       Ingredients = string.Join("," x.Where(y => y.IngrName != null).Select(y => $"{y.Quantity} {y.UOM} {y.Name}").Distinct()),
                       Tags = string.Join("," x.Where(y => y.TagName != null).Select(y => y.TagName).Distinct())
                   }).ToList();

    return new JsonResult { Data = recipes, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}

2
投票

如果你想在sql中使用它,你可以使用STUFF

SELECT  a.Id,
        Recipe = a.Name,
        Ingredient = STUFF((
              SELECT ',' 
                     + CAST(b.Quantity AS NVARCHAR(10)) + ' ' 
                     + b.UOM + ' ' 
                     + b.Name
              FROM dbo.RecipeIngredient b
              WHERE a.Id = b.RecipeId
              FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
         Tag = STUFF((
              SELECT ',' + c.Name
              FROM dbo.RecipeTag c
              WHERE a.ID = c.RecipeId
              FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM    Recipe a

这是一个Demo.

执行存储过程并将结果作为json返回到控制器方法中

var recipies = db.Database.SqlQuery<RecipeVM>("NameOfStoredProcedure");
return Json(recipes, JsonRequestBehavior = JsonRequestBehavior.AllowGet);

RecipeVM在哪里

public class RecipeVM
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Ingredient { get; set; }
    public string Tag { get; set; }
}

1
投票

假设您已正确设置导航属性(即Recipe包含public virtual ICollection<RecipieIngredient> Ingredients { get; set; }等),那么以您想要的连接格式获取数据,

public JsonResult GetAllRecipes()
{
    var recipes = db.Recipes
        .OrderBy(r => r.Name)
        .ToList() // this is necessary because we need Linq to Objects for the string formatting
        .Select(r => new // can be anonymous objects because we are returning a JsonResult
        {
            Id = r.Id,
            Name = r.Name,
            Ingredients = r.Ingredients
                .Select(i => string.Format("{0} {1} {2}", i.Quantity, i.UOM, i.Name).TrimStart())
                .Aggregate((c, n) => c + ", " + n),
            Tags = r.Tags
                .Select(t => t.Name)
                .Aggregate((c, n) => c + ", " + n)
        });
    return Json(recipes, JsonRequestBehavior = JsonRequestBehavior.AllowGet);
}

旁注,你的RecipeIngredient表显示QuantityUOM的可空值,因此TrimStart。我假设,如果QuantityUOMnull,那么另一个也是null

或者,您可以使用(在LINQ to SQL中)

var recipes = (from r in db.Recipies
               join i in db.RecipeIngredient on r.Id equals i.RecipeId into Ingedients
               join t in db.RecipeTag on r.Id equals t.RecipeId into Tags
               orderby r.Name
               select new
               {
                   Name = r.Name,
                   Ingedients = Ingedients,
                   Tags = Tags
               }).ToList()
               .Select(x => new
               {
                   Name = x.Name,
                   Ingredients = x.Ingedients
                       .Select(y => string.Format("{0} {1} {2}", y.Quantity, y.UOM, y.Name).Trim())
                       .Aggregate((c, n) => c + ", " + n),
                   Tags = x.Tags
                       .Select(y => y.Name)
                       .Aggregate((c, n) => c + ", " + n)
               });
return Json(recipes, JsonRequestBehavior = JsonRequestBehavior.AllowGet);

0
投票

我不确定你要完成什么,但是如果你试图以编程方式从用户输入中插入这些数据,你可以迭代成分/标签并构建一个字符串以插入到相关的表中。

如果您尝试从现有数据执行此操作,那么我不确定EF是否可以使用。我只想编写SQL脚本来处理它。

© www.soinside.com 2019 - 2024. All rights reserved.