如何循环遍历 IEnumerable List 如果有任何重复项,请对每个重复项的值求和,并在 MVC C 中删除 ASP.Net 重复项#

How to Loop through IEnumerable List and if there are any duplicates, sum a value each duplicate has and remove the duplicates in ASP.Net MVC C#

提问人:Kip M. 提问时间:10/30/2023 最后编辑:dbcKip M. 更新时间:11/1/2023 访问量:90

问:

我有一个库存使用情况页面,其中填充了我在特定时间段(例如一个月左右)内使用过的物品列表。有大量重复的项目,我试图在视图页面(IEnumerable List)上放置一个按钮,该按钮将使用项目及其总数列表填充pdf。我无法弄清楚的是如何遍历项目列表,如果有任何重复项,请获取“AmtTaken”值并将它们相加,然后删除重复项,其中它只显示每个项目一次,但“AmtTaken”总数相加在一起。 我现在没有太多代码可以删除,因为我被困住了,并试图找出最好的方法来做到这一点。它来自名为“InventoryUsage”的数据库表。

这是我的模型:

   public partial class InventoryUsage
   {
       [Key]
       [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
       public int ID { get; set; }           
       [Display(Name = "Item Code")]
       public string Item_Code { get; set; }           
       [Display(Name = "Amt Taken")]
       public string Amt_Taken { get; set; }           
       [Display(Name = "Submitted?")]
       public Nullable<bool> Submitted { get; set; }
   }

因此,我正在寻找的重复项是具有相同Item_Code的任何重复项,如果存在重复项,则将Amt_Taken值相加。我仍然希望它列出所有没有重复的项目。我目前如何设置它是“已提交”== false 的所有项目。因此,使用此模型,如果存在重复项,则 ID 将不相同,因此这是另一件让我失望的事情。

这是我的视图页面:

 @model IEnumerable<MyApp.Models.InventoryUsage>

     <div class="wrapper">
         <table class="table">
             <tr>
                 <th>
                     Item/RM Code
                 </th>
                 <th>
                     Amt Taken
                 </th>
                 <th>
                     Submitted? (Y/N)
                 </th>
                 <th></th>
             </tr>

             @foreach (var item in Model)
             {
                 <tr>
                     <td>
                         @Html.DisplayFor(modelItem => item.Item_RM_Code)
                     </td>
                     <td>
                         @Html.DisplayFor(modelItem => item.Amt_Taken)
                     </td>
                     <td>
                         @if (item.Submitted_ == true)
                         {
                             <label class="lbl-yes">Yes</label>
                         }
                         else
                         {
                             <label class="lbl-no">No</label>
                         }
                     </td>
                     <td>
                         @Html.ActionLink("Generate List", "GetTotals", new { not sure what to put here yet }) |
                         @Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
                         @Html.ActionLink("Delete", "Delete", new { id = item.ID })
                     </td>
                 </tr>
             }
         </table>
     </div>

对于我的控制器来说,我还没有太多代码,因为我完全被难住了。

    public ActionResult Index()
    {
        var usage = from u in db.InventoryUsage
                    select u;

        return View(usage.Where(u => u.Submitted_ == false).ToList());
    }


    public ActionResult GetTotals()
    {
        var list = db.InventoryUsage.Where(x => x.Submitted == false).ToList();

        //Stuck on this part//

    }

任何建议或指导将不胜感激!

C# asp.net ASP.NET-MVC LINQ

评论

0赞 dbc 10/31/2023
1) 为什么字符串而不是数字类型像?如何对字符串值求和?2) LINQ 是否删除重复项和结果项以具有数量之和和/或如何在 Linq 中获取 SUM? 回答您的问题?Amt_Takendecimal
0赞 Kip M. 10/31/2023
@dbc当我第一次制作数据库表时,我的格式是错误的。我应该添加一个“计量单位”列,但决定只保留一个文本列,这样我就可以输入(例如:“10 磅”或“10 加仑”,而不必做 2 个不同的字段。直到我开始想尝试做这个列表功能,我才意识到我搞砸了,不能这样做。因此,我将不得不为度量单位添加新列,并将 AmtTaken 更改为数字。但无论哪种方式,只要只有一个数值,它还是应该求和吧?
0赞 dbc 10/31/2023
只要你有办法得到每个数值的数值,我相信你应该能够使用dtb的答案来获得一个关于如何在Linq中得到一个SUM? 来得到你的总和:。这回答了你的问题吗?InventoryUsagedb.InventoryUsage.GroupBy(x => x.Item_Code).Select(g => new { Item_Code = g.Key, Amt_Taken= g.Sum(x => GetValue(x.Amt_Taken)) })
0赞 Kip M. 10/31/2023
此外,这些示例让我感到困惑,不明白我如何将其应用于我的例子。他们使用通用列表并按 ID 匹配它们,而我无法按 ID 匹配我的。
0赞 Wyck 10/31/2023
Смотритетакже: 在数据库中存储单位的最佳方式

答:

0赞 Moho 10/31/2023 #1

使用并求和结果:GroupBy

IEnumerable<InventoryUsage> usages = ...;

var aggregatedUsages = usages.GroupBy( iu => iu.Item_Code )
    .Select( g => new
    {
        Item_Code = g.Key,
        Amt_Taken = g.Select( iu => Convert.ToInt32( iu.Amt_Taken ) )
            .Sum();
    } );

您没有指定如何处理相同 的值不匹配。如果您希望按项目代码和已提交/未提交值对金额进行总和,则可以将该部分作为密钥的一部分:SubmittedItem_CodeGroupBy

usages.GroupBy( iu => new { iu.Item_Code, iu.Submitted } )

然后投影这些属性:

.Select( g => new
{
    Item_Code = g.Key.Item_Code,
    Submitted = g.Key.Submitted,
    Amt_Taken = ...,
} )

评论

0赞 Kip M. 10/31/2023
谢谢@Moho,我会试一试,让你知道!但有一个问题,g.Key 值是什么?我不明白这是从哪里来的?
0赞 dbc 10/31/2023
Convert.ToInt32( iu.Amt_Taken )-- 这使用本地化解析。由于使用的区域设置是服务器的区域设置,而不是客户端的区域设置,因此可能不合适。Querent 真的应该重新考虑他们的数据库设计,以避免这种陷阱。
0赞 dbc 10/31/2023
@KipM。- 它是IGrouping<TKey,TElement>。键
0赞 Moho 10/31/2023
@KipM。learn.microsoft.com/en-us/dotnet/api/......
0赞 Kip M. 11/1/2023
在执行上述示例时,我在执行“Convert.ToInt32”时不断获得无效的输入数据类型,因此我返回并将数据类型更改为十进制,因为我的某些值将是十进制金额。执行此操作后,现在它一直显示“System.InvalidOperationException:传递到字典中的模型项的类型为'System.Linq.Enumerable+WhereSelectEnumerableIterator2[System.String,KTC_QC1.Models.InventoryUsage_QC],但此字典需要类型为“System.Collections.Generic.IEnumerable”1[KTC_QC1.Models.InventoryUsage_QC]'。2[System.Linq.IGrouping
0赞 Kip M. 11/1/2023 #2

我终于能够让它工作。@dbc和@Moho,非常感谢你们俩!你为我指明了正确的方向,在研究了更多关于分组方法的东西之后,我最终只是对你的所有建议做了一些小的调整。出于某种原因,它不允许我对我的数据库实体模型执行此操作,因为它使用泛型列表,因此我创建了另一个名为 UsageTotalsModel 的模型类,并仅添加了 InventoryUsage 模型中的相关字段。我猜,由于这不是数据库实体模型,因此它可以使用此函数使用的泛型列表。这是我添加的新模型:

  public class UsageTotalsModel
  {
      public UsageTotalsModel() { }


      public string Item_Code { get; set; }
      [DisplayFormat(DataFormatString = "{0:0.###}")]
      public Nullable<decimal> Amt_Taken { get; set; }
      public string UnitOfMeasure { get; set; }       
      public Nullable<bool> Submitted { get; set; }
      public InventoryUsage Usage { set; get; }
  }

因此,在我的控制器中,我只是从 InventoryUsage 中提取数据并将其添加到 UsageTotalsModel。这修复了我不断收到的错误消息。

    public ActionResult GetTotals()
    {
        var usage = from u in db.InventoryUsage
                    where u.Submitted == false
                    group u by u.Item_Code into g
                    orderby g.Key
                    select new UsageTotalsModel() { Item_Code = g.Key, Amt_Taken = g.Sum(u => u.Amt_Taken) };
                 
        var result = usage.ToList();
        return new ViewAsPdf("GetTotals", result) { PageOrientation = Rotativa.Options.Orientation.Portrait };
    }

现在我唯一的问题是带有小数点的项目会自动四舍五入到最接近的十分之一,因此在某些金额上,它为 0.02 磅,它显示为 0。但这是一个不同的问题,如果我卡住了,我会针对这个问题发布另一个问题,但我应该能够弄清楚。无论如何,感谢您对此的帮助!我从来没有想过要通过和选择方法进行分组。我在网上找到的东西似乎令人困惑,不确定它是否适用于我,但多亏了你们,你们让它变得有意义!