代码之家  ›  专栏  ›  技术社区  ›  Steffen

在linq查询中对象构造后立即调用方法

  •  4
  • Steffen  · 技术社区  · 15 年前

    我有一些实现这个接口的对象:

    public interface IRow
    {
      void Fill(DataRow dr);
    }
    

    通常,当我从数据库中选择一些内容时,我会:

    public IEnumerable<IRow> SelectSomeRows
    {
      DataTable table = GetTableFromDatabase();
      foreach (DataRow dr in table.Rows)
      {
        IRow row = new MySQLRow(); // Disregard the MySQLRow type, it's not important
        row.Fill(dr);
        yield return row;
      }
    }
    

    现在有了.net 4,我想使用阿斯巴利,因此linq。

    我对它做了一些测试,它加快了速度(irow.fill使用反射,所以对cpu很难)

    不管怎样,我的问题是,如何创建一个linq查询,它调用fill作为查询的一部分,所以它是正确并行的?

    为了测试性能,我创建了一个以datarow为参数的构造函数,但是 真正地 如果可能的话,我会尽量避免。

    有了构造函数,显然就足够简单了:

    public IEnumerable<IRow> SelectSomeRowsParallel
    {
      DataTable table = GetTableFromDatabase();
      return from DataRow dr in table.Rows.AsParallel()
             select new MySQLRow(dr);
    }
    

    不过,正如我所说的,我非常希望能够将我的fill方法填充到linq查询中,因此不需要构造函数重载。

    3 回复  |  直到 14 年前
        1
  •  4
  •   SLaks    15 年前

    您需要创建一个多语句lambda表达式,如下所示:

    table.AsEnumerable().AsParallel().Select(dr => 
        IRow row = new MySQLRow(); 
        row.Fill(dr);
        return row;
    });
    
        2
  •  1
  •   Tomas Petricek    15 年前

    我认为没有任何方法可以执行命令式操作(例如调用 Fill 返回的方法 void )在linq查询语法中,但是可以使用显式调用 Select 方法,它允许您使用任意代码:

    DataTable table = GetTableFromDatabase(); 
    return table.Rows.Cast<DataRow>().AsParallel().Select(dr => {
      IRow row = new MySQLRow(); 
      row.Fill(dr); 
      return dr; });
    

    您需要将呼叫添加到 Cast (因为数据集没有实现 IEnumerable )剩下的代码非常简单。您的原始查询将完全转换为这些调用。

    如果您想做一些技巧,可以修改接口,以便 填充 方法返回某些内容(例如 int )然后你可以用 let 子句并忽略返回值。

    return from DataRow dr in table.AsParallel() 
           let IRow row = new MySQLRow()
           let _ = row.Fill(dr) // ignoring return value; '_' is just variable name
           select row;
    

    可以使用这个技巧调用返回某些内容的方法,但不能使用返回的方法 无效 .

        3
  •  1
  •   Fermin    14 年前

    幸运的是,答案很简单。做吧:)没有什么能阻止您在查询的select部分简单地调用方法

    public IEnumerable<IRow> SelectSomeRowsParallel
            {
              DataTable table = GetTableFromDatabase();
              return from DataRow dr in table.Rows.AsParallel()
                     select (row => 
                             var mysqlRow = new MySQLRow()
                             mysqlRow.Fill(row);
                             return mysqlRow;)
            }
    

    如果你不能把lambda赋给func,我不确定你能不能把它塞进里面(我有机会写linq已经有几年了)

    Func<IRow,DataRow> getRow = 
                         (row => 
                         var mysqlRow = new MySQLRow()
                         mysqlRow.Fill(row);
                         return mysqlRow;)
    

    然后在select子句中调用它