当我向查询两次添加相同的表达式时,为什么会收到此Linq to Nhibernate异常? [英] Why am I getting this Linq to Nhibernate exception when I add the same expression to the query twice?

查看:98
本文介绍了当我向查询两次添加相同的表达式时,为什么会收到此Linq to Nhibernate异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题.我收到已经添加了具有相同键的项目".当我尝试枚举查询结果时出现异常.当我尝试在最终查询中包含来自相同原始变量的表达式时,就会发生这种情况.我试图通过复制表达式来解决此问题,但无济于事:

I have a problem. I'm getting an "An item with the same key has already been added." exception when I try to enumerate over the query results. It happens when I try to include an expression from the same original variable in the final query. I tried to get around this by copying the expression but to no avail:

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.这是堆栈跟踪.谁能解释一下?

I'm using Linq to Nhibernate. Here is the stacktrace. Can anyone explain this?

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)

推荐答案

我刚刚在LINQ to Objects,LINQ to SQL和LINQ to Entities中尝试了您的示例,并且在所有示例中都可以正常工作(稍作调整).您可能希望将其作为错误报告给LINQ to NHibernate团队.

I just tried your example in LINQ to Objects, LINQ to SQL, and LINQ to Entities, and it works fine in all of them (with minor tweaking). You may want to report it as a bug to the LINQ to NHibernate team.

为了复制"表达式树,您必须使用

In order to "copy" the expression tree, you'd have to copy every node of that tree using something like an ExpressionVisitor, which is cumbersome and may or may not end up fixing your problem.

根据代码的结构方式,一种解决方法可能是通过首先传入产生该表达式的内容来两次重现原始表达式树:

Depending on how your code is structured, one workaround may be to reproduce the original expression tree twice, by passing in whatever produces that expression in the first place:

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,看来它可能并不那么困难.看看是否可行:

Update

I just spent some time reading up on ExpressionVisitors, and it looks like it might not be that difficult after all. See if this works:

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(); 

这篇关于当我向查询两次添加相同的表达式时,为什么会收到此Linq to Nhibernate异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆