|
|
|
Forum Member
      
Group: Forum Members
Last Login: 2010-04-07 22:36:16
Posts: 32,
Visits: 78
|
|
| Hi all Does anybody have an idea how to use an enum in a linq expression ? I have a simple class, with one attribute DocType - of an enum type DocumentType { Office, Private} After creating the database, the ocl debugger knows everything about my DocumentType (knows all the values) I've tried to form a linq expression like: Class1 c = (from aClass in EcoSpace.PSQuery<Class1>() where (aClass.TypeOfDocument == DocumentType.Private) select aClass).FirstOrDefault(); When I try to run the application the following exception occurs: System.InvalidOperationException was unhandled by user code Message="ECO LINQ: Unhandled nodetype Convert in UnaryExpression" Source="Eco.LinqExtender" StackTrace: at Eco.Linq.EcoQuery`1.WalkExpression(Expression parentexpression, Expression expression, OclEnvironment env, Dictionary`2 lambdaParameters) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 426 at Eco.Linq.EcoQuery`1.WalkExpression(Expression parentexpression, Expression expression, OclEnvironment env, Dictionary`2 lambdaParameters) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 174 at Eco.Linq.EcoQuery`1.WalkExpression(Expression parentexpression, Expression expression, OclEnvironment env, Dictionary`2 lambdaParameters) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 278 at Eco.Linq.EcoQuery`1.WalkExpression(Expression parentexpression, Expression expression, OclEnvironment env, Dictionary`2 lambdaParameters) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 416 at Eco.Linq.EcoQuery`1.HandleIterator(Expression parentexpression, OclEnvironment env, Dictionary`2 lambdaParameters, MethodCallExpression methodCallExp, String iteratorName, TBoldOCLIteratorSpecifier iteratorType) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 493 at Eco.Linq.EcoQuery`1.WalkExpression(Expression parentexpression, Expression expression, OclEnvironment env, Dictionary`2 lambdaParameters) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 367 at Eco.Linq.EcoQuery`1.CreateQuery[S](Expression expression) in e:\dev\fbuild\source\Eco\Eco.Linq\EcoQuery.cs:line 532 at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate) at EcoLinqBug.Form1.button1_Click(Object sender, EventArgs e) in C:\TestLab\EcoLinqBug\EcoLinqBug\Form1.cs:line 45 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativewindow.WndProc(Message& m) at System.Windows.Forms.Nativewindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) InnerException: Am I doing something wrong or is it a bug ? What I can find on the net, implies that this is a valid expression, but I might miss something. Could someone please verify ? Thnx - Per
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: Today @ 20:20:07
Posts: 241,
Visits: 7 537
|
|
| That looks like an enum conversion bug to me - for whatever that is worth. Do you know how to add issues in Mantis? I mostly added this post to remind you that .FirstOrDefault() only works if you add .ToArray() before it (more info).
Rick Weyrauch
|
|
|
|
|
Forum Member
      
Group: Forum Members
Last Login: 2010-04-07 22:36:16
Posts: 32,
Visits: 78
|
|
| Thnx, I've reported it in mantis #861. My example works fine with FirstOrDefault() (odd, if it did not work for you), because if the query return an empty result (ie. null) the call throws an exception. Per
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: Today @ 20:20:07
Posts: 241,
Visits: 7 537
|
|
I will have to try and run my test code again tomorrow. What build number are you running?
Rick Weyrauch
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: Today @ 20:20:07
Posts: 241,
Visits: 7 537
|
|
Well, my test still fails at the second Assert. The first Assert is to verify there was at least one Class3 with Option == 100.[ Test]public void FirstOrDefault(){ var es = new NotDerivedSettableEcoSpace { Active = true }; var class3 = (from c3 in es.PSQuery<Class3>() where c3.Option == 100 select c3).ToArray().FirstOrDefault(); Assert.That(class3, Is.Not.Null); class3 = ( from c3 in es.PSQuery<Class3>() where c3.Option == 100 select c3).FirstOrDefault(); Assert.That(class3, Is.Not.Null);}
Rick Weyrauch
|
|
|
|
|
Forum Member
      
Group: Forum Members
Last Login: 2010-04-07 22:36:16
Posts: 32,
Visits: 78
|
|
| Thats odd. The FirstOrDefault() works for me. I'm using build 5.0.0.4560
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: Today @ 20:20:07
Posts: 241,
Visits: 7 537
|
|
Odd indeed becuase this does not seem to work either:
if (ecospace.PSQuery<Vintage>().FirstOrDefault(v => v.Year == year) != null) throw new ArgumentOutOfRangeException("year", string.Format("Unable to create new vintage for {0} - Duplicate!", year));
If I call this 3 times in a row, with UpdateDatabase() in between of course, it never tosses the exception.
Rick Weyrauch
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: Today @ 20:20:07
Posts: 241,
Visits: 7 537
|
|
| Ok, I got to the bottom of it. There are two pathways for the Linq to follow on a PSQuery<T> returned object: IQueryable<T> and IEnumerable<T>. The IEnumerable<T> path works and the IQueryable<T> does not. This version of my last post works: if ( ((IEnumerable<Vintage> )ecospace.PSQuery<Vintage>().Where(v => v.Year == year)).FirstOrDefault() != null) throw new ArgumentOutOfRangeException("year", string.Format("Unable to create new vintage for {0} - Duplicate!", year));
I beleive this is true for all of the Element Operators and Aggregation Operators but I do not know that for sure. What are the chances that you are using a cast to IEnumerable as part of your route to FirstOrDefault()?
Rick Weyrauch
|
|
|
|
|
Forum Member
      
Group: Forum Members
Last Login: 2010-04-07 22:36:16
Posts: 32,
Visits: 78
|
|
| Hi Rick Yep, thats it. I'd tried a lot of examples from microsoft's website, and one of those examples did indeed contain a type cast to IEnumerable. Other places in the code where I'd tried the FirstOrDefault(), failed miserably! Lesson learned - When reading my own code, be more careful  thnx for your insight. Per
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: 2011-07-14 17:05:00
Posts: 290,
Visits: 2 617
|
|
RickWeyrauch (2009-10-29)
Ok, I got to the bottom of it. There are two pathways for the Linq to follow on a PSQuery<T> returned object: IQueryable<T> and IEnumerable<T>. The IEnumerable<T> path works and the IQueryable<T> does not. This version of my last post works:
if ( ((IEnumerable<Vintage> )ecospace.PSQuery<Vintage>().Where(v => v.Year == year)).FirstOrDefault() != null)
throw new ArgumentOutOfRangeException("year", string.Format("Unable to create new vintage for {0} - Duplicate!", year));
I beleive thisis true for all of the Element Operators and Aggregation Operatorsbut I do not know that for sure.
What are the chances that you are using a cast to IEnumerable as part of your route to FirstOrDefault()?
You should still report this on mantis.
====
Pete
|
|
|
|