如何将这些类似的linq查询合并为一个?

时间:2010-05-04 15:19:59

标签: c# linq

这可能是一个基本的LINQ问题。我需要选择一个对象,如果为null则选择另一个对象。我正在以下列方式使用linq对象,我知道可以更快,更好,更清洁......

    public Attrib DetermineAttribution(Data data)
    {

        var one = from c in data.actions
                           where c.actionType == Action.ActionTypeOne
                           select new Attrib 
                                      {
                                          id = c.id,
                                          name = c.name
                                      };
        if( one.Count() > 0)
            return one.First();

        var two = from c in data.actions
                  where c.actionType == Action.ActionTypeTwo
                  select new Attrib
                             {
                                 id = c.id,
                                 name = c.name
                             };
        if (two.Count() > 0 )
            return two.First();

  }

两个linq操作仅在where子句上有所不同,我知道有一种方法可以将它们组合在一起。任何想法都将不胜感激。

5 个答案:

答案 0 :(得分:6)

我认为这个解决方案简单而有效:

public Attrib DetermineAttribution(Data data)
{
    var c = data.actions.FirstOrDefault(c => c.actionType == Action.ActionTypeOne) ??
            data.actions.FirstOrDefault(c => c.actionType == Action.ActionTypeTwo);
    return c != null ? new Attrib { id = c.id, name = c.name } : null;
}

答案 1 :(得分:1)

这不使用查询语法,但它保留了类型ActionTypeOne的元素在ActionTypeTwo元素之前返回的逻辑。由于延迟评估,除非没有ActionTypeOne类型的元素,否则不会执行第二个查询。

public Attrib DetermineAttribution(Data data)
{

    return data.actions.Where( c => c.actionType == Action.ActionTypeOne)
              .Concat( data.actions.Where( c.actionType == Action.ActionTypeTwo ) )
              .Select( c => new Attrib
                         {
                             id = c.id,
                             name = c.name
                         })
              .FirstOrDefault();
}

答案 2 :(得分:0)

 var one = (from c in data.actions
                           where (c.actionType == Action.ActionTypeOne) || (c.actionType == Action.ActionTypeTwo)
                           select new Attrib 
                                      {
                                          id = c.id,
                                          name = c.name
                                      }).FirstOrDefault();

这并不能保证在ActionTypeTwo之前找到ActionTypeOne。它找到第一个记录,即ActionTypeOne ActionTypeTwo。

答案 3 :(得分:0)

我建议:

 public Attrib DetermineAttribution(Data data)
 {
        var types = Enum.GetValues(typeof (Action)).Cast<Action>();
        var merged = from c in data.actions
                     from t in types
                     where c.actionType == t
                     select new Attrib {id = c.id, name = c.name};

        return merged.FirstOrDefault();
 }

答案 4 :(得分:0)

 var one =  from c in data.actions
                where c.actionType == Action.ActionTypeOne
                    || c.actionType == Action.ActionTypeTwo
                orderby c.actionType == Action.ActionTypeOne ? 0 : 1
                select new Attrib 
                                {
                                  id = c.id,
                                  name = c.name
                                }).FirstOrDefault();

等效的SQL查询将是(我使用了Case语句,因为我不知道ActionType列的数据类型):

Select TOP 1 id, name
From Actions
where ActionType In(ActionTypeOne, ActionTypeTwo)
Order By Case ActionType When 1 Then 0 Else 1 End ASC