- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Linq to SQL 执行一个非常简单的查询。我正在创建表达式,然后将其传递给 Where() 扩展方法。当我尝试实际执行查询时,Linq 内部会抛出 StackOverflowException。这是代码:
int expectedCount = 4;
Expression<Func<Thing, bool>> expression = ...;
//Expression looks like (LocaleID = 1 && GenderID ==1 && (TimeFrameID == 2007 || TimeFrameID == 2008))
using (XYZDataContext context = new XYZDataContext())
{
int count = context.Things.Where(expression).Count();
//...
}
.Lambda #Lambda1<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
.Invoke (.Lambda #Lambda2<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>)($o) & .Invoke (.Lambda #Lambda3<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>)($o)
}
.Lambda #Lambda2<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
.Invoke (.Lambda #Lambda4<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>)($o) & .Invoke (.Lambda #Lambda5<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>)($o)
}
.Lambda #Lambda3<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
.Invoke (.Lambda #Lambda6<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>)($o) | .Invoke (.Lambda #Lambda7<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>)($o)
}
.Lambda #Lambda4<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
$o.LocaleID == .Constant<System.Nullable`1[System.Int32]>(1)
}
.Lambda #Lambda5<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
$o.GenderID == .Constant<System.Nullable`1[System.Int32]>(1)
}
.Lambda #Lambda6<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
$o.TimeframeID == .Constant<System.Nullable`1[System.Int32]>(2007)
}
.Lambda #Lambda7<System.Func`2[XYZ.DataAccess.Thing,System.Boolean]>(XYZ.DataAccess.Thing $o)
{
$o.TimeframeID == .Constant<System.Nullable`1[System.Int32]>(2008)
}
((LocaleID == 1 && GenderID == 1) && (TimeFrameID == 2007 || TimeFrameID == 2008))
ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, object state, bool ignoreSyncCtx)
public class LinqSearchField<T, V> : ISearchField
{
public string Name { get; private set; }
public Expression<Func<T, V>> Selector { get; private set; }
public Expression<Func<T, bool>> LessThan(V value)
{
return Expression.Lambda<Func<T, bool>>(Expression.LessThan(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
}
public Expression<Func<T, bool>> LessThanOrEqual(V value)
{
return Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
}
public Expression<Func<T, bool>> Equal(V value)
{
return Expression.Lambda<Func<T, bool>>(Expression.Equal(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
}
public Expression<Func<T, bool>> NotEqual(V value)
{
return Expression.Lambda<Func<T, bool>>(Expression.NotEqual(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
}
public Expression<Func<T, bool>> GreaterThan(V value)
{
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
}
public Expression<Func<T, bool>> GreaterThanOrEqual(V value)
{
return Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(this.Selector.Body, GetConstant(value)), this.Selector.Parameters);
}
private ConstantExpression GetConstant(V value)
{
return Expression.Constant(value, typeof(V));
}
public Expression<Func<T, bool>> Null()
{
return Expression.Lambda<Func<T, bool>>(Expression.Equal(this.Selector.Body, Expression.Constant(null)), this.Selector.Parameters);
}
public Expression<Func<T, bool>> NotNull()
{
return Expression.Lambda<Func<T, bool>>(Expression.NotEqual(this.Selector.Body, Expression.Constant(null)), this.Selector.Parameters);
}
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
ParameterExpression[] parameters = expression1.Parameters.Union(expression2.Parameters).Distinct(new ParameterExpressionComparer()).ToArray();
InvocationExpression invocationExpression1 = Expression.Invoke(expression1, parameters);
InvocationExpression invocationExpression2 = Expression.Invoke(expression2, parameters);
Expression binaryExpression = null;
//And the current expression to the previous one.
binaryExpression = Expression.AndAlso(invocationExpression1, invocationExpression2); //Or OrElse.
//Wrap the expression in a lambda.
return Expression.Lambda<Func<T, bool>>(binaryExpression, parameters);
}
最佳答案
我最初有我的怀疑,但现在可以确认它。
您正在组合两个具有两个完全不同的参数实例的 lambda。参数实例是不可交换的,即使它们具有相同的名称和相同的类型。它们是不同范围内的有效参数。当您尝试使用错误的参数对象调用其中一个表达式时,就会出现困惑,在这种情况下,会出现堆栈溢出。
您应该做的是创建一个新的参数实例(或重用一个)并重新绑定(bind) lambda 的主体以使用该新参数。我怀疑这会解决这个问题。更进一步,您应该通过重建它们来正确组合这些表达式,而不是将它们作为方法调用修补在一起。我怀疑查询提供者是否会喜欢这些作为调用。
试试你的 And()
的这个实现和 Or()
方法与此辅助方法一起进行重新绑定(bind):
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
// reuse the first expression's parameter
var param = expression1.Parameters.Single();
var left = expression1.Body;
var right = RebindParameter(expression2.Body, expression2.Parameters.Single(), param);
var body = Expression.AndAlso(left, right);
return Expression.Lambda<Func<T, bool>>(body, param);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
var param = expression1.Parameters.Single();
var left = expression1.Body;
var right = RebindParameter(expression2.Body, expression2.Parameters.Single(), param);
var body = Expression.OrElse(left, right);
return Expression.Lambda<Func<T, bool>>(body, param);
}
private static Expression RebindParameter(Expression expr, ParameterExpression oldParam, ParameterExpression newParam)
{
switch (expr.NodeType)
{
case ExpressionType.Parameter:
var asParameterExpression = expr as ParameterExpression;
return (asParameterExpression.Name == oldParam.Name)
? newParam
: asParameterExpression;
case ExpressionType.MemberAccess:
var asMemberExpression = expr as MemberExpression;
return asMemberExpression.Update(
RebindParameter(asMemberExpression.Expression, oldParam, newParam));
case ExpressionType.AndAlso:
case ExpressionType.OrElse:
case ExpressionType.Equal:
case ExpressionType.NotEqual:
case ExpressionType.LessThan:
case ExpressionType.LessThanOrEqual:
case ExpressionType.GreaterThan:
case ExpressionType.GreaterThanOrEqual:
var asBinaryExpression = expr as BinaryExpression;
return asBinaryExpression.Update(
RebindParameter(asBinaryExpression.Left, oldParam, newParam),
asBinaryExpression.Conversion,
RebindParameter(asBinaryExpression.Right, oldParam, newParam));
case ExpressionType.Call:
var asMethodCallExpression = expr as MethodCallExpression;
return asMethodCallExpression.Update(
RebindParameter(asMethodCallExpression.Object, oldParam, newParam),
asMethodCallExpression.Arguments.Select(arg =>
RebindParameter(arg, oldParam, newParam)));
case ExpressionType.Invoke:
var asInvocationExpression = expr as InvocationExpression;
return asInvocationExpression.Update(
RebindParameter(asInvocationExpression.Expression, oldParam, newParam),
asInvocationExpression.Arguments.Select(arg =>
RebindParameter(arg, oldParam, newParam)));
case ExpressionType.Lambda:
var asLambdaExpression = expr as LambdaExpression;
return Expression.Lambda(
RebindParameter(asLambdaExpression.Body, oldParam, newParam),
asLambdaExpression.Parameters.Select(param =>
(ParameterExpression)RebindParameter(param, oldParam, newParam)));
default:
// you should add cases for any expression types that have subexpressions
return expr;
}
}
ParameterExpression
在表达式树中被另一个
ParameterExpression
的实例替换.这不会修改现有表达式,但会在需要时重建表达式以创建新更新的表达式。换句话说,它返回一个新的表达式,它应该被用来替换你正在重新绑定(bind)的那个。
Expression
并确定它是什么类型。如果是
ParameterExpression
,检查它是否与我们要查找的参数同名。如果是,则返回我们的新参数,否则返回它,因为我们不应该更改它。如果表达式不是参数,它可能是一个包含子表达式并且必须被替换的表达式。
BinaryExpression
将有
Left
操作数和
Right
操作数,两个表达式。它们都需要被反弹,因为它们的表达式树的某个地方可能是需要替换的参数。
Update()
方法将用具有新子表达式的类似表达式替换当前表达式。在这种情况下,我们只想(可能)更新
Left
和
Right
子表达式。
MethodCallExpression
和
InvocationExpression
有相同的想法,但它的树略有不同。它有
Object
表示您要调用的实例(或委托(delegate)/lambda)的表达式(或
Expression
在调用的情况下)。 (
MethodCallExpression
还有一个
MethodInfo
代表要调用的实例方法)他们也有
Arguments
(所有表达式)用作调用的参数。这些表达可能需要被反弹。
RebindParameter()
方法作为“ super ”-
Update()
更新整个表达式树中的参数的方法。
ExpressionVisitor
.希望我能早点注意到它。这将使重新绑定(bind)器更好地使用。而不是在这里发布完整的代码,这里是
pastebin .然后使用它:
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
// reuse the first expression's parameter
var param = expression1.Parameters.Single();
var left = expression1.Body;
var right = ParameterRebinder.Rebind(expression2.Body, expression2.Parameters.Single(), param);
var body = Expression.AndAlso(left, right);
return Expression.Lambda<Func<T, bool>>(body, param);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
{
var param = expression1.Parameters.Single();
var left = expression1.Body;
var right = ParameterRebinder.Rebind(expression2.Body, expression2.Parameters.Single(), param);
var body = Expression.OrElse(left, right);
return Expression.Lambda<Func<T, bool>>(body, param);
}
关于linq-to-sql - Linq to SQL 抛出 StackOverflowException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5744764/
dataElementsList : TypesAndData.DataElement list 是一个包含 50,000 条记录的列表(实际上更多,但让我们从小处开始)。我正在尝试序列化为 JSON
我试图序列化一个自定义类型,该类型在其他成员中包含一个字典。与字典的键和值相关联的类型是实现的接口(interface)。 字典看起来像 Dictionary TypeA implements IT
我有一个 C# 工厂对象,它使用对象列表作为源,通过工厂方法创建对象。 对象列表的创建方式如下: public WidgetFactory() { widgetLibrary
我正在 GenericList 类中实现递归快速排序方法。我将有第二种方法,它接受一个compareDelegate来比较不同的类型,但出于开发目的,我对GenericList进行排序。 我根据列表大
我为我的作业编写了一种方法,用于通过递归计算整数数组的所有排列。 (我正在尝试实现回溯算法)。但计算超过 7 个数字的前突变时会导致 StackOverflowException 。我不知道如何解决这
我正在尝试将一个大文件拆分成许多小文件。每个拆分发生的位置基于检查每个给定行的内容返回的谓词(isNextObject 函数)。 我试图通过 File.ReadLines 函数读取大文件,这样我就可以
我正在使用 onSuccessCallBack() 接口(interface)方法同步大量数据。按照如图所示的方法将数据发送到服务器。在这里我面临 StackOverflowException 的问题
我必须递归调用一个函数。但片刻之后它会抛出 StackOverFlowException。当我使用 Invoke(new Action(Start)) 方法时,它会抛出相同的异常,但不会在很长一段时间
我有一些依赖于 HttpContext.Cache 的代码,我希望它在满足特定条件时重新缓存某些内容。但是,这会引入潜在的堆栈溢出,我不确定这里的适当方法是什么。 看看这段代码: void OnCac
我将我的代码剥离到导致问题的部分。代码在这里来回跳转第5行和第9行,导致stackoverflowexception。 我该如何做呢?我需要 Game 类中的 Platform 实例才能在函数中使用。
我的问题很简单。我有这个新表格,我只是编写代码: public partial class Form1 : Form { public Form1() { In
根据我的question (通用方法的可重用非通用方法)我已经实现了提供的解决方案,但经过一些重构(将代码移动到基类)后,我的代码导致了我不理解的 StackOverflowException。 调用
背景。我的脚本在递归搜索大字符串中的特定文本时遇到 StackOverflowException。循环不是无限的;问题发生在 9,000-10,000 次合法搜索之间(对于特定搜索)——我需要它继续进
请帮助我解决 System.StackOverflowException我想用 .aspx 将记录写入数据库我使用 4 层架构来实现这一切都正常但是当我编译页面然后它显示要插入数据的字段时,当我将数据
我正在尝试回答 my own old question基于我唯一的(无效的)答案。 这个想法是为了简化按值排序的映射的创建: public class SortedByValueMap> implem
我目前正在制作有界数组堆栈。此方法将大于存储容量的数组抛出到 StackOverflowException,除了我不断收到“throws StackOverflowException 部分”的错误消息
我正在使用以下方法递归迭代对象的属性: void GetProps(object obj) { if (obj == null) return; var objType
我想做一个非常简单的任务,它以某种方式使程序崩溃。 我有一个包含数字的列表,所有数字都是唯一的。超过一定数量,我想倒序。 示例:5, 16, 11, 3, 8, 4 -> 5, 16, 11, 4,
我正在尝试编写一个函数来检查字符串是否为回文,并使用 this example ,我正在尝试使用递归匿名函数反转字符串: static Boolean checkPalindromeAnonRec(s
这段代码有什么问题?我不断收到 StackOverlflowException.. public class Places { public string Title { get; set;
我是一名优秀的程序员,十分优秀!