亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在運行時使用屬性名稱和類型查詢 IQueryable

在運行時使用屬性名稱和類型查詢 IQueryable

C#
嗶嗶one 2023-05-14 16:13:27
我需要在運行時知道屬性名稱和類型來進行查詢。我已經使用了反射IEnumerable<>但是會因此出現性能問題嗎?我想知道是否有更好的方法來做到這一點IQueryable<>?我已經研究了一下,Expressions但我不太確定該怎么做。編輯:目前這似乎不是性能問題,但我還沒有測試過非常大的工作負載。我需要搜索運行時已知的多個不同類型的字段。var cosmosClient = new DocumentClient(new Uri(cosmosDBEndpointUrl), cosmosDBAuthorizationKey);var feedOptions = new FeedOptions { MaxItemCount = -1, EnableCrossPartitionQuery = true };var objects = cosmosClient.CreateDocumentQuery<MyObject>(collectionLink, feedOptions).AsEnumerable();if (!string.IsNullOrEmpty(searchQuery)){             var predicate = PredicateBuilder.New<MyObject>();     foreach (var fieldToSearch in fieldsToSearch)    {      predicate = predicate.Or(x => x.GetPropertyValue(fieldToSearch).CheckDateTime().ToString()                                     .Contains(searchQuery, StringComparison.InvariantCultureIgnoreCase));      objects = objects.Where(predicate);    }}objects = objects.Skip(index)                 .Take(pageSize);return objects.ToList();這個輔助方法:public static object GetPropertyValue(this object obj, string propertyName){    foreach (var part in propertyName.Split('.'))    {        if (obj == null) { return null; }        Type type = obj.GetType();        PropertyInfo info = type.GetProperty(part, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);        if (info == null) { return null; }        obj = info.GetValue(obj, null);    }    return obj;}我不知道在這種特殊情況下是否有更好的方法來做到這一點。
查看完整描述

1 回答

?
小怪獸愛吃肉

TA貢獻1852條經驗 獲得超1個贊

所以在這種情況下,我確實認為你想要?IQueryable而不是IEnumerable.?最容易記住的方法是將IEnumerable所有數據加載到內存中,然后運行其余的 LINQ 查詢,同時IQueryable嘗試在源上運行過濾器(如果它可以將結果數據加載到內存中)。您確實需要使用支持IQueryableLINQ to SQL 或 Entity Framework 的 ORM。對于 CosmosDB,SDK 構建在 LINQ to SQL 之上。

通過使用你將所有IEnumerable數據從 Cosmos加載到內存中,然后應用你的過濾器和分頁。當您只有幾條記錄時這很好,但是隨著數據集的增長,您可能可以想象這會如何成為一個主要問題。通常,您希望在數據庫中做盡可能多的工作,并且只返回最少數量的結果。這將遠遠超過使用反射構建謂詞的任何性能考慮因素。

的最好的部分之一IQueryable是它繼承自IEnumerable,因此任何與之一起工作的東西都IEnumerable將與IQueryable.?您需要做的就是擺脫您的AsEnumerable().


重要的是要注意,并非所有 LINQ 運算符都自動支持,一旦系統遇到無法翻譯的運算符,它就會執行目前已有的操作,并在內存中完成其余操作。文檔中有CosmosDB 的可用運算符列表。

對于您的查詢,最重要的是,雖然您的Where()條款得到支持,Skip()Take()目前不支持。這意味著每次執行此方法時,所有結果都將從 CosmosDB 返回,然后對分頁進行評估。

有幾種方法可以在 SDK 中處理分頁。當前支持的方式是將MaxItemCountinside your設置FeedOptions為您的頁面大小。Skip()當前系統使用延續令牌代替函數。為了訪問令牌,您可以使用AsDocumentQuery().?由于您必須逐頁瀏覽到下一頁,因此緩存令牌可能非常有幫助——跳來跳去很困難。

第二種選擇是使用 .Net SDK v3。它目前處于預覽階段,但可在 Nuget 上使用。幾個月前啟用了 skip/take。在這種情況下,在您調用之前的所有內容ToList()都應轉換為 SQL 并在 CosmosDB 中進行評估。


查看完整回答
反對 回復 2023-05-14
  • 1 回答
  • 0 關注
  • 139 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號