簡體   English   中英

實體框架核心 Lambda Function 未提前終止

[英]Entity Framwork Core Lambda Function not early terminating

我正在使用帶有實體框架的 asp.net 內核。

在進行 API 調用以獲取實體列表時,我在 json 中傳遞了一個可選過濾器,該過濾器可能如下所示:

{
  "name": "john",
  "customer.id": 1
}

在我的 ControllerAction 中,我首先反序列化 JSON,然后查詢數據庫。

var dynamicfilter = filter != null ? JsonConvert.DeserializeObject<Dictionary<string, string>>(filter) : new Dictionary<string, string>();

List<User> Users = _context.Users.Include(u => u.Customer).Where(u =>
    dynamicfilter.Keys.Count > 0 ? (
        (dynamicfilter.ContainsKey("name") ? u.Name.ToLower().Contains(dynamicfilter["name"].ToLower()) : true) &&
        (dynamicfilter.ContainsKey("customer.id") ? u.Customer.ID == Convert.ToInt32(dynamicfilter["customer.id"]) : true)
    ) : true).ToList();

只要設置了所有過濾器參數,它就可以工作。 如果未設置至少一個過濾器參數,則會拋出 null 引用,因為即使ContainsKey()false ,代碼之間的代碼是什么? 和:被執行。

但是如果我首先加載整個表並在本地應用過濾器,通過這樣做

List<User> Users = _context.Users.Include(u => u.Customer).ToList().Where(...

它就像一個魅力。 有沒有辦法讓它在數據庫端也能工作?

只需將邏輯移出查詢即可。 喜歡:

IQueryable<User> query = _context.Users.Include(u => u.Customer);
query = dynamicfilter.ContainsKey("name") 
    ? query.Where(u=>u.Name.ToLower().Contains(dynamicfilter["name"].ToLower()) 
    : query;
query = dynamicfilter.ContainsKey("customer.id") 
    ? query.Where(u=>u.Customer.ID == Convert.ToInt32(dynamicfilter["customer.id"])) 
    : query;

List<User> Users = query.ToList(); // DB query executed here

這樣,表達式樹將在query object 中構建,並且僅在嘗試枚舉時執行。 檢查 MS 文檔

此接口繼承了 IEnumerable 接口,因此如果它表示一個查詢,則可以枚舉該查詢的結果。 枚舉強制執行與 IQueryable object 關聯的表達式樹。 調用 Execute(Expression) 方法時會執行不返回可枚舉結果的查詢。

最重要的是,我建議在將其應用於查詢之前檢查所有傳入參數

if(dynamicfilter.ContainsKey("name") 
    && !string.IsNullOrWhitespace(dynamicfilter["name"]))
{
    var nameFilter = dynamicfilter["name"].ToLower();
    query = query.Where(u=>u.Name.ToLower().Contains(nameFilter);
}

暫無
暫無

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

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