我有问题。我收到了“已添加相同密钥的项目”。我尝试枚举查询结果时出现异常。当我尝试在最终查询中包含来自相同原始变量的表达式时,会发生这种情况。我试图通过复制表达来解决这个问题,但无济于事:
var predicate1 = PredicateBuilder.True<SomeType>();
var predicate2 = PredicateBuilder.True<SomeType>();
var predicate3 = PredicateBuilder.True<SomeType>();
System.Linq.Expressions.Expression<Func<FieldObservation, bool>> predicate1copy1 = System.Linq.Expressions.Expression.Lambda<Func<FieldObservation, bool>>(predicate1.Body, predicate1.Parameters);
System.Linq.Expressions.Expression<Func<FieldObservation, bool>> predicate1copy2 = System.Linq.Expressions.Expression.Lambda<Func<FieldObservation, bool>>(predicate1.Body, predicate1.Parameters);
predicate2 = x => x.FirstBoolProperty;
predicate2 = predicate2.And(predicate1copy1);
predicate3 = x => x.SecondBoolProperty;
predicate3 = predicate3.And(predicate1copy2); //predicate1copy2 comes from the same original predicate1
var predicate4 = predicate2.Or(predicate3);
var results1 = query.Where(predicate4).ToList(); //exception thrown here: "An item with the same key has already been added."
我正在使用Linq来Nhibernate。这是堆栈跟踪。谁能解释一下呢?
Stacktrace:
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at NHibernate.Linq.Visitors.ExpressionParameterVisitor.VisitConstantExpression(ConstantExpression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\ExpressionParameterVisitor.cs:line 43
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression) in :line 0
at NHibernate.Linq.Visitors.NhExpressionTreeVisitor.VisitExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\NhExpressionTreeVisitor.cs:line 32
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression) in :line 0
at NHibernate.Linq.Visitors.NhExpressionTreeVisitor.VisitExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\NhExpressionTreeVisitor.cs:line 32
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitBinaryExpression(BinaryExpression expression) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression) in :line 0
at NHibernate.Linq.Visitors.NhExpressionTreeVisitor.VisitExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\NhExpressionTreeVisitor.cs:line 32
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitLambdaExpression(LambdaExpression expression) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression) in :line 0
at NHibernate.Linq.Visitors.NhExpressionTreeVisitor.VisitExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\NhExpressionTreeVisitor.cs:line 32
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitUnaryExpression(UnaryExpression expression) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression) in :line 0
at NHibernate.Linq.Visitors.NhExpressionTreeVisitor.VisitExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\NhExpressionTreeVisitor.cs:line 32
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitAndConvert[T](T expression, String methodName) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.<>c__DisplayClass6`1.<VisitAndConvert>b__5(T expression) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitList[T](ReadOnlyCollection`1 list, Func`2 visitMethod) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitAndConvert[T](ReadOnlyCollection`1 expressions, String callerName) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitMethodCallExpression(MethodCallExpression expression) in :line 0
at Remotion.Linq.Parsing.ExpressionTreeVisitor.VisitExpression(Expression expression) in :line 0
at NHibernate.Linq.Visitors.NhExpressionTreeVisitor.VisitExpression(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\NhExpressionTreeVisitor.cs:line 32
at NHibernate.Linq.Visitors.ExpressionParameterVisitor.Visit(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\Visitors\ExpressionParameterVisitor.cs:line 21
at NHibernate.Linq.NhLinqExpression..ctor(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\NhLinqExpression.cs:line 38
at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\DefaultQueryProvider.cs:line 67
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\DefaultQueryProvider.cs:line 33
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression) in d:\CSharp\NH\NH\nhibernate\src\NHibernate\Linq\DefaultQueryProvider.cs:line 40
at Remotion.Linq.QueryableBase`1.GetEnumerator() in :line 0
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at FieldSystemCore.Reports.ObservationReport.ObservationReportSearch.getResults(ObservationReportConfigurationObject config) in C:\Users\Isaac.G\Desktop\checkout\Field System\FieldSystem\FieldSystemCore\Reports\ObservationReport\ObservationReportSearch.cs:line 39
at FieldSystemGUI.Controls.Reports.ObservationReport.ObservationReport_ReportSearchEvent(Object sender, DoWorkEventArgs e) in C:\Users\Isaac.G\Desktop\checkout\Field System\FieldSystem\FieldSystemGUI\Controls\Reports\ObservationReport.cs:line 99
at GUIComponents.Controls.Reports.BaseCommonReport.backgroundWorker_DoWork(Object sender, DoWorkEventArgs e) in C:\Users\Isaac.G\Desktop\checkout\Library Projects\GUIComponents\GUIComponents\Controls\Reports\BaseCommonReport.cs:line 194
at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
答案 0 :(得分:1)
这是一个长期猜测。
您可以将其添加到predicatebuilder类
的副本中public static Expression<Func<T, bool>> Copy<T>
(this Expression<Func<T, bool>> expr1)
{
return Expression.Lambda<Func<T, bool>>(expr1.Body, expr1.Parameters);
}
然后使用它:
predicate3 = predicate3.And(predicate1.Copy());
可能无法解决您的重复密钥问题 - 我没有看到任何字典涉及。你在猜什么?
答案 1 :(得分:1)
我刚尝试了LINQ to Objects,LINQ to SQL和LINQ to Entities中的示例,并且它在所有这些中都运行良好(只需稍加调整)。您可能希望将其作为错误报告给LINQ to NHibernate团队。
为了“复制”表达式树,你必须使用类似ExpressionVisitor
之类的东西来复制该树的每个节点,这很麻烦,可能会或可能不会最终修复你的问题。
根据代码的结构,一种解决方法可能是重复原始表达式树两次,通过传入第一个产生该表达式的内容:
Func<Expression<Func<SomeType, bool>>> predicate1Builder =
() => PredicateBuilder.True<SomeType>();
var predicate2 = PredicateBuilder.True<SomeType>();
var predicate3 = PredicateBuilder.True<SomeType>();
predicate2 = x => x.FirstBoolProperty;
predicate2 = predicate2.And(predicate1Builder());
predicate3 = x => x.SecondBoolProperty;
predicate3 = predicate3.And(predicate1Builder());
var predicate4 = predicate2.Or(predicate3);
var results1 = query.Where(predicate4).ToList();
我只花了一些时间阅读ExpressionVisitors,看起来它可能并不那么困难。看看是否有效:
public class Visitor : ExpressionVisitor
{
public Expression<T> Modify<T>(Expression<T> node) {return (Expression<T>)Visit(node);}
}
var predicate1 = PredicateBuilder.True<SomeType>();
var predicate2 = PredicateBuilder.True<SomeType>();
var predicate3 = PredicateBuilder.True<SomeType>();
predicate2 = x => x.FirstBoolProperty;
predicate2 = predicate2.And(predicate1);
predicate3 = x => x.SecondBoolProperty;
var copy = new Visitor().Modify(predicate1);
predicate3 = predicate3.And(copy);
var predicate4 = predicate2.Or(predicate3);
var results1 = query.Where(predicate4).ToList();