2

我有这个简单的课程:

public class JDEItemLotAvailability
    {
        public string Code { get; set; }
        public int ShortCode { get; set; }
        public string Description { get; set; }
        public string PrimaryUnitCode { get; set; }
        public string BranchPlant { get; set; }
        public string Location { get; set; }
        public string Lot { get; set; }
        public int AvailableQuantity { get; set; }
    }

我的 BLL 中的这个 DAL 方法返回它们的列表:

var returnedLotList = _JDE8dal.GetLotAvailabilityAsList(_lot);

我想在返回的列表中执行以下操作,并且我想以最“优雅”的 LINQ 方式进行操作。

我想检查列表中是否有符合特定条件的记录。我想过这样的事情:

  var query =
      returnedLotList.Where(l => l.AvailableQuantity != 0 && l.BranchPlant == _mcu && l.Location == _locn)
                               .OrderByDescending(l => l.AvailableQuantity);

但是我想说,如果上面的查询没有返回结果,我想取其余列表条目中的第一个。

我怎样才能做到这一点?

4

3 回答 3

3

你可以使用DefaultIfEmpty

//your first query, unaltered
var query =
      returnedLotList.Where(l => l.AvailableQuantity != 0 && l.BranchPlant == _mcu && l.Location == _locn)
                               .OrderByDescending(l => l.AvailableQuantity);

var query2 = query.DefaultIfEmpty(returnedLotList.Take(1));
于 2012-12-18T17:58:24.717 回答
0

您可以创建一个扩展方法来执行此操作:

public static IEnumerable<T> WhereOrFirstOfRest<T>(
    this IEnumerable<T> collection, Func<T, bool> predicate)
{
    var filtered = collection.Where(predicate);

    return filtered.Any() ? filtered : collection.Take(1);
}

这种扩展方法的缺点是它会多次迭代集合。当您处理流(例如来自数据库)时,这可能是一个问题。更有效的方法如下:

public static IEnumerable<T> WhereOrFirstOfRest<T>(
    this IEnumerable<T> collection, Func<T, bool> predicate)
{
    // Materialize the complete collection.
    collection = collection.ToArray();

    // Filter the collection. ToArray prevents calling the predicate
    // twice for any item.
    var filtered = collection.Where(predicate).ToArray();

    return filtered.Any() ? filtered : collection.Take(1);
}

尽管这样可以避免对数据库进行任何可能的额外调用,但这确实会在后台创建几个新数组。因此,最有效的方法应该是:

public static IEnumerable<T> WhereOrFirstOfRest<T>(
    this IEnumerable<T> collection, Func<T, bool> predicate)
{
    T firstItem = default(T);
    bool firstStored = false;
    bool predicateReturnedItems = false;

    foreach (var item in collection)
    {
        if (!firstStored)
        {
            firstItem = item;
            firstStored = true;   
        }

        if (predicate(item))
        {
            yield return item;
            predicateReturnedItems = true;
        }
    }

    if (!predicateReturnedItems && !first)
    {
        yield return firstItem;
    }
}
于 2012-12-18T17:57:44.793 回答
0

我不确定我是否理解,但可能是这样的:

var firstMatch = returnedLotList.FirstOrDefault(l => l.AvailableQuantity != 0 && 
                                                     l.BranchPlant == _mcu && 
                                                     l.Location == _locn);
if (firstMatch != null)
    return firstMatch;
int max = returnedLotList.Max(l => l.AvailableQuantity);
return returnedLotList.First(l => l.AvailableQuantity == max);
  • 如果不匹配,FirstOrDefault 将返回 null
  • 我认为拆分查询以更清楚地了解正在发生的事情是一个好主意。
于 2012-12-18T17:59:40.550 回答