Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在表达式树中使用局部变量_C#_Linq_Entity Framework 5_Expression Trees - Fatal编程技术网

C# 在表达式树中使用局部变量

C# 在表达式树中使用局部变量,c#,linq,entity-framework-5,expression-trees,C#,Linq,Entity Framework 5,Expression Trees,我有一个LINQ表达式,用于查找给定客户信用余额的所有历史变化: var history = GetHistory(id); var changes = history.Where(x => history.Where(y => y.AuditId < x.AuditId) .OrderByDescending(y => y.AuditId)

我有一个LINQ表达式,用于查找给定客户信用余额的所有历史变化:

var history = GetHistory(id);
var changes = history.Where(x => history.Where(y => y.AuditId < x.AuditId)
                                        .OrderByDescending(y => y.AuditId)
                                        .Select(y => y.CreditBalance)
                                        .FirstOrDefault() != x.CreditBalance);
var history=GetHistory(id);
var changes=历史记录。其中(x=>history.Where(y=>y.auditdy.D)
.选择(y=>y.CreditBalance)
.FirstOrDefault()!=x.CreditBalance);
此函数按预期工作。我想做的是更改此函数,以允许用户查询对任何历史字段的更改。我选择的解决方法是使用表达式树

到目前为止,我已经提出了以下解决方案:

var history = GetHistory(id);
var c = Expression.Parameter(typeof(Customer_history), "c");
var d = Expression.Parameter(typeof(Customer_history), "d");
var cAudit = Expression.Property(c, typeof(Customer_history).GetProperty("AuditId"));
var dAudit = Expression.Property(d, typeof(Customer_history).GetProperty("AuditId"));

var whereBody = Expression.LessThan(dAudit, cAudit);
var whereLambda = Expression.Lambda(whereBody, d);
var where = Methods.QueryableWhere.MakeGenericMethod(typeof(Customer_history));

var whereCall = Expression.Call(null, where, **Expression.Constant(history)**, whereLambda);

var orderByLambda = Expression.Lambda(dAudit, d);

var orderBy = Methods.QueryableOrderByDescending.MakeGenericMethod(typeof(Customer_history), orderByLambda.Body.Type);
var orderByCall = Expression.Call(null, orderBy, whereCall, orderByLambda);

var dProp = Expression.Property(d, typeof(Customer_history).GetProperty(field));
var selectLambda = Expression.Lambda(dProp, d);

var select = Methods.QueryableSelect.MakeGenericMethod(typeof(Customer_history), selectLambda.Body.Type);
var selectCall = Expression.Call(null, select, orderByCall, selectLambda);

var firstOrDefault = Methods.QueryableFirstOrDefault.MakeGenericMethod(selectLambda.Body.Type);
var firstOrDefaultCall = Expression.Call(null, firstOrDefault, selectCall);

var cProp = Expression.Property(c, typeof(Customer_history).GetProperty(field));
var comparison = Expression.NotEqual(firstOrDefaultCall, cProp);
var lambda = Expression.Lambda<Func<Customer_history, bool>>(comparison, c);

var changes = history.Where(lambda);
var history=GetHistory(id);
var c=表达式参数(类型(客户历史记录),“c”);
var d=表达式参数(typeof(Customer_history),“d”);
var cAudit=Expression.Property(c,typeof(Customer_history).GetProperty(“audit”);
var dAudit=Expression.Property(d,typeof(Customer_history).GetProperty(“audit”);
var whereBody=表达式.LessThan(dAudit,cAudit);
var whereLambda=表达式.Lambda(whereBody,d);
var where=Methods.QueryableWhere.MakeGenericMethod(typeof(Customer_history));
var whereCall=Expression.Call(null,其中,**Expression.Constant(history)**,whereLambda);
var orderByLambda=表达式.Lambda(dAudit,d);
var orderBy=Methods.QueryableOrderByDescending.MakeGenericMethod(typeof(Customer_history),orderbyrambda.Body.Type);
var orderByCall=Expression.Call(null,orderBy,whereCall,orderByLambda);
var dProp=Expression.Property(d,typeof(Customer_history).GetProperty(field));
var selectLambda=Expression.Lambda(dProp,d);
var select=Methods.QueryableSelect.MakeGenericMethod(typeof(Customer\u history),selectLambda.Body.Type);
var selectCall=Expression.Call(null、select、orderByCall、selectLambda);
var firstOrDefault=Methods.QueryableFirstOrDefault.MakeGenericMethod(selectLambda.Body.Type);
var firstOrDefaultCall=Expression.Call(null,firstOrDefault,selectCall);
var cProp=Expression.Property(c,typeof(Customer_history).GetProperty(field));
var比较=Expression.NotEqual(firstOrDefaultCall,cProp);
var lambda=表达式.lambda(比较,c);
var变化=历史。其中(λ);
问题是,我在执行查询时遇到了以下异常:

无法创建类型为的常量值 “名称空间。客户历史记录”。只有基元类型或枚举 在此上下文中支持类型

现在我假设问题是基于异常消息的Expression.Constant(history)语句。问题是,我不知道如何重写它以允许查询提供者适当地处理它。我知道这是因为原始查询的缘故,我只是不知道如何在表达式树中实现它


有人能提供任何方向吗?

正如人们所怀疑的那样,恒常表达式似乎不是从局部变量获取值的方法

我需要做的是创建一个私有类来存储变量,然后我就可以使用FieldMemberExpression访问它

private class ValueHolder<T>
{
      public IQueryable<T> History;
}
私人类价值持有人
{
公众可阅读的历史;
}
然后,在我的方法中,我能够使用以下公式计算表达式:

var valueHolder = new ValueHolder<T>
{
      History = data
};

var c = Expression.Parameter(typeof(T), "c");
var constantEx = Expression.Constant(valueHolder);
var fieldEx = Expression.Field(constantEx, valueHolder.GetType().GetField("History"));
var值持有人=新的值持有人
{
历史=数据
};
var c=表达式参数(类型(T),“c”);
var constantEx=表达式常数(valueHolder);
var fieldEx=Expression.Field(constantEx,valueHolder.GetType().GetField(“历史”));

您可以尝试使用动态linq,它允许您使用字符串作为表达式,而不是lambda

例如:

var query = history.Where("MyField = MyFilter");


如何允许您从条件访问局部变量?