簡體   English   中英

在LINQ查詢中的對象構造之后立即調用方法

[英]Call method immediately after object construction in LINQ query

我有一些實現這個接口的對象:

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

通常當我從db中選擇一些東西時,我會去:

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,我想使用AsParallel,從而使用LINQ。

我已經對它進行了一些測試,並且它加速了很多東西(IRow.Fill使用Reflection,因此在CPU上很難)

無論如何我的問題是,我如何創建一個LINQ查詢,它調用Fills作為查詢的一部分,所以它是否正確並行化?

為了測試性能,我創建了一個構造函數,它將DataRow作為參數,但是如果可能的話,我真的很想避免這種情況。

有了構造函數,它顯然很簡單:

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

但是就像我說的,我真的很想能夠將我的Fill方法填充到LINQ查詢中,因此不需要構造函數重載。

你需要創建一個多語句lambda表達式,如下所示:

table.AsEnumerable().AsParallel().Select(dr => 
    IRow row = new MySQLRow(); 
    row.Fill(dr);
    return row;
});

答案很幸運很簡單。 就這么做:)沒有什么可以阻止你在查詢的選擇部分中簡單地調用一個方法

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

如果你不能把它分配給Func,我不確定你能把lambda放在那里(自從我有機會寫LINQ以來已經有幾年了)

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

然后在你的select子句中調用它

我認為沒有辦法將命令式操作(例如調用返回voidFill方法)放入LINQ查詢語法中,但是你可以使用顯式調用Select方法做同樣的事情,它允許你使用任意代碼:

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

您需要添加對Cast的調用(因為DataSet不實現IEnumerable通用版本),其余的代碼非常簡單。 您的原始查詢將轉換為這些調用。

如果你想做一些技巧,你可以修改界面,這樣Fill方法返回一些東西(例如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;

可以使用返回某些內容的技巧調用方法,但不能使用返回void方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM