我在SharePoint中有一個Web部件,並且我嘗試使用列表中特定字段的唯一/不同值填充下拉控件。在LINQ中獲取不同值的更快方法?
不幸的是,由於系統的性質,它是一個文本字段,所以沒有其他確定的來源來獲取數據值(即,如果它是一個選擇字段,我可以獲得字段定義並且只是從那裏獲取值),並且我在隨後的CAML查詢中使用下拉列表中的所選值,因此值必須準確到列表項目上的值。目前該列表有arpprox。 4K項目,但它(並將繼續)增長緩慢。
而且,它是沙盒解決方案的一部分,所以它受到用戶代碼服務時間限制的限制 - 而且它往往會超時。在我的開發環境中,我在調試過程中逐步瞭解了代碼,看起來LINQ的那一行我實際上得到了不同的值,這是最耗時的,然後我完全調用了這個方法,超時停止,所以我相當肯定這是問題所在。
這裏是我的代碼:
private void AddUniqueValues(SPList list, SPField filterField, DropDownList dropDownControl)
{
SPQuery query = new SPQuery();
query.ViewFields = string.Format("<FieldRef Name='{0}' />", filterField.InternalName);
query.ViewFieldsOnly = true;
SPListItemCollection results = list.GetItems(query); // retrieves ~4K items
List<string> uniqueValues = results.Cast<SPListItem>().Select(item => item[filterField.Id].ToString()).Distinct().ToList(); // this takes too long with 4K items
uniqueValues.Sort();
dropDownControl.Items.AddRange(uniqueValues.Select(itm => new ListItem(itm)).ToArray());
}
據我所知,有沒有辦法讓直接在CAML查詢「獨特」的價值觀,所以我怎麼能更快地做到這一點?有沒有一種方法來重構LINQ運行速度更快?
有沒有一種簡單/快速的方式從客戶端做到這一點? (REST會是首選,但如果需要,我會做JSOM)。
以爲我會在這裏添加一些額外的信息,因爲我做了一些進一步的測試並發現了一些有趣的結果。
首先,解決是否需要Cast()
和Select()
的問題:是的,他們是。
SPListItemCollection
是IEnumerable
但不是IEnumerable<T>
,所以我們需要強制轉換才能夠使用LINQ。
那麼它轉換爲IEnumerable<SPListItem>
後,SPListItem
是一個相當複雜的對象,我期待從剛一個該對象的屬性找到不同的值。直接在IEnumerable<SPListItem>
上使用Distinct()
可以得到所有這些。所以我必須Select()
只是我想比較的單個值。
所以是的,Cast()
和Select()
是絕對必要的。
正如M.kazem Akhgary在評論中指出的那樣,在我最初的代碼行中,每次調用ToString()
(對於4K項)都會增加一些時間。但在測試一些其他的變化:
// original
List<string> uniqueValues = results.Cast<SPListItem>().Select(item => item[filterField.Id].ToString()).Distinct().ToList();
// hash set alternative
HashSet<object> items = new HashSet<object>(results.Cast<SPListItem>().Select(itm => itm[filterField.Id]));
// don't call ToString(), just deal with base objects
List<object> obs = results.Cast<SPListItem>().Select(itm => itm[filterField.Id]).Distinct().ToList();
// alternate LINQ syntax from Pieter_Daems answer, seems to remove the Cast()
var things = (from SPListItem item in results select item[filterField.Id]).Distinct().ToList();
我發現所有的這些方法了多個幾十秒完成。奇怪的是,從Pieter_Daems answer的DataTable
/DataView
方法,而我平添了幾分提取我想要的值:
DataTable dt = results2.GetDataTable();
DataView vw = new DataView(dt);
DataTable udt = vw.ToTable(true, filterField.InternalName);
List<string> rowValues = new List<string>();
foreach (DataRow row in udt.Rows)
{
rowValues.Add(row[filterField.InternalName].ToString());
}
rowValues.Sort();
了只有1-2秒!最後,我打算使用Thriggle's answer,因爲它可以很好地處理SharePoint的5000個項目列表視圖閾值,我可能會在某一天處理這個閾值,而且它的速度只會稍微慢於(2-3秒) DataTable
方法。還有很多,比所有LINQ快得多。
雖然有趣的是,從SPListItemCollection
的特定字段獲取不同值的最快方式似乎是DataTable
/DataView
轉換方法。
我認爲,這是因爲'項目[filterField.Id]的ToString()'一部分。 ToString方法是否被覆蓋?如果不是那麼它的基本上返回相同的字符串一遍又一遍,你不會從哈希中受益 –
你不能添加區別到檢索? 'SPListItemCollection results = list.GetItems(query).Distinct()'? –
'.Cast.Select.Unique()'linq需要執行多少時間? – TripleEEE