Record我有一個搜索設定來根據條件回傳匹配的物件。它根據條件型別構建運算式樹并查詢資料庫以回傳匹配項。以前,它只匹配頂級屬性,但現在我試圖在子屬性中搜索Record并構建一個可以在查詢中與其他屬性組合的運算式。物件如下所示:
public class Record
{
public virtual ICollection<Attribute> Attributes { get; set; }
}
public class Attribute
{
public Guid AttributeId { get; set; }
public string Value { get; set; }
public virtual Record Record { get; set; }
}
AttributeId一個可能的標準是and的值對Value,為此我將回傳Record具有Attribute匹配這兩個值的所有行。例如,如果我只是撰寫一個簡單的 LINQ 查詢,它看起來像這樣:
Guid searchId = Guid.NewGuid();
string searchValue = "asdf";
IQueryable<Record> records = GetSomeQueryToRecords();
IEnumerable<Record> recordsThatMatch = records
.Where(r => r.Attribute.Any(a => a.AttributeId == searchId && a.Value == searchValue));
我需要將其構建到我的運算式樹中,以便它可以在記憶體中和 EF Core 查詢中作業。回傳的運算式GetExpression最終將與其他運算式組合使用AndAlso以構建大型查詢。我試過這個:
ParameterExpression record = Expression.Parameter(typeof(Record));
Expression searchExpression = GetExpression(record, searchId, searchValue);
Expression<Func<Record, bool>> lambda = Expression.Lamda<Func<Record, bool>>(searchExpression, record);
recordsThatMatch = records.Where(lambda);
private Expression GetExpression(ParameterExpression parameter, Guid searchId, string searchValue)
{
// Get the Record.Attributes Memboer.
MemberExpression attributes = Expression.Property(parameter, nameof(Record.Attributes));
// Get the "record.Attributes.Any(predicate)" Method.
MethodInfo anyMethod = typeof(Enumerable).GetMethods()
.Where(m => m.Name == nameof(Enumerable.Any))
.Where(m => m.GetParameters().Length == 2)
.Single();
// Make Method generic.
anyMethod = anyMethod.MakeGenericMethod(typeof(Attribute));
ParameterExpression attribute = Expression.Parameter(typeof(Attribute));
Expression idEqualExpression = Expression.Equal(
Expression.Property(attribute, nameof(Attribute.AttributeId)),
Expression.Constant(searchId)
);
Expression valueEqualExpression = Expression.Equal(
Expression.Property(attribute, nameof(Attribute.Value)),
Expression.Constant(searchValue)
);
Expression attributeMatchExpression = Expression.AndAlso(idEqualExpression, valueEqualExpression);
return Expression.Call(null, anyMethod, attributes, attributeMatchExpression);
}
不過,我得到了一個ArgumentExceptionwith Expression.Call,因為老實說,我不知道如何在這個特定的實體中使用它,而且它有很多覆寫。我相信我應該通過,null因為我實際上想要一個靜態方法作為.Any()擴展方法。
uj5u.com熱心網友回復:
您忘記創建“LambdaExpresson”。也Expression.Call可以簡化。
private Expression GetExpression(ParameterExpression parameter, Guid searchId, string searchValue)
{
// Get the Record.Attributes Memboer.
MemberExpression attributes = Expression.Property(parameter, nameof(Record.Attributes));
ParameterExpression attribute = Expression.Parameter(typeof(Attribute));
Expression idEqualExpression = Expression.Equal(
Expression.Property(attribute, nameof(Attribute.AttributeId)),
Expression.Constant(searchId)
);
Expression valueEqualExpression = Expression.Equal(
Expression.Property(attribute, nameof(Attribute.Value)),
Expression.Constant(searchValue)
);
Expression attributeMatchExpression = Expression.AndAlso(idEqualExpression, valueEqualExpression);
var matchLambda = Expression.Lambda(attributeMatchExpression, attribute);
return Expression.Call(typeof(Enumerable), nameof(Enumerable.Any), new [] {typeof(Attribute)}, attributes, matchLambda);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/476612.html
上一篇:給孩子時如何顯示祖父母
下一篇:linq查詢中的性能問題
