簡體   English   中英

如何 LINQ 按對象列表過濾 dbset

[英]How to LINQ filter dbset by list of objects

我正在嘗試使用 SomeModel 的 IEnumerable 請求過濾此類偽結構(field1,field2,field3)的實體的數據庫集,其中 SomeModel 包含對(field1,field2)(相同的字段子集)

我試過了

var ordersList3 = await _dbContext.MyEntities.
AsNoTracking().
Where(a => request.Contains(new SomeModel() { field1 = a.field1, field2 = a.field2})).
ToListAsync();

但它不起作用

您能否建議通過包含字段子集的模型列表過濾數據庫集的正確方法?

我不知道這是否對你來說是必要的,但有時你需要直接寫下表達式。 因為這可能很有趣,所以這里是 go:

public static Expression<Func<PseudoStructure, bool>> GetPredicate<PseudoStructure>(
    IEnumerable<PseudoStructure> request) {
    var parameter = Expression.Parameter(typeof(PseudoStructure), "o");
    var expression = request.Aggregate(
        (Expression)null,
        (acc, next) => MakeBinary(
            acc, 
            CompareInstances(parameter, next),
            ExpressionType.Or));
    return Expression.Lambda<Func<PseudoStructure, bool>>(expression, parameter);
}

此方法生成一個 Expression<Func<PseudoStructure, bool>> ,其中包含檢查實例相等性的表達式:

private static Expression CompareInstances<PseudoStructure>(
    ParameterExpression parameter,
    PseudoStructure constant) 
        => typeof(PseudoStructure)
        .GetFields()
        .Select(fieldInfo => Expression.Equal(
            Expression.Constant(fieldInfo.GetValue(constant)),
            Expression.Field(parameter, fieldInfo)))
        .Aggregate(
            (Expression)null,
            (expression, binaryExpression) => MakeBinary(expression, binaryExpression, ExpressionType.And)
        );
    }
}

請注意,相等意味着字段值的相等。 MakeBinary 是 Expression.MakeBinary 的簡單包裝器:

private static Expression MakeBinary(Expression left, Expression right, ExpressionType expressionType)
    => left == null || right == null ?
        left ?? right
        : Expression.MakeBinary(expressionType, left, right);

您可以像這樣使用它:

public struct Foo
{
    public int A;
    public decimal B;
    public decimal C;
} 

var values = new List<Foo> {
    new Foo {A = 1, B = 2, C = 3},
    new Foo {A = 4, B = 5, C = 6},
    new Foo {A = 7, B = 8, C = 9},
    new Foo {A = 10, B = 11, C = 12}
};

var expression =
    GetPredicate(new[] { 
        new Foo {A = 1, B = 2, C = 3}, 
        new Foo {A = 10, B = 11, C = 12}
    });

var result = values.AsQueryable().Where(expression).ToList();

您收到錯誤是因為實體框架無法轉換為 sql 查詢表達式。 這是由於 where 子句中的謂詞。 正確的實現是:

var ordersList3 = await _dbContext.MyEntities.
AsNoTracking().
Where(a => request.Any(r => r.field1 == a.field1 && r.field2 == a.field2})).
ToListAsync();

暫無
暫無

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

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