Loop to LINQ Conversion -
Asked Answered
O

4

6

Ok I have the following, set-up and working great. These lines of code should do a conversion from DAL Entity (Subsonic) to a ViewModel.

    IList<ProductOptionModel> OptionsRetData = new List<ProductOptionModel>();

    foreach (var CurProductOption in this.ProductOptions)
    {
        OptionsRetData.Add(CurProductOption.ToDataModel());
    }

    returnData.Options = OptionsRetData.AsEnumerable();

I'd like to convert this to a LINQ single line statment and came up with the following.

returnData.Options = this.ProductOptions.Select(o => o.ToDataModel());

and am recieving the following error.

Server Error in '/' Application.
Sequence contains no matching element 

So why does the first statment work but not the LINQ and, what steps can I take to resolve it.

Stack Trace

at System.Linq.Enumerable.First[TSource](IEnumerable1 source, Func2 predicate) at SubSonic.Extensions.Database.Load[T](IDataReader rdr, T item, List1 ColumnNames) at SubSonic.Extensions.Database.ToEnumerable[T](IDataReader rdr, List1 ColumnNames) at SubSonic.Linq.Structure.DbQueryProvider.Execute[T](QueryCommand1 query, Object[] paramValues) at lambda_method(Closure ) at SubSonic.Linq.Structure.DbQueryProvider.Execute(Expression expression) at SubSonic.Linq.Structure.Query1.GetEnumerator()

Maybe this is to do with subsonic?

Opportune answered 25/5, 2010 at 15:2 Comment(5)
What's the call stack of the exception?Along
What is the return type of ToDataModel()?Hootman
@Dave Swersky - Return type is ProductOptionModelOpportune
I dont think 'select' method throw any error. did you used any 'single' method?Palila
I also have gotten similar error. Double check if your return type is the same for Options collection and your ProductOptions is not nullUlrikeulster
K
7

One possibility is that it's not working because you've changed the time at which the query is materialized. Change the code to this instead:

returnData.Options = this.ProductOptions.Select(o => o.ToDataModel()).ToList();

That will force the query to be evaluated at the same time it was before.

EDIT: Your stack trace is showing First() being called somehow, but we haven't got anything about that in the code you've shown... any ideas where that's happening?

EDIT: I've realised the difference - and I'm foolish for not doing so before. You want to force the projection to be done in-process:

returnData.Options = this.ProductOptions
                         .AsEnumerable()
                         .Select(o => o.ToDataModel())
                         .ToList();

That extra call to AsEnumerable means it'll be the Enumerable.Select overload which gets called, making it equivalent to your original code.

Kortneykoruna answered 25/5, 2010 at 15:10 Comment(5)
@Jon SKeet - Thanks for the reply. Adding the .ToList() results int he same error. (Just on that line now rather than at the VIEW)Opportune
@Jon Skeet - Sneeky suspicion that this is to do with SubSonic. As I make no actual call to .First();Opportune
@Jon Skeet - There is a reason you have such a high rep. Thanks again, this worked. Is there anywhere I can read up a little more about what you have written?Opportune
@Pino: its weird. sorry for bad suggestionsPalila
@Palila dont be sorry it wasnt bad, i appriciate you trying to help!Opportune
P
2

As i said you're using First method. you may want to change it to FirstOrDefault. it will be solved. or do you able to change?

Stack Trace

at System.Linq.Enumerable.First

Palila answered 25/5, 2010 at 15:29 Comment(2)
as I said, I am not directly calling that. This seems to be deep in the subsonic files. Maybe thats causing the issue?Opportune
yep. its why this happening. edit. maybe using try catch statements'll fix this. did you tried?Palila
E
0
this.ProductOptions.Select(o => o.ToDataModel()).ToList<ProductOptionModel>();
Erato answered 25/5, 2010 at 15:11 Comment(1)
Same problem when using the example line.Opportune
E
-1

I think you have to check for the length of this.ProductOptions before the LINQ statement.

So maybe (revised without check for null):

returnData.Options = (this.ProductOptions.Length > 0) ? this.ProductOptions.Select(o => o.ToDataModel()) : new List<ProductOptionModel>().AsEnumerable();
Erato answered 25/5, 2010 at 15:22 Comment(2)
Maybe no need to check for null. The loop works because with length 0, the flow of the program never enters the loop.Erato
Select shouldn't fail if it doesn't get any values though... it should just yield an empty result.Kortneykoruna

© 2022 - 2024 — McMap. All rights reserved.