如果使用lambda表达式找不到匹配项,则获取与null值关联的记录

时间:2018-03-16 00:56:26

标签: c# linq lambda

我要求优惠券与每个州相关联。下面是表格结构

╔═════════╦═══════╗
║ Coupon  ║ State ║
╠═════════╬═══════╣
║ Coupon1 ║ CA    ║
║ Coupon2 ║ CA    ║
║ Coupon3 ║ NULL  ║
╚═════════╩═══════╝

如果没有找到该州的优惠券,则默认优惠券将显示给用户。如何以这种方式更改以下lambda表达式以实现结果。例如,如果传入状态为“CA”,则下面的表达式返回两个值并获取第一个集合而不是获得准确的结果(获得与CA关联的优惠券,因为已经找到了)

var loggedinUserCoupons = loggedinUser.Coupons.Where(x => x.StateId == loggedinUsers.StateID || x.StateId == null).FirstOrDefault();

2 个答案:

答案 0 :(得分:2)

DefaultIfEmpty功能可让您在主查询未返回任何结果时提供后备:

var fallback = loggedinUser.Coupons
                           .Where(x => x.StateId == null)
                           .First();
var loggedinUserCoupons = loggedinUser.Coupons
                                      .Where(x => x.StateId == loggedinUsers.StateID)
                                      .DefaultIfEmpty(fallback);

如果仅枚举源一次非常重要,您可以使用:

IEnumerable<T> WhereWithDefault<T>(this IEnumerable<T> source,
                                   Predicate<T> primaryCondition,
                                   Predicate<T> fallbackCondition)
{
    var fallback = new List<T>();
    bool foundPrimary = false;
    foreach( T t in source ) {
        if (primaryCondition(t)) { foundPrimary = true; fallback.Clear(); yield return t; }
        else if (!foundPrimary && fallbackCondition(t)) { fallback.Add(t); }
    }
    if (foundPrimary) yield break;
    foreach (T t in fallback) yield return t;
}

var loggedinUserCoupons = loggedinUser.Coupons
                                      .WhereWithDefault(x => x.StateId == loggedinUsers.StateID, x => x.StateId == null);

但请注意,第一种方法对于LINQ-to-SQL更好,因为数据库只需返回与两个ID匹配的对象,而不是整个表。

答案 1 :(得分:0)

您需要分两步完成此操作。

首先,尝试查找状态ID为Coupon的所有CA,如下所示:

var loggedinUserCoupons = 
            loggedinUser.Coupons
                        .Where(x => x.StateId == loggedinUsers.StateID)
                        .ToList();

如果找不到任何元素,那么我们可以获得您提供的默认Coupon

if(loggedinUserCoupons.Count == 0)
   loggedinUserCoupons = new List<Coupon>() {
                         loggedinUser.Coupons
                                     .FirstOrDefault(x => x.StateId == null) };

如果列表末尾总是有一个默认的Coupon,那么您可以这样做:

 if(loggedinUserCoupons.Count == 0)
       loggedinUserCoupons = new List<Coupon>() {
                             loggedinUser.Coupons
                                         .Last() };