簡體   English   中英

有條件地組合函數以創建 Linq 濾波器

[英]Combining functions conditionally to create Linq filter

我有一個要有條件地查詢的測試實體存儲庫和測試實體過濾器。

測試實體過濾器如下所示:

    public class TestEntityFilter
    {
        public string Name { get; set; } = null!;
        public string Type { get; set; } = null!;
        public Status? Status { get; set; }
        public int Take { get; set; }
        public int PageNumber { get; set; }
    }

我希望查詢在NameTypeStatus為 null 時返回所有內容,並在它們不是時使用給定值進行過濾。 如果其中一個是 null,它將被忽略,另外兩個將用於過濾。 對於這個條件查詢,我嘗試有條件地創建一個函數並根據值組合它們,但我的存儲庫方法看起來並不像它不起作用。 解決此類問題的最佳方法是什么?

        public async Task<IEnumerable<TestEntity>> GetTestEntitiesAsync(TestEntityFilter testEntityFilter, CancellationToken cancellationToken)
        {
            var combinedFilter = BuildFilers(testEntityFilter);
            return await _dbContext.TestEntity
                .Where(testEntity => combinedFilter(testEntity))
                .ToListAsync(cancellationToken);
        }
            
            
            
        public Func<TestEntity, bool> BuildFilers(TestEntityFilter testEntityFilter)    
        {   
            Func<TestEntity, bool> mainFilter = testEntityFilter => true;
            Func<TestEntity, bool> filterByName = string.IsNullOrEmpty(testEntityFilter.Name) ? 
                (TestEntity j) => true :
                (TestEntity j) => testEntityFilter.Name == j.Name;

            Func<TestEntity, bool> filterByType = string.IsNullOrEmpty(testEntityFilter.Type) ?
                (TestEntity j) => true :
                (TestEntity j) => testEntityFilter.Type == j.Type; 

            Func<TestEntity, bool> filterByStatus = testEntityFilter.Status is null?
                (TestEntity j) => true :
                (TestEntity j) => testEntityFilter.Status == j.Status;

            Func<TestEntity, bool> combinedFilter = (TestEntity j) => mainFilter(j) && filterByName(j) && filterByType(j) && filterByStatus(j);
        }

使用過濾器運行上述方法會引發以下異常:

'The LINQ expression 'DbSet<TestEntity>()
    .Where(j => Invoke(__combinedFilter_0, j))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.

您可以結合Where條件

var res = _db.TestEntity;
if (!string.IsNullOrWhiteSpace(filter.Name))
    res = res.Where(x => x.Name = filter.Name)
        
if (!string.IsNullOrWhiteSpace(filter.Status))
    res = res.Where(x => x.Status = filter.Status)
        
// .. rest
            
return await res.ToListAsync(cancellationToken);

你可以試試這個:

public async Task<IEnumerable<TestEntity>> GetTestEntitiesAsync(TestEntityFilter testEntityFilter, CancellationToken cancellationToken)
    {
        var combinedFilter = BuildFilers(testEntityFilter);

        var data = BuildFilers(_dbContext.TestEntity.AsQueryable(), testEntityFilter);

        return await data.ToListAsync(cancellationToken);
    }



    public IQueryable<TestEntity> BuildFilers(IQueryable<TestEntity> entities, TestEntityFilter testEntityFilter)
    {
        if (string.IsNullOrEmpty(testEntityFilter.Name))
        {
            entities = entities.Where(j => testEntityFilter.Name == j.Name);
        }

        if (string.IsNullOrEmpty(testEntityFilter.Type))
        {
            entities = entities.Where(j => testEntityFilter.Type == j.Type);
        }

        if (testEntityFilter.Status.HasValue)
        {
            entities = entities.Where(j => testEntityFilter.Status == j.Status);
        }

        return entities;
    }

暫無
暫無

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

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