2016-07-05 54 views
1

我想調用每個記錄上的函數來設置一些字段值。當結果打算被分頁時,則通過以下方式實現:從精巧結果調用每個記錄上的函數

public IDataWrapper GetPagedQuery<T>(string myQuery, object param, Action<T> customAction) 
{ 
    var obj = new DataWrapper(); 
    using (var oConn = CreateConnection(ConnectionString)) 
    { 
     TotalPages totalRows = null; 
     var list = oConn.Query<T, TotalPages, T>(myQuery, (e, t) => 
     { 
      totalRows = t; 
      if (mapAction != null) customAction(e); 
      return e; 
     }, param, splitOn: "SplitOn"); 
     obj.RowsFound = (IEnumerable<dynamic>)list; 
     obj.TotalRows = totalRows == null ? 0 : totalRows.TotalRows; 
    } 
    return obj; 
} 

當結果不打算分頁時,我的問題就出現了。我在第一個例子中的查詢包括列拆分,這就是爲什麼它一切正常,但我的下一個查詢是一個簡單的查詢,如Select Column1, Column2 FROM MyAwesomeTable這將返回所有行,列等...

問題是,我仍然需要對每個返回的結果應用customAction。現在讓我們想象一下,有數百萬條記錄回來的潛力(相信我,根據我的情況,這不是不現實的),因此我不想循環播放每條記錄並應用我的方法,我希望這種方法就像在第一種情況下那樣,隨着小巧玲瓏正在返回結果。

這裏是我的嘗試:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction) 
{ 
    var obj = new DataWrapper(); 
    using (var oConn = CreateConnection(ConnectionString)) 
    { 
     var list = oConn.Query<T>(myQuery, (e) => 
     { 
      if (mapAction != null) customAction(e); 
      return e; 
     }, param).ToList(); 
     obj.RowsFound = (IEnumerable<dynamic>)list; 
     obj.TotalRows = list.Count(); 
    } 
    return obj; 
} 

我得到了上面的代碼中的錯誤,它無法解決方法Query<T>(etc...我的理解是,因爲它不存在。我在這裏問什麼是完成我所要做的最好的方法?是否有可能與精巧。

+0

您對SplitOn的理解不正確,其目的是映射1-1複雜實體,並且與分頁無關,可用於任何類型的查詢。當前代碼替換每條記錄的TotalRows,與Sql查詢獲取的重複值相同,本身並不是一個最佳用法,儘管您也可以用任意數量的記錄重複其他部分。另外,所有這些Dapper所做的處理是在內存中獲取數據後,如果您已明確應用Action –

+0

@MrinalKamboj,則無需過分擔心遍歷內存中的數據我相信我對SplitOn有很好的理解,您看不到的是我的完整的SQL語句。我可能在解釋問題中的這個部分方面做得不好,從而誤解。我所說的是,我的分頁使用了spliton列,因爲我們正在用查詢進行分頁,而不是分頁。長話短說,首先查詢使用SplitOn,其次不。我爲我的誤會道歉。 – Bojan

+0

以不同的方式理解我的觀點,您使用Func提供的SplitOn應用自定義操作,實際上即使在Spliton中,填充重複值也是不正確的。當Dapper實際上遍歷內存集合,因爲它是Linq 2對象提供者時,它的印象是,它不需要遍歷集合來這樣做。理想的方法是將SplitOn隨處移除,改爲使用QueryMultiple在單個調用中獲得單獨的結果,然後單獨應用您已接受的響應中顯示的操作 –

回答

1

恐怕簡短的答案是你不能這樣做。

稍長的答案是,在你的分頁查詢,它本質上第二次通過的數據,因爲小巧玲瓏的做了一些工作,每行的數據轉換成的「T」的實例,然後它使一個單獨的呼叫到您用來調用您的「customAction」的「地圖」方法。

因此,在做一個簡單的非分頁「conn.Query」調用之後,隨後執行您的customAction會發生很小的差異。像下面這樣:

public IDataWrapper GetNonPagedQuery<T>(string myQuery, object param, Action<T> customAction) 
{ 
    var obj = new DataWrapper(); 
    using (var oConn = CreateConnection(ConnectionString)) 
    { 
     var results = oConn 
      .Query<T>(myQuery) 
      .ToList(); 
     obj.TotalRows = results.Count(); 
     obj.RowsFound = results 
      .Select(value => 
      { 
       customAction(value); 
       return value; 
      }) 
      .Cast<dynamic>(); 
    } 
    return obj; 
} 

如果您關注的是,你可能被加載在非分頁查詢了很多很多的記錄那麼值得銘記所有的這些記錄將被加載到內存中一旦;當你枚舉返回的結果時,它們不會一次從數據庫中拉出來,這可能會造成資源的大量消耗(如果你談論的數據太多,以至於你想避免第二次枚舉) 。

這種情況是因爲SQL連接由於GetNonPagedQuery返回而關閉,因此無法保持打開狀態以根據調用者「按需」讀取數據。如果你真的在處理大量的數據,也許非分頁查詢不是最好的方法?

請注意,在上面的代碼中,「customAction」只會在行列舉時被調用,所以在GetNonPagedQuery返回之前不會全部觸發。如果「customAction」可能是一個昂貴的操作,那麼這可能對您有益。另一方面,如果你希望在GetNonPagedQuery返回之前爲每個結果調用「customAction」,那麼在Cast <動態>()之後,你需要再調用一次ToList(),這取決於哪種情況對你更有用。

0

是的,它可能是:

見小巧玲瓏文檔的部分約Type Switching per Row。我懷疑(即沒有自己嘗試過),如果您使用相同的系統通過讀取每行並將其明確處理,將結果按照您想要的格式進行處理,它將不起作用。