如何使用LINQ在列表中生成重复项?

12

这是我使用的LINQ查询

var result = (from price in inventoryDb.Pricing.AsNoTracking()               
              where price.Quantity > 0m
              select new
              {
                 TagNo = price.TagNo,
                 SellingRate = price.SellingRate,
                 Quantity = price.Quantity           
              }).ToList();

根据数量的值,我需要在列表中生成重复项。

输出:

result = [0]{TagNo="100", SellingRate=1500.00, Quantity=1}
         [1]{TagNo="101", SellingRate=1600.00, Quantity=2}

期望结果:

result = [0]{TagNo="100", SellingRate=1500.00}
         [1]{TagNo="101", SellingRate=1600.00}
         [2]{TagNo="101", SellingRate=1600.00}
2个回答

11
你可以使用Enumerable.SelectMany + Enumerable.Range
var result = inventoryDb.Pricing.AsNoTracking()
    .Where(p => p.Quantity > 0m)
    .SelectMany(p => Enumerable.Range(0, p.Quantity)
        .Select(i => new
              {
                 TagNo = p.TagNo,
                 SellingRate = p.SellingRate      
              }))
    .ToList();

如果你的LINQ提供程序不支持这个(例如 Linq-To-Entities),最简单的方法是使用 Linq-To-Objects。为了避免将所有内容加载到内存中,应该在 Where 后使用 AsEnumerable

var result = inventoryDb.Pricing.AsNoTracking()
    .Where(p => p.Quantity > 0m)
    .AsEnumerable()
    .SelectMany(p => Enumerable.Range(0, p.Quantity)
        .Select(i => new
              {
                 TagNo = p.TagNo,
                 SellingRate = p.SellingRate      
              }))
    .ToList();

4

按照查询语法,只需添加Enumerable.Repeat,如下所示:

var result = (from price in inventoryDb.Pricing.AsNoTracking()
              where price.Quantity > 0m
              from dup in Enumerable.Repeat(0,price.Quantity)
              select new
              {
                 TagNo = price.TagNo,
                 SellingRate = price.SellingRate,          
              }).ToList();

如果实际上linq to entities不支持,则需要添加AsEnumerable,如下所示:
var result = (from price in inventoryDb.Pricing.AsNoTracking()
                                               .Where(p => p.Quantity > 0m)
                                               .AsEnumerable() //Loads only the filtered items to memory            
              from dup in Enumerable.Repeat(0,price.Quantity)
              select new
              {
                 TagNo = price.TagNo,
                 SellingRate = price.SellingRate,          
              }).ToList();

您也可以使用 Enumerable.Range,但由于您不使用该集合的值(并且在我看来仅仅是因为 Repeat 更好地描述了您正在做的事情),所以我决定只使用 Repeat


1
这是显而易见的LINQ To Objects解决方案。问题是,这是否适用于EF(请注意inventoryDb.Pricing.AsNoTracking())。我打赌会出现“NotSupportedException” :) - Ivan Stoev
1
@IvanStoev,在调用Enumerable.Repeat之前,只需添加.AsEnumerable()即可。 - kiziu
@IvanStoev - 感谢您的注意 :) 您是正确的,我忘记检查了。请查看更新 - Gilad Green
@kiziu - 感谢您的建议。 - Gilad Green

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接