Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将这些类似的linq查询组合成一个查询?_C#_Linq - Fatal编程技术网

C# 如何将这些类似的linq查询组合成一个查询?

C# 如何将这些类似的linq查询组合成一个查询?,c#,linq,C#,Linq,这可能是一个基本的LINQ问题。我需要选择一个对象,如果为空,则选择另一个。我正在以以下方式使用linq to对象,我知道这可以更快、更好、更干净地完成 public Attrib DetermineAttribution(Data data) { var one = from c in data.actions where c.actionType == Action.ActionTypeOne

这可能是一个基本的LINQ问题。我需要选择一个对象,如果为空,则选择另一个。我正在以以下方式使用linq to对象,我知道这可以更快、更好、更干净地完成

    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子句上有所不同,我知道有一种方法可以将它们结合起来。如有任何想法,将不胜感激

 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();
但这并不保证ActionTypeOne会在ActionTypeTwo之前找到。它查找第一条记录,即ActionTypeOne或ActionTypeTwo


但这并不保证ActionTypeOne会在ActionTypeTwo之前找到。它查找第一条记录,即ActionTypeOne或ActionTypeTwo。

这不使用查询语法,但它保留了以下逻辑:类型为
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();
}

这不使用查询语法,但它保留了
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();
}
我建议:

 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();
 }
公共属性确定分布(数据)
{
var types=Enum.GetValues(typeof(Action)).Cast();
var merged=来自data.actions中的c
从t型开始
其中c.actionType==t
选择新属性{id=c.id,name=c.name};
返回merged.FirstOrDefault();
}
我建议:

 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();
 }
公共属性确定分布(数据)
{
var types=Enum.GetValues(typeof(Action)).Cast();
var merged=来自data.actions中的c
从t型开始
其中c.actionType==t
选择新属性{id=c.id,name=c.name};
返回merged.FirstOrDefault();
}
等效的SQL查询是(我使用了Case语句,因为我不知道ActionType列的数据类型):

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


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

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;
}

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

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;
}

您可以使用orderby来确保项目的检索顺序。@codymanix:您必须指定一个自定义比较器,以便在
ActionTypeOne
类型的元素之前返回
ActionTypeTwo
类型的元素(不能保证默认情况下它们会按这种方式排序)。它还需要一些可以在线性时间内运行的东西,并将其转换为n个log(n)。99%的时间都不重要,但需要注意的是。您可以使用orderby来确保检索项目的顺序。@codymanix:您必须指定一个自定义比较器,以便在返回
ActionTypeOne
类型的元素之前返回
ActionTypeTwo
(不能保证默认情况下它们会按这种方式排序)。它还需要一些可以在线性时间内运行的内容,并将其转换为n个日志(n)。99%的时间都不重要,但需要注意一些内容。您应该使用.Any()而不是.Count().Count()遍历整个序列,而Any只检查第一个项是否存在。@MikeD:应该注意的是,上面的内容没有编译,因为如果两个序列都没有您要查找的项,则不会返回值。对不起,我试图在SO窗口中将我的方法清理为简洁的内容,显然是tooke太多了。您应该使用.Any()而不是.Count().Count()遍历整个序列,而Any只检查第一个项是否存在。@MikeD:应该注意的是,上面的内容没有编译,因为如果两个序列都没有您要查找的项,则不会返回值。对不起,我试图在SO窗口中将我的方法清理为简洁的内容,显然是tooke太多了。